void SignedDistanceFieldText::CreateScene()
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();

    scene_ = new Scene(context_);

    // Create the Octree component to the scene. This is required before adding any drawable components, or else nothing will
    // show up. The default octree volume will be from (-1000, -1000, -1000) to (1000, 1000, 1000) in world coordinates; it
    // is also legal to place objects outside the volume but their visibility can then not be checked in a hierarchically
    // optimizing manner
    scene_->CreateComponent<Octree>();

    // Create a child scene node (at world origin) and a StaticModel component into it. Set the StaticModel to show a simple
    // plane mesh with a "stone" material. Note that naming the scene nodes is optional. Scale the scene node larger
    // (100 x 100 world units)
    Node* planeNode = scene_->CreateChild("Plane");
    planeNode->SetScale(Vector3(100.0f, 1.0f, 100.0f));
    StaticModel* planeObject = planeNode->CreateComponent<StaticModel>();
    planeObject->SetModel(cache->GetResource<Model>("Models/Plane.mdl"));
    planeObject->SetMaterial(cache->GetResource<Material>("Materials/StoneTiled.xml"));

    // Create a directional light to the world so that we can see something. The light scene node's orientation controls the
    // light direction; we will use the SetDirection() function which calculates the orientation from a forward direction vector.
    // The light will use default settings (white light, no shadows)
    Node* lightNode = scene_->CreateChild("DirectionalLight");
    lightNode->SetDirection(Vector3(0.6f, -1.0f, 0.8f)); // The direction vector does not need to be normalized
    Light* light = lightNode->CreateComponent<Light>();
    light->SetLightType(LIGHT_DIRECTIONAL);

    // Create more StaticModel objects to the scene, randomly positioned, rotated and scaled. For rotation, we construct a
    // quaternion from Euler angles where the Y angle (rotation about the Y axis) is randomized. The mushroom model contains
    // LOD levels, so the StaticModel component will automatically select the LOD level according to the view distance (you'll
    // see the model get simpler as it moves further away). Finally, rendering a large number of the same object with the
    // same material allows instancing to be used, if the GPU supports it. This reduces the amount of CPU work in rendering the
    // scene.
    const unsigned NUM_OBJECTS = 200;
    for (unsigned i = 0; i < NUM_OBJECTS; ++i)
    {
        Node* mushroomNode = scene_->CreateChild("Mushroom");
        mushroomNode->SetPosition(Vector3(Random(90.0f) - 45.0f, 0.0f, Random(90.0f) - 45.0f));
        mushroomNode->SetScale(0.5f + Random(2.0f));
        StaticModel* mushroomObject = mushroomNode->CreateComponent<StaticModel>();
        mushroomObject->SetModel(cache->GetResource<Model>("Models/Mushroom.mdl"));
        mushroomObject->SetMaterial(cache->GetResource<Material>("Materials/Mushroom.xml"));

        Node* mushroomTitleNode = mushroomNode->CreateChild("MushroomTitle");
        mushroomTitleNode->SetPosition(Vector3(0.0f, 1.2f, 0.0f));
        Text3D* mushroomTitleText = mushroomTitleNode->CreateComponent<Text3D>();
        mushroomTitleText->SetText("Mushroom " + String(i));
        mushroomTitleText->SetFont(cache->GetResource<Font>("Fonts/BlueHighway.sdf"), 24);

        mushroomTitleText->SetColor(Color::RED);
        
        if (i % 3 == 1)
        {
            mushroomTitleText->SetColor(Color::GREEN);
            mushroomTitleText->SetTextEffect(TE_SHADOW);
            mushroomTitleText->SetEffectColor(Color(0.5f, 0.5f, 0.5f));
        }
        else if (i % 3 == 2)
        {
            mushroomTitleText->SetColor(Color::YELLOW);
            mushroomTitleText->SetTextEffect(TE_STROKE);
            mushroomTitleText->SetEffectColor(Color(0.5f, 0.5f, 0.5f));
        }

        mushroomTitleText->SetAlignment(HA_CENTER, VA_CENTER);
    }

    // Create a scene node for the camera, which we will move around
    // The camera will use default settings (1000 far clip distance, 45 degrees FOV, set aspect ratio automatically)
    cameraNode_ = scene_->CreateChild("Camera");
    cameraNode_->CreateComponent<Camera>();

    // Set an initial position for the camera scene node above the plane
    cameraNode_->SetPosition(Vector3(0.0f, 5.0f, 0.0f));
}
void PrefabImporter::HandlePrefabSave(StringHash eventType, VariantMap& eventData)
{
    using namespace PrefabSave;

    PrefabComponent* component = static_cast<PrefabComponent*>(eventData[P_PREFABCOMPONENT].GetPtr());

    if (component->GetPrefabGUID() != asset_->GetGUID())
        return;

    Node* node = component->GetNode();

    if (!node)
        return;

    // flip temporary root children and components to not be temporary for save
    const Vector<SharedPtr<Component>>& rootComponents = node->GetComponents();
    const Vector<SharedPtr<Node> >& children = node->GetChildren();

    PODVector<Component*> tempComponents;
    PODVector<Node*> tempChildren;
    PODVector<Node*> filterNodes;

    for (unsigned i = 0; i < rootComponents.Size(); i++)
    {
        if (rootComponents[i]->IsTemporary())
        {
            rootComponents[i]->SetTemporary(false);
            tempComponents.Push(rootComponents[i]);

            // Animated sprites contain a temporary node we don't want to save in the prefab
            // it would be nice if this was general purpose because have to test this when
            // breaking node as well
            if (rootComponents[i]->GetType() == AnimatedSprite2D::GetTypeStatic())
            {
                AnimatedSprite2D* asprite = (AnimatedSprite2D*) rootComponents[i].Get();
                if (asprite->GetRootNode())
                    filterNodes.Push(asprite->GetRootNode());
            }

        }
    }

    for (unsigned i = 0; i < children.Size(); i++)
    {
        if (filterNodes.Contains(children[i].Get()))
            continue;

        if (children[i]->IsTemporary())
        {
            children[i]->SetTemporary(false);
            tempChildren.Push(children[i]);
        }
    }

    // store original transform
    Vector3 pos = node->GetPosition();
    Quaternion rot = node->GetRotation();
    Vector3 scale = node->GetScale();

    node->SetPosition(Vector3::ZERO);
    node->SetRotation(Quaternion::IDENTITY);
    node->SetScale(Vector3::ONE);

    component->SetTemporary(true);

    SharedPtr<File> file(new File(context_, asset_->GetPath(), FILE_WRITE));
    node->SaveXML(*file);
    file->Close();

    component->SetTemporary(false);

    // restore
    node->SetPosition(pos);
    node->SetRotation(rot);
    node->SetScale(scale);

    for (unsigned i = 0; i < tempComponents.Size(); i++)
    {
        tempComponents[i]->SetTemporary(true);
    }

    for (unsigned i = 0; i < tempChildren.Size(); i++)
    {
        tempChildren[i]->SetTemporary(true);
    }


    FileSystem* fs = GetSubsystem<FileSystem>();
    fs->Copy(asset_->GetPath(), asset_->GetCachePath());

    // reload it immediately so it is ready for use
    // TODO: The resource cache is reloading after this reload due to catching the file cache
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    XMLFile* xmlfile = cache->GetResource<XMLFile>(asset_->GetGUID());
    cache->ReloadResource(xmlfile);

    VariantMap changedData;
    changedData[PrefabChanged::P_GUID] = asset_->GetGUID();
    SendEvent(E_PREFABCHANGED, changedData);

}
Example #3
0
void AnimationState::ApplyTrack(AnimationStateTrack& stateTrack, float weight, bool silent)
{
    const AnimationTrack* track = stateTrack.track_;
    Node* node = stateTrack.node_;

    if (track->keyFrames_.Empty() || !node)
        return;

    unsigned& frame = stateTrack.keyFrame_;
    track->GetKeyFrameIndex(time_, frame);

    // Check if next frame to interpolate to is valid, or if wrapping is needed (looping animation only)
    unsigned nextFrame = frame + 1;
    bool interpolate = true;
    if (nextFrame >= track->keyFrames_.Size())
    {
        if (!looped_)
        {
            nextFrame = frame;
            interpolate = false;
        }
        else
            nextFrame = 0;
    }

    const AnimationKeyFrame* keyFrame = &track->keyFrames_[frame];
    unsigned char channelMask = track->channelMask_;

    Vector3 newPosition;
    Quaternion newRotation;
    Vector3 newScale;

    if (interpolate)
    {
        const AnimationKeyFrame* nextKeyFrame = &track->keyFrames_[nextFrame];
        float timeInterval = nextKeyFrame->time_ - keyFrame->time_;
        if (timeInterval < 0.0f)
            timeInterval += animation_->GetLength();
        float t = timeInterval > 0.0f ? (time_ - keyFrame->time_) / timeInterval : 1.0f;

        if (channelMask & CHANNEL_POSITION)
            newPosition = keyFrame->position_.Lerp(nextKeyFrame->position_, t);
        if (channelMask & CHANNEL_ROTATION)
            newRotation = keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t);
        if (channelMask & CHANNEL_SCALE)
            newScale = keyFrame->scale_.Lerp(nextKeyFrame->scale_, t);
    }
    else
    {
        if (channelMask & CHANNEL_POSITION)
            newPosition = keyFrame->position_;
        if (channelMask & CHANNEL_ROTATION)
            newRotation = keyFrame->rotation_;
        if (channelMask & CHANNEL_SCALE)
            newScale = keyFrame->scale_;
    }
    
    if (blendingMode_ == ABM_ADDITIVE) // not ABM_LERP
    {
        if (channelMask & CHANNEL_POSITION)
        {
            Vector3 delta = newPosition - stateTrack.bone_->initialPosition_;
            newPosition = node->GetPosition() + delta * weight;
        }
        if (channelMask & CHANNEL_ROTATION)
        {
            Quaternion delta = newRotation * stateTrack.bone_->initialRotation_.Inverse();
            newRotation = (delta * node->GetRotation()).Normalized();
            if (!Equals(weight, 1.0f))
                newRotation = node->GetRotation().Slerp(newRotation, weight);
        }
        if (channelMask & CHANNEL_SCALE)
        {
            Vector3 delta = newScale - stateTrack.bone_->initialScale_;
            newScale = node->GetScale() + delta * weight;
        }
    }
    else
    {
        if (!Equals(weight, 1.0f)) // not full weight
        {
            if (channelMask & CHANNEL_POSITION)
                newPosition = node->GetPosition().Lerp(newPosition, weight);
            if (channelMask & CHANNEL_ROTATION)
                newRotation = node->GetRotation().Slerp(newRotation, weight);
            if (channelMask & CHANNEL_SCALE)
                newScale = node->GetScale().Lerp(newScale, weight);
        }
    }
    
    if (silent)
    {
        if (channelMask & CHANNEL_POSITION)
            node->SetPositionSilent(newPosition);
        if (channelMask & CHANNEL_ROTATION)
            node->SetRotationSilent(newRotation);
        if (channelMask & CHANNEL_SCALE)
            node->SetScaleSilent(newScale);
    }
    else
    {
        if (channelMask & CHANNEL_POSITION)
            node->SetPosition(newPosition);
        if (channelMask & CHANNEL_ROTATION)
            node->SetRotation(newRotation);
        if (channelMask & CHANNEL_SCALE)
            node->SetScale(newScale);
    }
}
void AnimatedSprite2D::UpdateAnimation(float timeStep)
{
    if (!animation_)
        return;

    currentTime_ += timeStep * speed_;

    float time;
    float animationLength = animation_->GetLength();

    if (looped_)
    {
        time = fmodf(currentTime_, animationLength);
        if (time < 0.0f)
            time += animation_->GetLength();
    }
    else
        time = Clamp(currentTime_, 0.0f, animationLength);

    for (unsigned i = 0; i < numTracks_; ++i)
    {
        trackNodeInfos_[i].worldSpace = false;
        
        const AnimationTrack2D& track = animation_->GetTrack(i);
        const Vector<AnimationKeyFrame2D>& keyFrames = track.keyFrames_;

        // Time out of range
        if (time < keyFrames[0].time_ || time > keyFrames.Back().time_)
            trackNodeInfos_[i].value.enabled_ = false;
        else
        {
            unsigned index = keyFrames.Size() - 1;
            for (unsigned j = 0; j < keyFrames.Size() - 1; ++j)
            {
                if (time <= keyFrames[j + 1].time_)
                {
                    index = j;
                    break;
                }
            }

            const AnimationKeyFrame2D& currKey = keyFrames[index];
            AnimationKeyFrame2D& value = trackNodeInfos_[i].value;

            value.enabled_ = currKey.enabled_;
            value.parent_ = currKey.parent_;

            if (index < keyFrames.Size() - 1)
            {
                const AnimationKeyFrame2D& nextKey = keyFrames[index + 1];
                float t = (time - currKey.time_)  / (nextKey.time_ - currKey.time_);
                value.transform_ = currKey.transform_.Lerp(nextKey.transform_, t, currKey.spin_);

                if (trackNodeInfos_[i].hasSprite)
                    value.alpha_ = Atomic::Lerp(currKey.alpha_, nextKey.alpha_, t);
            }
            else
            {
                value.transform_ = currKey.transform_;

                if (trackNodeInfos_[i].hasSprite)
                    value.alpha_ = currKey.alpha_;
            }

            if (trackNodeInfos_[i].hasSprite)
            {
                value.zIndex_ = currKey.zIndex_;
                value.sprite_ = currKey.sprite_;
                value.useHotSpot_ = currKey.useHotSpot_;
                value.hotSpot_ = currKey.hotSpot_;
            }
        }
    }

    for (unsigned i = 0; i < numTracks_; ++i)
    {
        Node* node = trackNodes_[i];
        if (!node)
            continue;

        TrackNodeInfo& nodeInfo = trackNodeInfos_[i];

        if (!nodeInfo.value.enabled_)
            node->SetEnabled(false);
        else
        {
            node->SetEnabled(true);

            // Calculate world transform.
            CalculateTimelineWorldTransform(i);

            // Update node's transform
            Vector2 position = nodeInfo.value.transform_.position_ * PIXEL_SIZE;
            if (flipX_)
                position.x_ = -position.x_;
            if (flipY_)
                position.y_ = -position.y_;
            node->SetPosition(position);

            float angle = nodeInfo.value.transform_.angle_;
            if (flipX_ != flipY_)
                angle = -angle;
            node->SetRotation(angle);
            node->SetScale(nodeInfo.value.transform_.scale_);

            if (nodeInfo.hasSprite)
            {
                StaticSprite2D* staticSprite = node->GetComponent<StaticSprite2D>();
                if (staticSprite)
                {
                    staticSprite->SetOrderInLayer(orderInLayer_ + nodeInfo.value.zIndex_);
                    staticSprite->SetSprite(nodeInfo.value.sprite_);
                    staticSprite->SetAlpha(nodeInfo.value.alpha_);
                    staticSprite->SetUseHotSpot(nodeInfo.value.useHotSpot_);
                    staticSprite->SetHotSpot(nodeInfo.value.hotSpot_);
                }
            }
        }
    }
}
void Clockwork2DConstraints::CreateScene()
{
    scene_ = new Scene(context_);
    scene_->CreateComponent<Octree>();
    scene_->CreateComponent<DebugRenderer>();
    PhysicsWorld2D* physicsWorld = scene_->CreateComponent<PhysicsWorld2D>(); // Create 2D physics world component
    physicsWorld->SetDrawJoint(true); // Display the joints (Note that DrawDebugGeometry() must be set to true to acually draw the joints)
    drawDebug_ = true; // Set DrawDebugGeometry() to true

    // Create camera
    cameraNode_ = scene_->CreateChild("Camera");
    // Set camera's position
    cameraNode_->SetPosition(Vector3(0.0f, 0.0f, 0.0f)); // Note that Z setting is discarded; use camera.zoom instead (see MoveCamera() below for example)

    camera_ = cameraNode_->CreateComponent<Camera>();
    camera_->SetOrthographic(true);

    Graphics* graphics = GetSubsystem<Graphics>();
    camera_->SetOrthoSize((float)graphics->GetHeight() * PIXEL_SIZE);
    camera_->SetZoom(1.2f * Min((float)graphics->GetWidth() / 1280.0f, (float)graphics->GetHeight() / 800.0f)); // Set zoom according to user's resolution to ensure full visibility (initial zoom (1.2) is set for full visibility at 1280x800 resolution)

    // Set up a viewport to the Renderer subsystem so that the 3D scene can be seen
    SharedPtr<Viewport> viewport(new Viewport(context_, scene_, camera_));
    Renderer* renderer = GetSubsystem<Renderer>();
    renderer->SetViewport(0, viewport);

    Zone* zone = renderer->GetDefaultZone();
    zone->SetFogColor(Color(0.1f, 0.1f, 0.1f)); // Set background color for the scene

    // Create 4x3 grid
    for (unsigned i = 0; i<5; ++i)
    {
        Node* edgeNode = scene_->CreateChild("VerticalEdge");
        RigidBody2D* edgeBody = edgeNode->CreateComponent<RigidBody2D>();
        if (!dummyBody)
            dummyBody = edgeBody; // Mark first edge as dummy body (used by mouse pick)
        CollisionEdge2D* edgeShape = edgeNode->CreateComponent<CollisionEdge2D>();
        edgeShape->SetVertices(Vector2(i*2.5f -5.0f, -3.0f), Vector2(i*2.5f -5.0f, 3.0f));
        edgeShape->SetFriction(0.5f); // Set friction
    }

    for (unsigned j = 0; j<4; ++j)
    {
        Node* edgeNode = scene_->CreateChild("HorizontalEdge");
        /*RigidBody2D* edgeBody = */edgeNode->CreateComponent<RigidBody2D>();
        CollisionEdge2D* edgeShape = edgeNode->CreateComponent<CollisionEdge2D>();
        edgeShape->SetVertices(Vector2(-5.0f, j*2.0f -3.0f), Vector2(5.0f, j*2.0f -3.0f));
        edgeShape->SetFriction(0.5f); // Set friction
    }

    ResourceCache* cache = GetSubsystem<ResourceCache>();

    // Create a box (will be cloned later)
    Node* box  = scene_->CreateChild("Box");
    box->SetPosition(Vector3(0.8f, -2.0f, 0.0f));
    StaticSprite2D* boxSprite = box->CreateComponent<StaticSprite2D>();
    boxSprite->SetSprite(cache->GetResource<Sprite2D>("Clockwork2D/Box.png"));
    RigidBody2D* boxBody = box->CreateComponent<RigidBody2D>();
    boxBody->SetBodyType(BT_DYNAMIC);
    boxBody->SetLinearDamping(0.0f);
    boxBody->SetAngularDamping(0.0f);
    CollisionBox2D* shape = box->CreateComponent<CollisionBox2D>(); // Create box shape
    shape->SetSize(Vector2(0.32f, 0.32f)); // Set size
    shape->SetDensity(1.0f); // Set shape density (kilograms per meter squared)
    shape->SetFriction(0.5f); // Set friction
    shape->SetRestitution(0.1f); // Set restitution (slight bounce)

    // Create a ball (will be cloned later)
    Node* ball  = scene_->CreateChild("Ball");
    ball->SetPosition(Vector3(1.8f, -2.0f, 0.0f));
    StaticSprite2D* ballSprite = ball->CreateComponent<StaticSprite2D>();
    ballSprite->SetSprite(cache->GetResource<Sprite2D>("Clockwork2D/Ball.png"));
    RigidBody2D* ballBody = ball->CreateComponent<RigidBody2D>();
    ballBody->SetBodyType(BT_DYNAMIC);
    ballBody->SetLinearDamping(0.0f);
    ballBody->SetAngularDamping(0.0f);
    CollisionCircle2D* ballShape = ball->CreateComponent<CollisionCircle2D>(); // Create circle shape
    ballShape->SetRadius(0.16f); // Set radius
    ballShape->SetDensity(1.0f); // Set shape density (kilograms per meter squared)
    ballShape->SetFriction(0.5f); // Set friction
    ballShape->SetRestitution(0.6f); // Set restitution: make it bounce

    // Create a polygon
    Node* polygon = scene_->CreateChild("Polygon");
    polygon->SetPosition(Vector3(1.6f, -2.0f, 0.0f));
    polygon->SetScale(0.7f);
    StaticSprite2D* polygonSprite = polygon->CreateComponent<StaticSprite2D>();
    polygonSprite->SetSprite(cache->GetResource<Sprite2D>("Clockwork2D/Aster.png"));
    RigidBody2D* polygonBody = polygon->CreateComponent<RigidBody2D>();
    polygonBody->SetBodyType(BT_DYNAMIC);
    CollisionPolygon2D* polygonShape = polygon->CreateComponent<CollisionPolygon2D>();
    // TODO: create from PODVector<Vector2> using SetVertices()
    polygonShape->SetVertexCount(6); // Set number of vertices (mandatory when using SetVertex())
    polygonShape->SetVertex(0, Vector2(-0.8f, -0.3f));
    polygonShape->SetVertex(1, Vector2(0.5f, -0.8f));
    polygonShape->SetVertex(2, Vector2(0.8f, -0.3f));
    polygonShape->SetVertex(3, Vector2(0.8f, 0.5f));
    polygonShape->SetVertex(4, Vector2(0.5f, 0.9f));
    polygonShape->SetVertex(5, Vector2(-0.5f, 0.7f));
    polygonShape->SetDensity(1.0f); // Set shape density (kilograms per meter squared)
    polygonShape->SetFriction(0.3f); // Set friction
    polygonShape->SetRestitution(0.0f); // Set restitution (no bounce)

    // Create a ConstraintDistance2D
    CreateFlag("ConstraintDistance2D", -4.97f, 3.0f); // Display Text3D flag
    Node* boxDistanceNode = box->Clone();
    Node* ballDistanceNode = ball->Clone();
    RigidBody2D* ballDistanceBody = ballDistanceNode->GetComponent<RigidBody2D>();
    boxDistanceNode->SetPosition(Vector3(-4.5f, 2.0f, 0.0f));
    ballDistanceNode->SetPosition(Vector3(-3.0f, 2.0f, 0.0f));

    ConstraintDistance2D* constraintDistance = boxDistanceNode->CreateComponent<ConstraintDistance2D>(); // Apply ConstraintDistance2D to box
    constraintDistance->SetOtherBody(ballDistanceBody); // Constrain ball to box
    constraintDistance->SetOwnerBodyAnchor(boxDistanceNode->GetPosition2D());
    constraintDistance->SetOtherBodyAnchor(ballDistanceNode->GetPosition2D());
    // Make the constraint soft (comment to make it rigid, which is its basic behavior)
    constraintDistance->SetFrequencyHz(4.0f);
    constraintDistance->SetDampingRatio(0.5f);

    // Create a ConstraintFriction2D ********** Not functional. From Box2d samples it seems that 2 anchors are required, Clockwork2D only provides 1, needs investigation ***********
    CreateFlag("ConstraintFriction2D", 0.03f, 1.0f); // Display Text3D flag
    Node* boxFrictionNode = box->Clone();
    Node* ballFrictionNode = ball->Clone();
    boxFrictionNode->SetPosition(Vector3(0.5f, 0.0f, 0.0f));
    ballFrictionNode->SetPosition(Vector3(1.5f, 0.0f, 0.0f));

    ConstraintFriction2D* constraintFriction = boxFrictionNode->CreateComponent<ConstraintFriction2D>(); // Apply ConstraintDistance2D to box
    constraintFriction->SetOtherBody(ballFrictionNode->GetComponent<RigidBody2D>()); // Constraint ball to box
    //constraintFriction->SetOwnerBodyAnchor(boxNode->GetPosition2D());
    //constraintFriction->SetOtherBodyAnchor(ballNode->GetPosition2D());
    //constraintFriction->SetMaxForce(10.0f); // ballBody.mass * gravity
    //constraintDistance->SetMaxTorque(10.0f); // ballBody.mass * radius * gravity

    // Create a ConstraintGear2D
    CreateFlag("ConstraintGear2D", -4.97f, -1.0f); // Display Text3D flag
    Node* baseNode = box->Clone();
    RigidBody2D* tempBody = baseNode->GetComponent<RigidBody2D>(); // Get body to make it static
    tempBody->SetBodyType(BT_STATIC);
    baseNode->SetPosition(Vector3(-3.7f, -2.5f, 0.0f));
    Node* ball1Node = ball->Clone();
    ball1Node->SetPosition(Vector3(-4.5f, -2.0f, 0.0f));
    RigidBody2D* ball1Body = ball1Node->GetComponent<RigidBody2D>();
    Node* ball2Node = ball->Clone();
    ball2Node->SetPosition(Vector3(-3.0f, -2.0f, 0.0f));
    RigidBody2D* ball2Body = ball2Node->GetComponent<RigidBody2D>();

    ConstraintRevolute2D* gear1 = baseNode->CreateComponent<ConstraintRevolute2D>(); // Apply constraint to baseBox
    gear1->SetOtherBody(ball1Body); // Constrain ball1 to baseBox
    gear1->SetAnchor(ball1Node->GetPosition2D());
    ConstraintRevolute2D* gear2 = baseNode->CreateComponent<ConstraintRevolute2D>(); // Apply constraint to baseBox
    gear2->SetOtherBody(ball2Body); // Constrain ball2 to baseBox
    gear2->SetAnchor(ball2Node->GetPosition2D());

    ConstraintGear2D* constraintGear = ball1Node->CreateComponent<ConstraintGear2D>(); // Apply constraint to ball1
    constraintGear->SetOtherBody(ball2Body); // Constrain ball2 to ball1
    constraintGear->SetOwnerConstraint(gear1);
    constraintGear->SetOtherConstraint(gear2);
    constraintGear->SetRatio(1.0f);

    ball1Body->ApplyAngularImpulse(0.015f, true); // Animate

    // Create a vehicle from a compound of 2 ConstraintWheel2Ds
    CreateFlag("ConstraintWheel2Ds compound", -2.45f, -1.0f); // Display Text3D flag
    Node* car = box->Clone();
    car->SetScale(Vector3(4.0f, 1.0f, 0.0f));
    car->SetPosition(Vector3(-1.2f, -2.3f, 0.0f));
    StaticSprite2D* tempSprite = car->GetComponent<StaticSprite2D>(); // Get car Sprite in order to draw it on top
    tempSprite->SetOrderInLayer(0); // Draw car on top of the wheels (set to -1 to draw below)
    Node* ball1WheelNode = ball->Clone();
    ball1WheelNode->SetPosition(Vector3(-1.6f, -2.5f, 0.0f));
    Node* ball2WheelNode = ball->Clone();
    ball2WheelNode->SetPosition(Vector3(-0.8f, -2.5f, 0.0f));

    ConstraintWheel2D* wheel1 = car->CreateComponent<ConstraintWheel2D>();
    wheel1->SetOtherBody(ball1WheelNode->GetComponent<RigidBody2D>());
    wheel1->SetAnchor(ball1WheelNode->GetPosition2D());
    wheel1->SetAxis(Vector2(0.0f, 1.0f));
    wheel1->SetMaxMotorTorque(20.0f);
    wheel1->SetFrequencyHz(4.0f);
    wheel1->SetDampingRatio(0.4f);

    ConstraintWheel2D* wheel2 = car->CreateComponent<ConstraintWheel2D>();
    wheel2->SetOtherBody(ball2WheelNode->GetComponent<RigidBody2D>());
    wheel2->SetAnchor(ball2WheelNode->GetPosition2D());
    wheel2->SetAxis(Vector2(0.0f, 1.0f));
    wheel2->SetMaxMotorTorque(10.0f);
    wheel2->SetFrequencyHz(4.0f);
    wheel2->SetDampingRatio(0.4f);

    // ConstraintMotor2D
    CreateFlag("ConstraintMotor2D", 2.53f, -1.0f); // Display Text3D flag
    Node* boxMotorNode = box->Clone();
    tempBody = boxMotorNode->GetComponent<RigidBody2D>(); // Get body to make it static
    tempBody->SetBodyType(BT_STATIC);
    Node* ballMotorNode = ball->Clone();
    boxMotorNode->SetPosition(Vector3(3.8f, -2.1f, 0.0f));
    ballMotorNode->SetPosition(Vector3(3.8f, -1.5f, 0.0f));

    ConstraintMotor2D* constraintMotor = boxMotorNode->CreateComponent<ConstraintMotor2D>();
    constraintMotor->SetOtherBody(ballMotorNode->GetComponent<RigidBody2D>()); // Constrain ball to box
    constraintMotor->SetLinearOffset(Vector2(0.0f, 0.8f)); // Set ballNode position relative to boxNode position = (0,0)
    constraintMotor->SetAngularOffset(0.1f);
    constraintMotor->SetMaxForce(5.0f);
    constraintMotor->SetMaxTorque(10.0f);
    constraintMotor->SetCorrectionFactor(1.0f);
    constraintMotor->SetCollideConnected(true); // doesn't work

    // ConstraintMouse2D is demonstrated in HandleMouseButtonDown() function. It is used to "grasp" the sprites with the mouse.
    CreateFlag("ConstraintMouse2D", 0.03f, -1.0f); // Display Text3D flag

    // Create a ConstraintPrismatic2D
    CreateFlag("ConstraintPrismatic2D", 2.53f, 3.0f); // Display Text3D flag
    Node* boxPrismaticNode = box->Clone();
    tempBody = boxPrismaticNode->GetComponent<RigidBody2D>(); // Get body to make it static
    tempBody->SetBodyType(BT_STATIC);
    Node* ballPrismaticNode = ball->Clone();
    boxPrismaticNode->SetPosition(Vector3(3.3f, 2.5f, 0.0f));
    ballPrismaticNode->SetPosition(Vector3(4.3f, 2.0f, 0.0f));

    ConstraintPrismatic2D* constraintPrismatic = boxPrismaticNode->CreateComponent<ConstraintPrismatic2D>();
    constraintPrismatic->SetOtherBody(ballPrismaticNode->GetComponent<RigidBody2D>()); // Constrain ball to box
    constraintPrismatic->SetAxis(Vector2(1.0f, 1.0f)); // Slide from [0,0] to [1,1]
    constraintPrismatic->SetAnchor(Vector2(4.0f, 2.0f));
    constraintPrismatic->SetLowerTranslation(-1.0f);
    constraintPrismatic->SetUpperTranslation(0.5f);
    constraintPrismatic->SetEnableLimit(true);
    constraintPrismatic->SetMaxMotorForce(1.0f);
    constraintPrismatic->SetMotorSpeed(0.0f);

    // ConstraintPulley2D
    CreateFlag("ConstraintPulley2D", 0.03f, 3.0f); // Display Text3D flag
    Node* boxPulleyNode = box->Clone();
    Node* ballPulleyNode = ball->Clone();
    boxPulleyNode->SetPosition(Vector3(0.5f, 2.0f, 0.0f));
    ballPulleyNode->SetPosition(Vector3(2.0f, 2.0f, 0.0f));

    ConstraintPulley2D* constraintPulley = boxPulleyNode->CreateComponent<ConstraintPulley2D>(); // Apply constraint to box
    constraintPulley->SetOtherBody(ballPulleyNode->GetComponent<RigidBody2D>()); // Constrain ball to box
    constraintPulley->SetOwnerBodyAnchor(boxPulleyNode->GetPosition2D());
    constraintPulley->SetOtherBodyAnchor(ballPulleyNode->GetPosition2D());
    constraintPulley->SetOwnerBodyGroundAnchor(boxPulleyNode->GetPosition2D() + Vector2(0.0f, 1.0f));
    constraintPulley->SetOtherBodyGroundAnchor(ballPulleyNode->GetPosition2D() + Vector2(0.0f, 1.0f));
    constraintPulley->SetRatio(1.0); // Weight ratio between ownerBody and otherBody

    // Create a ConstraintRevolute2D
    CreateFlag("ConstraintRevolute2D", -2.45f, 3.0f); // Display Text3D flag
    Node* boxRevoluteNode = box->Clone();
    tempBody = boxRevoluteNode->GetComponent<RigidBody2D>(); // Get body to make it static
    tempBody->SetBodyType(BT_STATIC);
    Node* ballRevoluteNode = ball->Clone();
    boxRevoluteNode->SetPosition(Vector3(-2.0f, 1.5f, 0.0f));
    ballRevoluteNode->SetPosition(Vector3(-1.0f, 2.0f, 0.0f));

    ConstraintRevolute2D* constraintRevolute = boxRevoluteNode->CreateComponent<ConstraintRevolute2D>(); // Apply constraint to box
    constraintRevolute->SetOtherBody(ballRevoluteNode->GetComponent<RigidBody2D>()); // Constrain ball to box
    constraintRevolute->SetAnchor(Vector2(-1.0f, 1.5f));
    constraintRevolute->SetLowerAngle(-1.0f); // In radians
    constraintRevolute->SetUpperAngle(0.5f); // In radians
    constraintRevolute->SetEnableLimit(true);
    constraintRevolute->SetMaxMotorTorque(10.0f);
    constraintRevolute->SetMotorSpeed(0.0f);
    constraintRevolute->SetEnableMotor(true);

    // Create a ConstraintRope2D
    CreateFlag("ConstraintRope2D", -4.97f, 1.0f); // Display Text3D flag
    Node* boxRopeNode = box->Clone();
    tempBody = boxRopeNode->GetComponent<RigidBody2D>();
    tempBody->SetBodyType(BT_STATIC);
    Node* ballRopeNode = ball->Clone();
    boxRopeNode->SetPosition(Vector3(-3.7f, 0.7f, 0.0f));
    ballRopeNode->SetPosition(Vector3(-4.5f, 0.0f, 0.0f));

    ConstraintRope2D* constraintRope = boxRopeNode->CreateComponent<ConstraintRope2D>();
    constraintRope->SetOtherBody(ballRopeNode->GetComponent<RigidBody2D>()); // Constrain ball to box
    constraintRope->SetOwnerBodyAnchor(Vector2(0.0f, -0.5f)); // Offset from box (OwnerBody) : the rope is rigid from OwnerBody center to this ownerBodyAnchor
    constraintRope->SetMaxLength(0.9f); // Rope length
    constraintRope->SetCollideConnected(true);

    // Create a ConstraintWeld2D
    CreateFlag("ConstraintWeld2D", -2.45f, 1.0f); // Display Text3D flag
    Node* boxWeldNode = box->Clone();
    Node* ballWeldNode = ball->Clone();
    boxWeldNode->SetPosition(Vector3(-0.5f, 0.0f, 0.0f));
    ballWeldNode->SetPosition(Vector3(-2.0f, 0.0f, 0.0f));

    ConstraintWeld2D* constraintWeld = boxWeldNode->CreateComponent<ConstraintWeld2D>();
    constraintWeld->SetOtherBody(ballWeldNode->GetComponent<RigidBody2D>()); // Constrain ball to box
    constraintWeld->SetAnchor(boxWeldNode->GetPosition2D());
    constraintWeld->SetFrequencyHz(4.0f);
    constraintWeld->SetDampingRatio(0.5f);

    // Create a ConstraintWheel2D
    CreateFlag("ConstraintWheel2D",  2.53f, 1.0f); // Display Text3D flag
    Node* boxWheelNode = box->Clone();
    Node* ballWheelNode = ball->Clone();
    boxWheelNode->SetPosition(Vector3(3.8f, 0.0f, 0.0f));
    ballWheelNode->SetPosition(Vector3(3.8f, 0.9f, 0.0f));

    ConstraintWheel2D* constraintWheel = boxWheelNode->CreateComponent<ConstraintWheel2D>();
    constraintWheel->SetOtherBody(ballWheelNode->GetComponent<RigidBody2D>()); // Constrain ball to box
    constraintWheel->SetAnchor(ballWheelNode->GetPosition2D());
    constraintWheel->SetAxis(Vector2(0.0f, 1.0f));
    constraintWheel->SetEnableMotor(true);
    constraintWheel->SetMaxMotorTorque(1.0f);
    constraintWheel->SetMotorSpeed(0.0f);
    constraintWheel->SetFrequencyHz(4.0f);
    constraintWheel->SetDampingRatio(0.5f);
    constraintWheel->SetCollideConnected(true); // doesn't work
}
void SkeletalAnimation::CreateScene()
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();

    scene_ = new Scene(context_);

    // Create octree, use default volume (-1000, -1000, -1000) to (1000, 1000, 1000)
    // Also create a DebugRenderer component so that we can draw debug geometry
    scene_->CreateComponent<Octree>();
    scene_->CreateComponent<DebugRenderer>();

    // Create scene node & StaticModel component for showing a static plane
    Node* planeNode = scene_->CreateChild("Plane");
    planeNode->SetScale(Vector3(100.0f, 1.0f, 100.0f));
    StaticModel* planeObject = planeNode->CreateComponent<StaticModel>();
    planeObject->SetModel(cache->GetResource<Model>("Models/Plane.mdl"));
    planeObject->SetMaterial(cache->GetResource<Material>("Materials/StoneTiled.xml"));

    // Create a Zone component for ambient lighting & fog control
    Node* zoneNode = scene_->CreateChild("Zone");
    Zone* zone = zoneNode->CreateComponent<Zone>();
    zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f));
    zone->SetAmbientColor(Color(0.15f, 0.15f, 0.15f));
    zone->SetFogColor(Color(0.5f, 0.5f, 0.7f));
    zone->SetFogStart(100.0f);
    zone->SetFogEnd(300.0f);

    // Create a directional light to the world. Enable cascaded shadows on it
    Node* lightNode = scene_->CreateChild("DirectionalLight");
    lightNode->SetDirection(Vector3(0.6f, -1.0f, 0.8f));
    Light* light = lightNode->CreateComponent<Light>();
    light->SetLightType(LIGHT_DIRECTIONAL);
    light->SetCastShadows(true);
    light->SetShadowBias(BiasParameters(0.00025f, 0.5f));
    // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
    light->SetShadowCascade(CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f));

    // Create animated models
    const unsigned NUM_MODELS = 100;
    const float MODEL_MOVE_SPEED = 2.0f;
    const float MODEL_ROTATE_SPEED = 100.0f;
    const BoundingBox bounds(Vector3(-47.0f, 0.0f, -47.0f), Vector3(47.0f, 0.0f, 47.0f));

    for (unsigned i = 0; i < NUM_MODELS; ++i)
    {
        Node* modelNode = scene_->CreateChild("Jack");
        modelNode->SetPosition(Vector3(Random(90.0f) - 45.0f, 0.0f, Random(90.0f) - 45.0f));
        modelNode->SetRotation(Quaternion(0.0f, Random(360.0f), 0.0f));
        AnimatedModel* modelObject = modelNode->CreateComponent<AnimatedModel>();
        modelObject->SetModel(cache->GetResource<Model>("Models/Jack.mdl"));
        modelObject->SetMaterial(cache->GetResource<Material>("Materials/Jack.xml"));
        modelObject->SetCastShadows(true);

        // Create an AnimationState for a walk animation. Its time position will need to be manually updated to advance the
        // animation, The alternative would be to use an AnimationController component which updates the animation automatically,
        // but we need to update the model's position manually in any case
        Animation* walkAnimation = cache->GetResource<Animation>("Models/Jack_Walk.ani");
        AnimationState* state = modelObject->AddAnimationState(walkAnimation);
        // The state would fail to create (return null) if the animation was not found
        if (state)
        {
            // Enable full blending weight and looping
            state->SetWeight(1.0f);
            state->SetLooped(true);
            state->SetTime(Random(walkAnimation->GetLength()));
        }

        // Create our custom Mover component that will move & animate the model during each frame's update
        Mover* mover = modelNode->CreateComponent<Mover>();
        mover->SetParameters(MODEL_MOVE_SPEED, MODEL_ROTATE_SPEED, bounds);
    }

    // Create the camera. Limit far clip distance to match the fog
    cameraNode_ = scene_->CreateChild("Camera");
    Camera* camera = cameraNode_->CreateComponent<Camera>();
    camera->SetFarClip(300.0f);

    // Set an initial position for the camera scene node above the plane
    cameraNode_->SetPosition(Vector3(0.0f, 5.0f, 0.0f));
}
Example #7
0
void Ragdolls::CreateScene()
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    
    scene_ = new Scene(context_);
    
    // Create octree, use default volume (-1000, -1000, -1000) to (1000, 1000, 1000)
    // Create a physics simulation world with default parameters, which will update at 60fps. Like the Octree must
    // exist before creating drawable components, the PhysicsWorld must exist before creating physics components.
    // Finally, create a DebugRenderer component so that we can draw physics debug geometry
    scene_->CreateComponent<Octree>();
    scene_->CreateComponent<PhysicsWorld>();
    scene_->CreateComponent<DebugRenderer>();
    
    // Create a Zone component for ambient lighting & fog control
    Node* zoneNode = scene_->CreateChild("Zone");
    Zone* zone = zoneNode->CreateComponent<Zone>();
    zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f));
    zone->SetAmbientColor(Color(0.15f, 0.15f, 0.15f));
    zone->SetFogColor(Color(0.5f, 0.5f, 0.7f));
    zone->SetFogStart(100.0f);
    zone->SetFogEnd(300.0f);
    
    // Create a directional light to the world. Enable cascaded shadows on it
    Node* lightNode = scene_->CreateChild("DirectionalLight");
    lightNode->SetDirection(Vector3(0.6f, -1.0f, 0.8f));
    Light* light = lightNode->CreateComponent<Light>();
    light->SetLightType(LIGHT_DIRECTIONAL);
    light->SetCastShadows(true);
    light->SetShadowBias(BiasParameters(0.0001f, 0.5f));
    // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
    light->SetShadowCascade(CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f));
    
    {
        // Create a floor object, 500 x 500 world units. Adjust position so that the ground is at zero Y
        Node* floorNode = scene_->CreateChild("Floor");
        floorNode->SetPosition(Vector3(0.0f, -0.5f, 0.0f));
        floorNode->SetScale(Vector3(500.0f, 1.0f, 500.0f));
        StaticModel* floorObject = floorNode->CreateComponent<StaticModel>();
        floorObject->SetModel(cache->GetResource<Model>("Models/Box.mdl"));
        floorObject->SetMaterial(cache->GetResource<Material>("Materials/StoneTiled.xml"));
        
        // Make the floor physical by adding RigidBody and CollisionShape components
        RigidBody* body = floorNode->CreateComponent<RigidBody>();
        // We will be spawning spherical objects in this sample. The ground also needs non-zero rolling friction so that
        // the spheres will eventually come to rest
        body->SetRollingFriction(0.15f);
        CollisionShape* shape = floorNode->CreateComponent<CollisionShape>();
        // Set a box shape of size 1 x 1 x 1 for collision. The shape will be scaled with the scene node scale, so the
        // rendering and physics representation sizes should match (the box model is also 1 x 1 x 1.)
        shape->SetBox(Vector3::ONE);
    }
    
    // Create animated models
    for (int z = -1; z <= 1; ++z)
    {
        for (int x = -4; x <= 4; ++x)
        {
            Node* modelNode = scene_->CreateChild("Jack");
            modelNode->SetPosition(Vector3(x * 5.0f, 0.0f, z * 5.0f));
            modelNode->SetRotation(Quaternion(0.0f, 180.0f, 0.0f));
            AnimatedModel* modelObject = modelNode->CreateComponent<AnimatedModel>();
            modelObject->SetModel(cache->GetResource<Model>("Models/Jack.mdl"));
            modelObject->SetMaterial(cache->GetResource<Material>("Materials/Jack.xml"));
            modelObject->SetCastShadows(true);
            // Set the model to also update when invisible to avoid staying invisible when the model should come into
            // view, but does not as the bounding box is not updated
            modelObject->SetUpdateInvisible(true);
            
            // Create a rigid body and a collision shape. These will act as a trigger for transforming the
            // model into a ragdoll when hit by a moving object
            RigidBody* body = modelNode->CreateComponent<RigidBody>();
            // The phantom mode makes the rigid body only detect collisions, but impart no forces on the
            // colliding objects
            body->SetPhantom(true);
            CollisionShape* shape = modelNode->CreateComponent<CollisionShape>();
            // Create the capsule shape with an offset so that it is correctly aligned with the model, which
            // has its origin at the feet
            shape->SetCapsule(0.7f, 2.0f, Vector3(0.0f, 1.0f, 0.0f));
            
            // Create a custom component that reacts to collisions and creates the ragdoll
            modelNode->CreateComponent<CreateRagdoll>();
        }
    }
    
    // Create the camera. Limit far clip distance to match the fog. Note: now we actually create the camera node outside
    // the scene, because we want it to be unaffected by scene load / save
    cameraNode_ = new Node(context_);
    Camera* camera = cameraNode_->CreateComponent<Camera>();
    camera->SetFarClip(300.0f);
    
    // Set an initial position for the camera scene node above the floor
    cameraNode_->SetPosition(Vector3(0.0f, 3.0f, -20.0f));
}
Example #8
0
void VehicleDemo::CreateScene()
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    
    scene_ = new Scene(context_);
    
    // Create scene subsystem components
    scene_->CreateComponent<Octree>();
    scene_->CreateComponent<PhysicsWorld>();
    scene_->CreateComponent<DebugRenderer>();
    
    // Create camera and define viewport. We will be doing load / save, so it's convenient to create the camera outside the scene,
    // so that it won't be destroyed and recreated, and we don't have to redefine the viewport on load
    cameraNode_ = new Node(context_);
    Camera* camera = cameraNode_->CreateComponent<Camera>();
    camera->SetFarClip(500.0f);
    GetSubsystem<Renderer>()->SetViewport(0, new Viewport(context_, scene_, camera));
    //GetSubsystem<Renderer>()->SetHDRRendering(true);
    RenderPath* effectRenderPath=GetSubsystem<Renderer>()->GetViewport(0)->GetRenderPath();
    //effectRenderPath->Append(cache->GetResource<XMLFile>("PostProcess/AutoExposure.xml"));
    effectRenderPath->Append(cache->GetResource<XMLFile>("PostProcess/Blur.xml"));
    
    effectRenderPath->SetShaderParameter("BlurRadius", Variant(0.002f) );
    effectRenderPath->SetShaderParameter("BlurSigma", Variant(0.001f) );
    effectRenderPath->SetEnabled("Blur", false);
    

    
    // Create static scene content. First create a zone for ambient lighting and fog control
    Node* zoneNode = scene_->CreateChild("Zone");
    Zone* zone = zoneNode->CreateComponent<Zone>();
    //zone->SetAmbientColor(Color(0.15f, 0.15f, 0.15f));
    zone->SetFogColor(Color(0.2f, 0.2f, 0.3f));
    zone->SetFogStart(300.0f);
    zone->SetFogEnd(500.0f);
    zone->SetBoundingBox(BoundingBox(-2000.0f, 2000.0f));

 /*
    // Create a directional light with cascaded shadow mapping
    Node* lightNode = scene_->CreateChild("DirectionalLight");
    lightNode->SetDirection(Vector3(0.3f, -0.5f, 0.425f));
    Light* light = lightNode->CreateComponent<Light>();
    light->SetLightType(LIGHT_DIRECTIONAL);
    light->SetCastShadows(true);
    light->SetShadowBias(BiasParameters(0.00025f, 0.5f));
    light->SetShadowCascade(CascadeParameters(20.0f, 50.0f, 200.0f, 0.0f, 0.8f));
    light->SetSpecularIntensity(0.5f);
*/
    
    
    
    
    // Create heightmap terrain with collision
    Node* terrainNode = scene_->CreateChild("Terrain");
    terrainNode->SetPosition(Vector3::ZERO);
    Terrain* terrain = terrainNode->CreateComponent<Terrain>();
    terrain->SetPatchSize(64);
    terrain->SetSpacing(Vector3(2.0f, 0.1f, 2.0f)); // Spacing between vertices and vertical resolution of the height map
    terrain->SetSmoothing(true);
    terrain->SetHeightMap(cache->GetResource<Image>("Textures/HeightMap.png"));
    terrain->SetMaterial(cache->GetResource<Material>("Materials/Terrain.xml"));
    // The terrain consists of large triangles, which fits well for occlusion rendering, as a hill can occlude all
    // terrain patches and other objects behind it
    terrain->SetOccluder(true);
    
    RigidBody* body = terrainNode->CreateComponent<RigidBody>();
    body->SetCollisionLayer(2); // Use layer bitmask 2 for static geometry
    CollisionShape* shape = terrainNode->CreateComponent<CollisionShape>();
    shape->SetTerrain();
    
    
    // Create skybox. The Skybox component is used like StaticModel, but it will be always located at the camera, giving the
    // illusion of the box planes being far away. Use just the ordinary Box model and a suitable material, whose shader will
    // generate the necessary 3D texture coordinates for cube mapping

