Beispiel #1
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);
}
Beispiel #2
0
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();
}