예제 #1
0
bullet::Collider::Ptr
bullet::Collider::linearFactor(Vector3::Ptr values)
{
    const bool changed = fabsf(values->x() - _linearFactor->x()) > 1e-3f
                         || fabsf(values->y() - _linearFactor->y()) > 1e-3f
                         || fabsf(values->z() - _linearFactor->z()) > 1e-3f;

    _linearFactor->copyFrom(values);

    if (changed)
        _propertiesChanged->execute(std::static_pointer_cast<Collider>(shared_from_this()));

    return std::static_pointer_cast<Collider>(shared_from_this());
}
예제 #2
0
void
Matrix4x4::decompose(Vector3::Ptr        translation,
                     Quaternion::Ptr    rotation,
                     Vector3::Ptr        scaling) const
{
    static auto matrixR = Matrix4x4::create();

    decomposeQR(rotation, matrixR);

    const std::vector<float>& matR = matrixR->_m;
    scaling->setTo(matR[0], matR[5], matR[10]);

#ifdef DEBUG
    if (fabsf(matR[1]) > 1e-3f || fabsf(matR[2]) > 1e-3f || fabsf(matR[6]) > 1e-3f)
        std::cout << "Warning: Matrix decomposition assumes the following composition order : scaling, rotation, and translation." << std::endl;
#endif // DEBUG

    translation->setTo(_m[3], _m[7], _m[11]);
}
예제 #3
0
Vector3::Ptr
bullet::PhysicsWorld::getColliderAngularVelocity(Collider::ConstPtr    collider,
                                                 Vector3::Ptr        output) const
{
    if (output == nullptr)
        output = Vector3::create(0.0f, 0.0f, 0.0f);

    auto foundColliderIt = _colliderMap.find(std::const_pointer_cast<Collider>(collider));
    if (foundColliderIt == _colliderMap.end())
        return output;

    auto rigidBody    = foundColliderIt->second->rigidBody();
    auto vec        = rigidBody->getAngularVelocity();

    return output->setTo(vec.x(), vec.y(), vec.z());
}
예제 #4
0
void
Geometry::getHitNormal(uint triangle, Vector3::Ptr hitNormal)
{
	auto normalBuffer = vertexBuffer("normal");
	auto& normalData = normalBuffer->data();
	auto normalPtr = &normalData[0];
	auto normalVertexSize = normalBuffer->vertexSize();
	auto normalOffset = std::get<2>(*normalBuffer->attribute("normal"));
	auto& indicesData = _indexBuffer->data();

	auto v0 = Vector3::create(normalPtr + indicesData[triangle] * normalVertexSize + normalOffset);
	auto v1 = Vector3::create(normalPtr + indicesData[triangle] * normalVertexSize + normalOffset);
	auto v2 = Vector3::create(normalPtr + indicesData[triangle] * normalVertexSize + normalOffset);

	auto edge1 = Vector3::create(v1)->subtract(v0)->normalize();
	auto edge2 = Vector3::create(v2)->subtract(v0)->normalize();

	hitNormal->copyFrom(edge2)->cross(edge1);
}
예제 #5
0
파일: main.cpp 프로젝트: 382309009/minko
int
main(int argc, char** argv)
{
    auto canvas         = Canvas::create("Minko Example - Leap Motion");

    // scene set-up
    auto sceneManager   = SceneManager::create(canvas);

    auto sceneNode      = Node::create("engine")
        ->addComponent(Transform::create());

    auto cameraNode     = Node::create("cameraNode")
        ->addComponent(Transform::create());

    // Leap Motion-based controls
    auto controller     = input::leap::Controller::create(canvas);

    const float        MIN_DELTA_HAND_DISTANCE    = 5.0f;
    const float        RELATIVE_MOVE_THRESHOLD    = 1.0f;
    const clock_t      START_CLOCK                = clock();

    // frame-persistant variables
    float    relativeMove              = 0.0f;
    auto     swipeDirection            = Vector3::create();

    float    goalExplosionValue        = 1.0f;
    float    goalCosRotation           = 1.0f;
    float    goalSinRotation           = 0.0f;
    float    goalCameraDistance        = 20.0f;

    float    explosionValue            = goalExplosionValue;
    float    cosRotation               = goalCosRotation;
    float    sinRotation               = goalSinRotation;
    float    cameraDistance            = goalCameraDistance;

    float    previousHandDistance      = -1.0f;
    float    previousTime              = 0.0f;
    float    previousExplosionValue    = explosionValue;

    bool     isInProgress              = false;

    auto leapEnterFrame = controller->enterFrame()->connect([&](input::leap::Controller::Ptr c)
    {
        if (!c->frame()->isValid())
            return;

        const float currentTime    = (clock() - START_CLOCK) / float(CLOCKS_PER_SEC);
        const float deltaTime      = currentTime - previousTime;
        previousTime               = currentTime;

        auto   frame               = c->frame();
        auto   leftHand            = frame->leftmostHand();
        auto   rightHand           = frame->rightmostHand();
        float  handDistance        = 0.0f;

        if (frame->numHands() >= 2)
        {
            if (leftHand->isValid() && rightHand->isValid())
                handDistance = (leftHand->palmPosition() - rightHand->palmPosition())->length();

            if (previousHandDistance < 0.0f)
                previousHandDistance = handDistance;

            const float deltaHandDistance = fabsf(handDistance - previousHandDistance);

            if (deltaHandDistance > MIN_DELTA_HAND_DISTANCE)
            {
                const float moveIncr = handDistance < previousHandDistance ? -10.0f : 10.0f;
                relativeMove += moveIncr * deltaTime;
            }

            previousHandDistance = handDistance;

            const float moveDecr = relativeMove > 0.0f ? 0.5f : -0.5f;
            relativeMove -= moveDecr * deltaTime;

            if (!isInProgress)
            {
                if (relativeMove > RELATIVE_MOVE_THRESHOLD)
                {
                    isInProgress        = true;
                    goalExplosionValue  = 3.5f;
                    relativeMove        = 0.0f;
#ifdef DEBUG
                    std::cout << "spread mesh" << std::endl;
#endif // DEBUG
                }
                else if (relativeMove < -RELATIVE_MOVE_THRESHOLD)
                {
                    isInProgress        = true;
                    goalExplosionValue  = 1.0f;
                    relativeMove        = 0.0f;
#ifdef DEBUG
                    std::cout << "restore mesh" << std::endl;
#endif // DEBUG
                }
            }
        }
        else
        {
            // consider only the swipe gesture whose direction exhibits the strongest magnitude
            const uint     numGestures         = frame->numGestures();
            Vector3::Ptr   swipeDirection      = Vector3::create();
            Vector3::Ptr   bestSwipeDirection  = Vector3::create();

            for (uint i = 0; i < numGestures; ++i)
            {
                auto gesture = frame->gestureByIndex(i);

                if (gesture->type() == input::leap::Gesture::Type::Swipe &&
                    gesture->state() == input::leap::Gesture::State::Start)
                {
                    gesture->toSwipeGesture()->direction(swipeDirection);

                    if (swipeDirection->lengthSquared() > bestSwipeDirection->lengthSquared())
                        bestSwipeDirection->copyFrom(swipeDirection);
                }
            }

#ifdef DEBUG
            if (bestSwipeDirection->lengthSquared() > 0.1f)
                std::cout << "starting swipe direction = " << bestSwipeDirection->toString() << std::endl;
#endif // DEBUG

            if (!isInProgress && bestSwipeDirection->lengthSquared() > 0.1f)
            {
                if (fabsf(swipeDirection->y()) > 0.5f)
                {
                    isInProgress       = true;
                    goalCameraDistance = swipeDirection->y() < 0.0f ? 10.0f : 20.0f;
#ifdef DEBUG
                    std::cout << "\t-> zoom in/out\tgoal camera distance = " << goalCameraDistance << std::endl;
#endif // DEBUG
                }
                else if (fabsf(swipeDirection->x()) > 0.5f)
                {
                    const float goalRotation = atan2f(goalSinRotation, goalCosRotation) +
                        (swipeDirection->x() < 0.0f ? float(M_PI) * 0.25f : - float(M_PI) * 0.25f);

                    isInProgress       = true;
                    goalCosRotation    = cosf(goalRotation);
                    goalSinRotation    = sinf(goalRotation);
#ifdef DEBUG
                    std::cout << "\t-> new rotation angle = " << 180.0f * goalRotation / float(M_PI) << std::endl;
#endif // DEBUG
                }
            }
        }

        const float diffExplosionValue     = goalExplosionValue - explosionValue;
        const float diffCameraDistance     = goalCameraDistance - cameraDistance;
        const float diffCosRotation        = goalCosRotation - cosRotation;
        const float diffSinRotation        = goalSinRotation - sinRotation;

        if (fabsf(diffExplosionValue) < 0.01f &&
            fabsf(diffCameraDistance) < 0.01f &&
            fabsf(diffCosRotation) < 0.01f &&
            fabsf(diffSinRotation) < 0.01f)
        {
#ifdef DEBUG
            if (isInProgress)
                std::cout << "current motion ended" << std::endl;
#endif // DEBUG

            explosionValue     = goalExplosionValue;
            cameraDistance     = goalCameraDistance;
            cosRotation        = goalCosRotation;
            sinRotation        = goalSinRotation;

            isInProgress       = false;
        }

        explosionValue     += diffExplosionValue   * std::min(1.0f, 2.0f * deltaTime);
        cameraDistance     += diffCameraDistance   * std::min(1.0f, 2.5f * deltaTime);
        cosRotation        += diffCosRotation      * std::min(1.0f, 3.0f * deltaTime);
        sinRotation        += diffSinRotation      * std::min(1.0f, 3.0f * deltaTime);

        explodeModel(
            explosionValue,
            previousExplosionValue,
            sceneNode
        );

        previousExplosionValue    = explosionValue;

        placeCamera(
            cameraDistance,
            atan2f(sinRotation, cosRotation),
            cameraNode->component<Transform>()->matrix()
        );
    });

    // on initialization of the Leap controller
    auto leapConnected = controller->connected()->connect([](input::leap::Controller::Ptr c)
    {
        c->enableGesture(input::leap::Gesture::Type::ScreenTap);
        c->enableGesture(input::leap::Gesture::Type::Swipe);

#ifdef DEBUG
        std::cout << "Leap controller connected (screentap and swipe gestures enabled)" << std::endl;
#endif // DEBUG

        std::cout << "Leap controls\n-------------" << std::endl;
        std::cout << "\t- Single hand controls\n\t\t- Horizontal swipe\tturn camera\n\t\t- Vertical swipe\tzoom in/out" << std::endl;
        std::cout << "\t- Two hand controls\n\t\t- Brisk spreading motion\texplose model\n\t\t- Brisk shrinking motion\trestore model" << std::endl;
    });


    auto root                = Node::create("root");

    // setup assets
    auto defaultMaterial    = Material::create()
        ->set("diffuseColor", Vector4::create(1.f, 1.f, 1.f, 1.f))
        ->set("triangleCulling", render::TriangleCulling::NONE);

    sceneManager->assets()->context()->errorsEnabled(true);

    sceneManager->assets()->loader()->options()
        ->registerParser<file::PNGParser>("png")
        ->registerParser<file::SceneParser>("scene")
        ->generateMipmaps(false)
        ->material(std::static_pointer_cast<Material>(
            Material::create()->set("triangleCulling", render::TriangleCulling::NONE)
        ))
        ->materialFunction([&](const std::string&, Material::Ptr)
    {
        return std::static_pointer_cast<Material>(defaultMaterial);
    });

    sceneManager->assets()
        ->geometry("cube",     geometry::CubeGeometry::create(sceneManager->assets()->context()))
        ->geometry("sphere",   geometry::SphereGeometry::create(sceneManager->assets()->context()))
        ->geometry("skybox",   geometry::SphereGeometry::create(sceneManager->assets()->context(), 80, 80, true));

    sceneManager->assets()->loader()
        ->queue(HANGAR_TEXTURE)
        ->queue("effect/Phong.effect")
        ->queue("effect/Basic.effect")
        ->queue(SCENE_NAME);

    sceneManager->assets()->loader()->options()
        ->effect(sceneManager->assets()->effect("effect/Phong.effect"));

    cameraNode
        ->addComponent(PerspectiveCamera::create(canvas->aspectRatio()))
        ->addComponent(Renderer::create(0x7F7F7FFF));

    placeCamera(
        cameraDistance,
        atan2f(sinRotation, cosRotation),
        cameraNode->component<Transform>()->matrix()
    );

    auto dirLight = Node::create("dirLight")
        ->addComponent(component::DirectionalLight::create())
        ->addComponent(component::Transform::create(
            Matrix4x4::create()->lookAt(Vector3::zero(), Vector3::create(-1.0f, -1.0f, -1.0f))
        ));

    auto pointLight = Node::create("pointLight")
        ->addComponent(component::PointLight::create())
        ->addComponent(component::Transform::create(
            Matrix4x4::create()->appendTranslation(0.0f, 10.0f, 0.0f)
        ));

    pointLight->component<PointLight>()->color()->setTo(1.0f, 1.0f, 1.0f);

    auto skybox = Node::create("skybox")
        ->addComponent(Transform::create(
            Matrix4x4::create()->appendScale(60.0f, 60.0f, 60.0f)
        ));

    root
        ->addChild(cameraNode)
        ->addChild(dirLight)
        ->addChild(pointLight)
        ->addComponent(sceneManager);

    auto _ = sceneManager->assets()->loader()->complete()->connect([=](file::Loader::Ptr loader)
    {
        sceneNode->addChild(sceneManager->assets()->symbol(SCENE_NAME));

        skybox->addComponent(Surface::create(
            sceneManager->assets()->geometry("skybox"),
            BasicMaterial::create()
                ->diffuseColor(Vector4::create(1.0f, 0.0f, 0.0f, 1.0f))
                ->diffuseMap(sceneManager->assets()->texture(HANGAR_TEXTURE))
                ->triangleCulling(render::TriangleCulling::FRONT),
            sceneManager->assets()->effect("effect/Basic.effect")
        ));

        root
            ->addChild(dirLight)
            ->addChild(pointLight)
            ->addChild(skybox)
            ->addChild(cameraNode)
            ->addChild(sceneNode);
    });

    auto resized = canvas->resized()->connect([&](AbstractCanvas::Ptr canvas, uint w, uint h)
    {
        cameraNode->component<PerspectiveCamera>()->aspectRatio(float(w) / float(h));
    });

    auto enterFrame = canvas->enterFrame()->connect([&](Canvas::Ptr canvas, float time, float deltaTime)
    {
        sceneManager->nextFrame(time, deltaTime);
    });

    controller->start();
    sceneManager->assets()->loader()->load();
    canvas->run();
}
예제 #6
0
Geometry::Ptr
Geometry::computeTangentSpace(bool doNormals)
{
	const unsigned int numVertices = this->numVertices();

	if (numVertices == 0)
		return shared_from_this();

	if (!_data->hasProperty("position") 
		|| !_data->hasProperty("uv"))
		throw std::logic_error("Computation of tangent space requires positions and uv.");

	if (doNormals)
		computeNormals();

	const std::vector<unsigned short>& indices (this->indices()->data());
	const unsigned int numFaces = indices.size() / 3;

	unsigned short vertexIds[3] = { 0, 0, 0 };
	std::vector<Vector3::Ptr> xyz(3);
	std::vector<Vector2::Ptr> uv(3);

	VertexBuffer::Ptr xyzBuffer			= _data->get<VertexBuffer::Ptr>("position");
	const unsigned int xyzSize			= xyzBuffer->vertexSize();
	const unsigned int xyzOffset		= std::get<2>(*xyzBuffer->attribute("position"));
	const std::vector<float>& xyzData	= xyzBuffer->data();

	VertexBuffer::Ptr uvBuffer			= _data->get<VertexBuffer::Ptr>("uv");
	const unsigned int uvSize			= uvBuffer->vertexSize();
	const unsigned int uvOffset			= std::get<2>(*uvBuffer->attribute("uv"));
	const std::vector<float>& uvData	= uvBuffer->data();

	std::vector<float> tangentsData(3 * numVertices, 0.0f);

	for (unsigned int i = 0, offset = 0; i < numFaces; ++i)
	{
		for (unsigned int k = 0; k < 3; ++k)
		{
			vertexIds[k] = indices[offset++];
			unsigned int index = xyzOffset + vertexIds[k] * xyzSize;
			xyz[k] = Vector3::create(xyzData[index], xyzData[index + 1], xyzData[index + 2]);
			index = uvOffset + vertexIds[k] * uvSize;
			uv[k] = Vector2::create(uvData[index], uvData[index + 1]);
		}

		Vector2::Ptr uv02		= uv[0] - uv[2];
		Vector2::Ptr uv12		= uv[1] - uv[2];
		const float denom		= uv02->x() * uv12->y() - uv12->x() * uv02->y();
		const float invDenom	= fabsf(denom) > 1e-6f ? 1.0f/denom : 1.0f;

		Vector3::Ptr faceTangent = ((xyz[0]-xyz[2]) * uv12->y() - (xyz[1]-xyz[2]) * uv02->y()) * invDenom;

		for (unsigned int k=0; k<3; ++k)
		{
			const unsigned int index = 3 * vertexIds[k];

			tangentsData[index]		+= faceTangent->x();
			tangentsData[index + 1]	+= faceTangent->y();
			tangentsData[index + 2]	+= faceTangent->z();
		}
	}

	for (unsigned int i = 0, index = 0; i < numVertices; ++i, index += 3)
	{
		const float x				= tangentsData[index];
		const float y				= tangentsData[index + 1];
		const float z				= tangentsData[index + 2];
		const float lengthSquared	= x * x + y * y + z * z;
		const float invLength		= lengthSquared > 1e-6f ? 1.0f / sqrtf(lengthSquared) : 1.0f;

		tangentsData[index]		*= invLength;
		tangentsData[index + 1]	*= invLength;
		tangentsData[index + 2]	*= invLength;
	}

	VertexBuffer::Ptr tangentsBuffer = VertexBuffer::create(xyzBuffer->context(), tangentsData);
	tangentsBuffer->addAttribute("tangent", 3, 0);
	addVertexBuffer(tangentsBuffer);

	return shared_from_this();
}
예제 #7
0
Geometry::Ptr
Geometry::computeNormals()
{
	const unsigned int numVertices = this->numVertices();

	if (numVertices == 0)
		return shared_from_this();

	if (_data->hasProperty("normal"))
		throw std::logic_error("The geometry already stores precomputed normals.");
		
	if (!_data->hasProperty("position"))
		throw std::logic_error("Computation of normals requires positions.");

	const std::vector<unsigned short>& indices	= this->indices()->data();
	const unsigned int numFaces					= indices.size() / 3;

	unsigned short vertexIds[3] = { 0, 0, 0 };
	std::vector<Vector3::Ptr> xyz(3);

	VertexBuffer::Ptr xyzBuffer			= _data->get<VertexBuffer::Ptr>("position");
	const unsigned int xyzSize			= xyzBuffer->vertexSize();
	const unsigned int xyzOffset		= std::get<2>(*xyzBuffer->attribute("position"));
	const std::vector<float>& xyzData	= xyzBuffer->data();

	std::vector<float> normalsData(3 * numVertices, 0.0f);

	for (unsigned int i = 0, offset = 0; i < numFaces; ++i)
	{
		for (unsigned int k = 0; k < 3; ++k)
		{
			vertexIds[k] = indices[offset++];
			const unsigned int index = xyzOffset + vertexIds[k] * xyzSize;
			xyz[k] = Vector3::create(xyzData[index], xyzData[index + 1], xyzData[index + 2]);
		}

		Vector3::Ptr faceNormal = Vector3::create()
			->copyFrom(xyz[0] - xyz[1])
			->cross(xyz[0] - xyz[2]);

 		for (unsigned int k = 0; k < 3; ++k)
		{
			const unsigned int index = 3 * vertexIds[k];

			normalsData[index]		+= faceNormal->x();
			normalsData[index + 1]	+= faceNormal->y();
			normalsData[index + 2]	+= faceNormal->z();
		}
	}

	for (unsigned int i = 0, index = 0; i < numVertices; ++i, index += 3)
	{
		const float x				= normalsData[index];
		const float y				= normalsData[index + 1];
		const float z				= normalsData[index + 2];
		const float lengthSquared	= x * x + y * y + z * z;
		const float invLength		= lengthSquared > 1e-6f ? 1.0f / sqrtf(lengthSquared) : 1.0f;

		normalsData[index]		*= invLength;
		normalsData[index + 1]	*= invLength;
		normalsData[index + 2]	*= invLength;
	}

	VertexBuffer::Ptr normalsBuffer = VertexBuffer::create(xyzBuffer->context(), normalsData);
	normalsBuffer->addAttribute("normal", 3, 0);
	addVertexBuffer(normalsBuffer);

	return shared_from_this();
}
예제 #8
0
			inline
			void
			copyTranslation(Vector3::Ptr t)
			{
				t->setTo(_m[3], _m[7], _m[11]);
			}
예제 #9
0
void
bullet::PhysicsWorld::setGravity(Vector3::Ptr gravity)
{
    _bulletDynamicsWorld->setGravity(btVector3(gravity->x(), gravity->y(), gravity->z()));
}