/*
    Node* skyNode2 = scene_->CreateChild("Sky");
    skyNode2->SetScale(80.0f); // The scale actually does not matter
    Skybox* skybox2 = skyNode2->CreateComponent<Skybox>();
    skybox2->SetModel(cache->GetResource<Model>("Models/Box.mdl"));
    skybox2->SetMaterial(cache->GetResource<Material>("Materials/Skybox.xml"));
   */
    
    
    Node* skyNode = scene_->CreateChild("ProcSkyNode");
    skyNode->SetEnabled(true);
    skyNode->SetName("ProcSkyNode");
    skyNode->SetPosition(Urho3D::Vector3(0.0, 0.0, 0.0));
    skyNode->SetRotation(Urho3D::Quaternion(1, 0, 0, 0));
    skyNode->SetScale(Urho3D::Vector3(100.0, 100.0, 100.0));
    
    
    ProcSky* procSky = skyNode->CreateComponent<ProcSky>();
    procSky->SetEnabled(true);
    
    Node* skyLightNode = skyNode->CreateChild("ProcSkyLight");
    skyLightNode->SetEnabled(true);
    skyLightNode->SetPosition(Urho3D::Vector3(0.0, 0.0, 0.0));
    skyLightNode->SetRotation(Urho3D::Quaternion(0.707107, 0, -0.707107, 0));
    skyLightNode->SetScale(Urho3D::Vector3(1, 1, 1));
    Light* skyLight = skyLightNode->CreateComponent<Light>();
    skyLight->SetLightType(LIGHT_DIRECTIONAL);
    skyLight->SetColor(Urho3D::Color(0.753, 0.749, 0.678, 1));
    skyLight->SetSpecularIntensity(0);
    skyLight->SetOccludee(false);
    skyLight->SetOccluder(false);
    skyLight->SetCastShadows(true);
    skyLight->SetShadowCascade(Urho3D::CascadeParameters(20, 50, 100, 500, 0.8f));
    skyLight->SetShadowFocus(Urho3D::FocusParameters(true, true, true, 1.0f, 5.0f));
    skyLight->SetShadowBias(Urho3D::BiasParameters(1e-005, 0.001));

    

    
    
    
    if (skyNode) {
        //ProcSky* procSky(skyNode->GetComponent<ProcSky>());
        if (procSky) {
            // Can set other parameters here; e.g., SetUpdateMode(), SetUpdateInterval(), SetRenderSize()
            procSky->Initialize();
            URHO3D_LOGINFO("ProcSky Initialized.");
        } else {
            URHO3D_LOGERROR("ProcSky node missing ProcSky component.");
        }
    } else {
        URHO3D_LOGERROR("ProcSky node not found in scene.");
    }
    
    // Create 1000 mushrooms in the terrain. Always face outward along the terrain normal
   /*
    const unsigned NUM_MUSHROOMS = 0;
    for (unsigned i = 0; i < NUM_MUSHROOMS; ++i)
    {
        Node* objectNode = scene_->CreateChild("SafetyCone");
        Vector3 position(Random(2000.0f) - 1000.0f, 0.0f, Random(2000.0f) - 1000.0f);
        position.y_ = terrain->GetHeight(position);
        objectNode->SetPosition(position);
        // Create a rotation quaternion from up vector to terrain normal
        objectNode->SetRotation(Quaternion(Vector3::UP, terrain->GetNormal(position)));
        objectNode->SetScale(3.0f);
        StaticModel* object = objectNode->CreateComponent<StaticModel>();
        object->SetModel(cache->GetResource<Model>("MyProjects/SafetyCone/SafetyCone.mdl"));
        object->SetMaterial(cache->GetResource<Material>("MyProjects/SafetyCone/ConeBase.xml"));
        object->SetMaterial(cache->GetResource<Material>("MyProjects/SafetyCone/SafetyCone.xml"));
        object->SetCastShadows(true);
        
        
        
        RigidBody* body = objectNode->CreateComponent<RigidBody>();
        //body->SetCollisionLayer(2);
        body->SetMass(2.0f);
        body->SetFriction(0.75f);
        CollisionShape* shape = objectNode->CreateComponent<CollisionShape>();
        //shape->SetTriangleMesh(object->GetModel(), 0);
        shape->SetConvexHull(object->GetModel(), 0);
    }
    */
}
Example #9
0
void MultipleViewports::CreateScene()
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    
    scene_ = new Scene(context_);
    
    // Create octree, use default volume (-1000, -1000, -1000) to (1000, 1000, 1000)
    // Also create a DebugRenderer component so that we can draw debug geometry
    scene_->CreateComponent<Octree>();
    scene_->CreateComponent<DebugRenderer>();
    
    // Create scene node & StaticModel component for showing a static plane
    Node* planeNode = scene_->CreateChild("Plane");
    planeNode->SetScale(Vector3(100.0f, 1.0f, 100.0f));
    StaticModel* planeObject = planeNode->CreateComponent<StaticModel>();
    planeObject->SetModel(cache->GetResource<Model>("Models/Plane.mdl"));
    planeObject->SetMaterial(cache->GetResource<Material>("Materials/StoneTiled.xml"));
    
    // Create a Zone component for ambient lighting & fog control
    Node* zoneNode = scene_->CreateChild("Zone");
    Zone* zone = zoneNode->CreateComponent<Zone>();
    zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f));
    zone->SetAmbientColor(Color(0.15f, 0.15f, 0.15f));
    zone->SetFogColor(Color(0.5f, 0.5f, 0.7f));
    zone->SetFogStart(100.0f);
    zone->SetFogEnd(300.0f);
    
    // Create a directional light to the world. Enable cascaded shadows on it
    Node* lightNode = scene_->CreateChild("DirectionalLight");
    lightNode->SetDirection(Vector3(0.6f, -1.0f, 0.8f));
    Light* light = lightNode->CreateComponent<Light>();
    light->SetLightType(LIGHT_DIRECTIONAL);
    light->SetCastShadows(true);
    light->SetShadowBias(BiasParameters(0.00025f, 0.5f));
    // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
    light->SetShadowCascade(CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f));

    // Create some mushrooms
    const unsigned NUM_MUSHROOMS = 240;
    for (unsigned i = 0; i < NUM_MUSHROOMS; ++i)
    {
        Node* mushroomNode = scene_->CreateChild("Mushroom");
        mushroomNode->SetPosition(Vector3(Random(90.0f) - 45.0f, 0.0f, Random(90.0f) - 45.0f));
        mushroomNode->SetRotation(Quaternion(0.0f, Random(360.0f), 0.0f));
        mushroomNode->SetScale(0.5f + Random(2.0f));
        StaticModel* mushroomObject = mushroomNode->CreateComponent<StaticModel>();
        mushroomObject->SetModel(cache->GetResource<Model>("Models/Mushroom.mdl"));
        mushroomObject->SetMaterial(cache->GetResource<Material>("Materials/Mushroom.xml"));
        mushroomObject->SetCastShadows(true);
    }
    
    // Create randomly sized boxes. If boxes are big enough, make them occluders
    const unsigned NUM_BOXES = 20;
    for (unsigned i = 0; i < NUM_BOXES; ++i)
    {
        Node* boxNode = scene_->CreateChild("Box");
        float size = 1.0f + Random(10.0f);
        boxNode->SetPosition(Vector3(Random(80.0f) - 40.0f, size * 0.5f, Random(80.0f) - 40.0f));
        boxNode->SetScale(size);
        StaticModel* boxObject = boxNode->CreateComponent<StaticModel>();
        boxObject->SetModel(cache->GetResource<Model>("Models/Box.mdl"));
        boxObject->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml"));
        boxObject->SetCastShadows(true);
        if (size >= 3.0f)
            boxObject->SetOccluder(true);
    }
    
    // Create the cameras. Limit far clip distance to match the fog
    cameraNode_ = scene_->CreateChild("Camera");
    Camera* camera = cameraNode_->CreateComponent<Camera>();
    camera->SetFarClip(300.0f);
    
    // Parent the rear camera node to the front camera node and turn it 180 degrees to face backward
    // Here, we use the angle-axis constructor for Quaternion instead of the usual Euler angles
    rearCameraNode_ = cameraNode_->CreateChild("RearCamera");
    rearCameraNode_->Rotate(Quaternion(180.0f, Vector3::UP));
    Camera* rearCamera = rearCameraNode_->CreateComponent<Camera>();
    rearCamera->SetFarClip(300.0f);
    // Because the rear viewport is rather small, disable occlusion culling from it. Use the camera's
    // "view override flags" for this. We could also disable eg. shadows or force low material quality
    // if we wanted
    rearCamera->SetViewOverrideFlags(VO_DISABLE_OCCLUSION);
    
    // Set an initial position for the front camera scene node above the plane
    cameraNode_->SetPosition(Vector3(0.0f, 5.0f, 0.0f));
}