bool ObjectPlacer::KeyHandler::handle(const sf::Event::KeyEvent& e, bool down) { if (!down) { return true; } if (e.code == sf::Keyboard::Numpad0) { m_placer->Save(); } if (e.code == sf::Keyboard::Add) { sf::Vector2f p; if (m_placer->GetCurrentNode()) { p = m_placer->GetCurrentNode()->GetGlobalPosition(); } else { p = m_placer->GetScene()->GetGame()->GetMousePosition(); } m_placer->Remove(); m_placer->Next(); m_placer->New(roundf(p.x), roundf(p.y)); } if (e.code == sf::Keyboard::Subtract) { sf::Vector2f p; if (m_placer->GetCurrentNode()) { p = m_placer->GetCurrentNode()->GetGlobalPosition(); } else { p = m_placer->GetScene()->GetGame()->GetMousePosition(); } m_placer->Remove(); m_placer->Prev(); m_placer->New(roundf(p.x), roundf(p.y)); } Node* obj = m_placer->GetCurrentNode(); if (obj) { auto p = obj->GetPosition(); if (e.code == sf::Keyboard::Down) { obj->SetPosition(p.x, p.y + 1); } if (e.code == sf::Keyboard::Up) { obj->SetPosition(p.x, p.y - 1); } if (e.code == sf::Keyboard::Left) { obj->SetPosition(p.x - 1, p.y); } if (e.code == sf::Keyboard::Right) { obj->SetPosition(p.x + 1, p.y); } if (e.code == sf::Keyboard::Multiply) { obj->SetRotation(obj->GetRotation() + 15); } if (e.code == sf::Keyboard::Divide) { obj->SetRotation(obj->GetRotation() - 15); } if (e.code == sf::Keyboard::Comma) { obj->SetRotation(0); } } return true; }
void AnimationState::ApplyTrackFullWeight(AnimationStateTrack& stateTrack) { 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_; if (!interpolate) { // No interpolation, full weight if (channelMask & CHANNEL_POSITION) node->SetPosition(keyFrame->position_); if (channelMask & CHANNEL_ROTATION) node->SetRotation(keyFrame->rotation_); if (channelMask & CHANNEL_SCALE) node->SetScale(keyFrame->scale_); } else { 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; // Interpolation, full weight if (channelMask & CHANNEL_POSITION) node->SetPosition(keyFrame->position_.Lerp(nextKeyFrame->position_, t)); if (channelMask & CHANNEL_ROTATION) node->SetRotation(keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t)); if (channelMask & CHANNEL_SCALE) node->SetScale(keyFrame->scale_.Lerp(nextKeyFrame->scale_, t)); } }
void Ragdolls::SpawnObject() { ResourceCache* cache = GetContext()->m_ResourceCache.get(); Node* boxNode = scene_->CreateChild("Sphere"); boxNode->SetPosition(cameraNode_->GetPosition()); boxNode->SetRotation(cameraNode_->GetRotation()); boxNode->SetScale(0.25f); StaticModel* boxObject = boxNode->CreateComponent<StaticModel>(); boxObject->SetModel(cache->GetResource<Model>("Models/Sphere.mdl")); boxObject->SetMaterial(cache->GetResource<Material>("Materials/StoneSmall.xml")); boxObject->SetCastShadows(true); RigidBody* body = boxNode->CreateComponent<RigidBody>(); body->SetMass(1.0f); body->SetRollingFriction(0.15f); CollisionShape* shape = boxNode->CreateComponent<CollisionShape>(); shape->SetSphere(1.0f); const float OBJECT_VELOCITY = 10.0f; // Set initial velocity for the RigidBody based on camera forward vector. Add also a slight up component // to overcome gravity better body->SetLinearVelocity(cameraNode_->GetRotation() * Vector3(0.0f, 0.25f, 1.0f) * OBJECT_VELOCITY); }
TileMaster::TileMaster(Context *context, MasterControl* masterControl): Object(context), masterControl_{masterControl} { rootNode_ = masterControl_->world.scene->CreateChild("TileMaster"); //Create hexagonal field //Lays a field of hexagons at the origin int bigHexSize = 23; for (int i = 0; i < bigHexSize; i++) { for (int j = 0; j < bigHexSize; j++) { if (i < (bigHexSize - bigHexSize / 4) + j / 2 && //Exclude bottom right i > (bigHexSize / 4) - (j + 1) / 2 && //Exclude bottom left i + 1 < (bigHexSize - bigHexSize / 4) + ((bigHexSize - j + 1)) / 2 && //Exclude top right i - 1 > (bigHexSize / 4) - ((bigHexSize - j + 2) / 2)) { //Exclude top left Vector3 tilePos = Vector3((-bigHexSize / 2.0f + i) * 2.0f + j % 2, -0.1f, (-bigHexSize / 2.0f + j + 0.5f) * 1.8f); tileMap_[IntVector2(i, j)] = new Tile(context_, this, tilePos); } } } //Add a directional light to the arena. Enable cascaded shadows on it Node* lightNode = rootNode_->CreateChild("Sun"); lightNode->SetPosition(Vector3::UP*5.0f); lightNode->SetRotation(Quaternion(90.0f, 0.0f, 0.0f)); Light* playLight = lightNode->CreateComponent<Light>(); playLight->SetLightType(LIGHT_DIRECTIONAL); playLight->SetBrightness(0.8f); playLight->SetRange(10.0f); playLight->SetColor(Color(1.0f, 0.9f, 0.95f)); playLight->SetCastShadows(false); }
void PhysicsStressTest::SpawnObject() { ResourceCache* cache = GetSubsystem<ResourceCache>(); // Create a smaller box at camera position Node* boxNode = scene_->CreateChild("SmallBox"); boxNode->SetPosition(cameraNode_->GetPosition()); boxNode->SetRotation(cameraNode_->GetRotation()); boxNode->SetScale(0.25f); StaticModel* boxObject = boxNode->CreateComponent<StaticModel>(); boxObject->SetModel(cache->GetResource<Model>("Models/Box.mdl")); boxObject->SetMaterial(cache->GetResource<Material>("Materials/StoneSmall.xml")); boxObject->SetCastShadows(true); // Create physics components, use a smaller mass also RigidBody* body = boxNode->CreateComponent<RigidBody>(); body->SetMass(0.25f); body->SetFriction(0.75f); CollisionShape* shape = boxNode->CreateComponent<CollisionShape>(); shape->SetBox(Vector3::ONE); const float OBJECT_VELOCITY = 10.0f; // Set initial velocity for the RigidBody based on camera forward vector. Add also a slight up component // to overcome gravity better body->SetLinearVelocity(cameraNode_->GetRotation() * Vector3(0.0f, 0.25f, 1.0f) * OBJECT_VELOCITY); }
void LuaIntegration::CreateScene() { ResourceCache* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); // Create the Octree component to the scene so that drawable objects can be rendered. Use default volume // (-1000, -1000, -1000) to (1000, 1000, 1000) scene_->CreateComponent<Octree>(); // Create a Zone component into a child scene node. The Zone controls ambient lighting and fog settings. Like the Octree, // it also defines its volume with a bounding box, but can be rotated (so it does not need to be aligned to the world X, Y // and Z axes.) Drawable objects "pick up" the zone they belong to and use it when rendering; several zones can exist Node* zoneNode = scene_->CreateChild("Zone"); Zone* zone = zoneNode->CreateComponent<Zone>(); // Set same volume as the Octree, set a close bluish fog and some ambient light zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f)); zone->SetAmbientColor(Color(0.05f, 0.1f, 0.15f)); zone->SetFogColor(Color(0.1f, 0.2f, 0.3f)); zone->SetFogStart(10.0f); zone->SetFogEnd(100.0f); // Create randomly positioned and oriented box StaticModels in the scene const unsigned NUM_OBJECTS = 2000; for (unsigned i = 0; i < NUM_OBJECTS; ++i) { Node* boxNode = scene_->CreateChild("Box"); boxNode->SetPosition(Vector3(Random(200.0f) - 100.0f, Random(200.0f) - 100.0f, Random(200.0f) - 100.0f)); // Orient using random pitch, yaw and roll Euler angles boxNode->SetRotation(Quaternion(Random(360.0f), Random(360.0f), Random(360.0f))); StaticModel* boxObject = boxNode->CreateComponent<StaticModel>(); boxObject->SetModel(cache->GetResource<Model>("Models/Box.mdl")); boxObject->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); // Add our custom Rotator script object (using the LuaScriptInstance C++ component to instantiate / store it) which will // rotate the scene node each frame, when the scene sends its update event LuaScriptInstance* instance = boxNode->CreateComponent<LuaScriptInstance>(); instance->CreateObject("LuaScripts/Rotator.lua", "Rotator"); // Call the script object's "SetRotationSpeed" function. WeakPtr<LuaFunction> function = instance->GetScriptObjectFunction("SetRotationSpeed"); if (function && function->BeginCall(instance)) { function->PushUserType(Vector3(10.0f, 20.0f, 30.0f), "Vector3"); function->EndCall(); } } // Create the camera. Let the starting position be at the world origin. As the fog limits maximum visible distance, we can // bring the far clip plane closer for more effective culling of distant objects cameraNode_ = scene_->CreateChild("Camera"); Camera* camera = cameraNode_->CreateComponent<Camera>(); camera->SetFarClip(100.0f); // Create a point light to the camera scene node Light* light = cameraNode_->CreateComponent<Light>(); light->SetLightType(LIGHT_POINT); light->SetRange(30.0f); }
void Urho3DQtApplication::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->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")); } // 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 AnimatingScene::CreateScene() { ResourceCache* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); // Create the Octree component to the scene so that drawable objects can be rendered. Use default volume // (-1000, -1000, -1000) to (1000, 1000, 1000) scene_->CreateComponent<Octree>(); // Create a Zone component into a child scene node. The Zone controls ambient lighting and fog settings. Like the Octree, // it also defines its volume with a bounding box, but can be rotated (so it does not need to be aligned to the world X, Y // and Z axes.) Drawable objects "pick up" the zone they belong to and use it when rendering; several zones can exist Node* zoneNode = scene_->CreateChild("Zone"); Zone* zone = zoneNode->CreateComponent<Zone>(); // Set same volume as the Octree, set a close bluish fog and some ambient light zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f)); zone->SetAmbientColor(Color(0.05f, 0.1f, 0.15f)); zone->SetFogColor(Color(0.1f, 0.2f, 0.3f)); zone->SetFogStart(10.0f); zone->SetFogEnd(100.0f); // Create randomly positioned and oriented box StaticModels in the scene const unsigned NUM_OBJECTS = 2000; for (unsigned i = 0; i < NUM_OBJECTS; ++i) { Node* boxNode = scene_->CreateChild("Box"); boxNode->SetPosition(Vector3(Random(200.0f) - 100.0f, Random(200.0f) - 100.0f, Random(200.0f) - 100.0f)); // Orient using random pitch, yaw and roll Euler angles boxNode->SetRotation(Quaternion(Random(360.0f), Random(360.0f), Random(360.0f))); StaticModel* boxObject = boxNode->CreateComponent<StaticModel>(); boxObject->SetModel(cache->GetResource<Model>("Models/Box.mdl")); boxObject->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); // Add our custom Rotator component which will rotate the scene node each frame, when the scene sends its update event. // The Rotator component derives from the base class LogicComponent, which has convenience functionality to subscribe // to the various update events, and forward them to virtual functions that can be implemented by subclasses. This way // writing logic/update components in C++ becomes similar to scripting. // Now we simply set same rotation speed for all objects Rotator* rotator = boxNode->CreateComponent<Rotator>(); rotator->SetRotationSpeed(Vector3(10.0f, 20.0f, 30.0f)); } // Create the camera. Let the starting position be at the world origin. As the fog limits maximum visible distance, we can // bring the far clip plane closer for more effective culling of distant objects cameraNode_ = scene_->CreateChild("Camera"); Camera* camera = cameraNode_->CreateComponent<Camera>(); camera->SetFarClip(100.0f); // Create a point light to the camera scene node Light* light = cameraNode_->CreateComponent<Light>(); light->SetLightType(LIGHT_POINT); light->SetRange(30.0f); }
void GizmoBar::OnTextChanged(const MGUI::FocusEvent * e) { Node * n = Editor::Instance()->GetSelectNode(); if (n == NULL) return ; String x_str, y_str, z_str; x_str.FromUnicode(mEditBox_X->GetCaption().c_str()); y_str.FromUnicode(mEditBox_Y->GetCaption().c_str()); z_str.FromUnicode(mEditBox_Z->GetCaption().c_str()); Float3 v; v.x = x_str.ToFloat(); v.y = y_str.ToFloat(); v.z = z_str.ToFloat(); switch (Gizmo::Instance()->GetOperator()) { case Gizmo::OP_MOVE: { UndoRedoManager::Instance()->Push(new UndoRedo_Move(n->GetUID(), n->GetPosition(), v)); n->SetPosition(v); Editor::Instance()->E_NodePositionChanged(); } break; case Gizmo::OP_ROTATE: { Quat q; q.FromEulerAngle(v); UndoRedoManager::Instance()->Push(new UndoRedo_Rotate(n->GetUID(), n->GetRotation(), q)); n->SetRotation(q); Editor::Instance()->E_NodeRotationChanged(); } break; case Gizmo::OP_SCALE: { UndoRedoManager::Instance()->Push(new UndoRedo_Scale(n->GetUID(), n->GetScale(), v)); n->SetScale(v); Editor::Instance()->E_NodeScaleChanged(); } break; } }
bool Gizmo3D::RotateEditNodes(Vector3 adjust) { bool moved = false; /* if (rotateSnap) { float rotateStepScaled = rotateStep * snapScale; adjust.x = Floor(adjust.x / rotateStepScaled + 0.5) * rotateStepScaled; adjust.y = Floor(adjust.y / rotateStepScaled + 0.5) * rotateStepScaled; adjust.z = Floor(adjust.z / rotateStepScaled + 0.5) * rotateStepScaled; } */ if (adjust.Length() > M_EPSILON) { moved = true; for (unsigned i = 0; i < editNodes_->Size(); ++i) { Node* node = editNodes_->At(i); Quaternion rotQuat(adjust.x_, adjust.y_, adjust.z_); if (axisMode_ == AXIS_LOCAL && editNodes_->Size() == 1) node->SetRotation(node->GetRotation() * rotQuat); else { Vector3 offset = node->GetWorldPosition() - gizmoAxisX_.axisRay_.origin_; if (node->GetParent() && node->GetParent()->GetWorldRotation() != Quaternion(1, 0, 0, 0)) rotQuat = node->GetParent()->GetWorldRotation().Inverse() * rotQuat * node->GetParent()->GetWorldRotation(); node->SetRotation(rotQuat * node->GetRotation()); Vector3 newPosition = gizmoAxisX_.axisRay_.origin_ + rotQuat * offset; if (node->GetParent()) newPosition = node->GetParent()->WorldToLocal(newPosition); node->SetPosition(newPosition); } } } return moved; }
//============================================================================= // sync wheels for rendering //============================================================================= void Vehicle::PostUpdate(float ) { for ( int i = 0; i < m_vehicle->getNumWheels(); i++ ) { m_vehicle->updateWheelTransform( i, true ); btTransform transform = m_vehicle->getWheelTransformWS( i ); Vector3 v3Origin = ToVector3( transform.getOrigin() ); Quaternion qRot = ToQuaternion( transform.getRotation() ); Node *pWheel = m_vpNodeWheel[ i ]; pWheel->SetPosition( v3Origin ); btWheelInfo whInfo = m_vehicle->getWheelInfo( i ); // tarting point of the ray, where the suspension connects to the chassis Vector3 v3PosLS = ToVector3( whInfo.m_chassisConnectionPointCS ); Quaternion qRotator = ( v3PosLS.x_ >= 0.0 ? Quaternion(0.0f, 0.0f, -90.0f) : Quaternion(0.0f, 0.0f, 90.0f) ); pWheel->SetRotation( qRot * qRotator ); /* const btRigidBody* const chassis = m_vehicle->getRigidBody(); // Calculate velocity of wheel wrt ground btVector3 rel_pos1 = whInfo.m_raycastInfo.m_contactPointWS - chassis->getCenterOfMassPosition(); btVector3 vel = chassis->getVelocityInLocalPoint(rel_pos1); // Calculate velocity in x & y //btScalar vz = -m_vehicle->getForward(i).dot(vel); btScalar vz = -whInfo.m_wheelDirectionCS.dot(vel); //btScalar vx = m_vehicle->getAxle(i).dot(vel); btScalar vx = whInfo.m_wheelAxleCS.dot(vel); // Calculate slip angle of wheel. btScalar slip_angle = btAtan2(vx, btFabs(vz)); */ //URHO3D_LOGINFOF("slip_angle %d: %f \n", i, slip_angle); // if(whInfo.m_skidInfo < 1.0) // URHO3D_LOGINFOF("whInfo.m_skidInfo %f \n", whInfo.m_skidInfo); } //URHO3D_LOGINFOF( "Speed: %f \n", (m_vehicle->getCurrentSpeedKmHour())); }
Node* Urho3DTemplate::CreateMushroom(const Vector3 &pos) { ResourceCache* cache = GetSubsystem<ResourceCache>(); Node* mushroomNode = scene_->CreateChild("Mushroom"); mushroomNode->SetPosition(pos); mushroomNode->SetRotation(Quaternion(0.0f, Random(360.0f), 0.0f)); mushroomNode->SetScale(2.0f + Random(0.5f)); StaticModel* mushroomObject = mushroomNode->CreateComponent<StaticModel>(); mushroomObject->SetModel(cache->GetResource<Model>("Models/Mushroom.mdl")); mushroomObject->SetMaterial(cache->GetResource<Material>("Materials/Mushroom.xml")); mushroomObject->SetCastShadows(true); return mushroomNode; }
void on_tick(const interface::TickEvent &event) { static uint a = 0; if(((a++) % 100) == 0){ main_context::access(m_server, [&](main_context::Interface *imc){ Scene *scene = imc->check_scene(m_main_scene); Node *n = scene->GetChild("Testbox"); //n->SetPosition(Vector3(0.0f, 8.0f, 0.0f)); n->SetRotation(Quaternion(30, 60, 90)); //n->SetPosition(Vector3(0.0f, 6.0f, 0.0f)); //n->SetPosition(Vector3(0.0f, 4.0f, 0.0f)); n->SetPosition(Vector3(-0.5f, 8.0f, 0.0f)); }); return; } }
void GameApplication::InitGridModels() { for(int x = 0;x < 4;x ++) { for(int y = 0;y < 4;y ++) { char szName[128]; sprintf(szName,"Node_%d_%d",x,y); Node* pNode = add_object(scene_,szName, enObjectType_StaticModel,0,0,0,"Models/Box.mdl",NULL); pNode->SetPosition(Vector3(x - 2 + 0.5,0,y - 2 + 0.5)); pNode->SetRotation(Quaternion(0.2,0,0)); gridNodes[y][x] = pNode; } } UpdateShow(); }
void CharacterDemo::CreateCharacter() { ResourceCache* cache = GetSubsystem<ResourceCache>(); Node* objectNode = scene_->CreateChild("Jack"); objectNode->SetPosition(Vector3(0.0f, 1.0f, 0.0f)); // spin node Node* adjustNode = objectNode->CreateChild("AdjNode"); adjustNode->SetRotation( Quaternion(180, Vector3(0,1,0) ) ); // Create the rendering component + animation controller AnimatedModel* object = adjustNode->CreateComponent<AnimatedModel>(); object->SetModel(cache->GetResource<Model>("Models/Mutant/Mutant.mdl")); object->SetMaterial(cache->GetResource<Material>("Models/Mutant/Materials/mutant_M.xml")); object->SetCastShadows(true); adjustNode->CreateComponent<AnimationController>(); // Set the head bone for manual control object->GetSkeleton().GetBone("Mutant:Head")->animated_ = false; // Create rigidbody, and set non-zero mass so that the body becomes dynamic RigidBody* body = objectNode->CreateComponent<RigidBody>(); body->SetCollisionLayer(1); body->SetMass(1.0f); // Set zero angular factor so that physics doesn't turn the character on its own. // Instead we will control the character yaw manually body->SetAngularFactor(Vector3::ZERO); // Set the rigidbody to signal collision also when in rest, so that we get ground collisions properly body->SetCollisionEventMode(COLLISION_ALWAYS); // Set a capsule shape for collision CollisionShape* shape = objectNode->CreateComponent<CollisionShape>(); shape->SetCapsule(0.7f, 1.8f, Vector3(0.0f, 0.9f, 0.0f)); // Create the character logic component, which takes care of steering the rigidbody // Remember it so that we can set the controls. Use a WeakPtr because the scene hierarchy already owns it // and keeps it alive as long as it's not removed from the hierarchy character_ = objectNode->CreateComponent<Character>(); }
void Main::CreateScene() { ResourceCache* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); scene_->CreateComponent<Octree>(); Node* lightNode = scene_->CreateChild("DirectionalLight"); lightNode->SetDirection(Vector3(0.6f, -1.0f, 0.8f)); Light* light = lightNode->CreateComponent<Light>(); light->SetLightType(LIGHT_DIRECTIONAL); Node* node = scene_->CreateChild("ExampleModel"); node->SetPosition(Vector3(0.0f, -0.5f, 0.0f)); node->SetRotation(Quaternion(0.0f, 135.0f, 0.0f)); StaticModel* object = node->CreateComponent<StaticModel>(); object->SetModel(cache->GetResource<Model>("Models/ExampleModel.mdl")); object->SetMaterial(cache->GetResource<Material>("Materials/Material.xml")); cameraNode_ = scene_->CreateChild("Camera"); cameraNode_->CreateComponent<Camera>(); cameraNode_->SetPosition(Vector3(0.0f, 1.0f, -5.0f)); }
void Hello3DUI::InitScene() { auto* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); scene_->CreateComponent<Octree>(); auto* zone = scene_->CreateComponent<Zone>(); zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f)); zone->SetFogColor(Color::GRAY); zone->SetFogStart(100.0f); zone->SetFogEnd(300.0f); // Create a child scene node (at world origin) and a StaticModel component into it. Node* boxNode = scene_->CreateChild("Box"); boxNode->SetScale(Vector3(5.0f, 5.0f, 5.0f)); boxNode->SetRotation(Quaternion(90, Vector3::LEFT)); // Create a box model and hide it initially. auto* boxModel = boxNode->CreateComponent<StaticModel>(); boxModel->SetModel(cache->GetResource<Model>("Models/Box.mdl")); boxNode->SetEnabled(false); // Create a camera. cameraNode_ = scene_->CreateChild("Camera"); cameraNode_->CreateComponent<Camera>(); // Set an initial position for the camera scene node. cameraNode_->SetPosition(Vector3(0.0f, 0.0f, -10.0f)); // Set up a viewport so 3D scene can be visible. auto* renderer = GetSubsystem<Renderer>(); ea::shared_ptr<Viewport> viewport(new Viewport(context_, scene_, cameraNode_->GetComponent<Camera>())); renderer->SetViewport(0, viewport); // Subscribe to update event and animate cube and handle input. SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(Hello3DUI, HandleUpdate)); }
void on_tick(const interface::TickEvent &event) { log_d(MODULE, "entitytest::on_tick"); static uint a = 0; if(((a++) % 100) == 0){ main_context::access(m_server, [&](main_context::Interface *imc){ Scene *scene = imc->check_scene(m_main_scene); Node *n = scene->GetChild("Box"); n->SetPosition(Vector3(0.0f, 6.0f, 0.0f)); n->SetRotation(Quaternion(30, 60, 90)); Node *n2 = scene->GetChild("Box2"); n2->SetPosition(Vector3(-0.4f, 8.0f, 0.0f)); n2->SetRotation(Quaternion(30, 60, 90)); m_slow_count++; if(m_slow_count == 2){ Node *n = scene->CreateChild("Box"); n->SetPosition(Vector3(0.0f, 10.0f, 0.0f)); n->SetScale(Vector3(1.0f, 1.0f, 1.0f)); RigidBody *body = n->CreateComponent<RigidBody>(); CollisionShape *shape = n->CreateComponent<CollisionShape>(); shape->SetBox(Vector3::ONE); body->SetMass(1.0); body->SetFriction(0.75f); // Model and material is set on client } }); return; } main_context::access(m_server, [&](main_context::Interface *imc){ Scene *scene = imc->check_scene(m_main_scene); Node *n = scene->GetChild("Box"); //n->Translate(Vector3(0.1f, 0, 0)); Vector3 p = n->GetPosition(); log_v(MODULE, "Position: %s", p.ToString().CString()); }); }
void RenderToTexture::CreateScene() { ResourceCache* cache = GetSubsystem<ResourceCache>(); { // Create the scene which will be rendered to a texture rttScene_ = new Scene(context_); // Create octree, use default volume (-1000, -1000, -1000) to (1000, 1000, 1000) rttScene_->CreateComponent<Octree>(); // Create a Zone for ambient light & fog control Node* zoneNode = rttScene_->CreateChild("Zone"); Zone* zone = zoneNode->CreateComponent<Zone>(); // Set same volume as the Octree, set a close bluish fog and some ambient light zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f)); zone->SetAmbientColor(Color(0.05f, 0.1f, 0.15f)); zone->SetFogColor(Color(0.1f, 0.2f, 0.3f)); zone->SetFogStart(10.0f); zone->SetFogEnd(100.0f); // Create randomly positioned and oriented box StaticModels in the scene const unsigned NUM_OBJECTS = 2000; for (unsigned i = 0; i < NUM_OBJECTS; ++i) { Node* boxNode = rttScene_->CreateChild("Box"); boxNode->SetPosition(Vector3(Random(200.0f) - 100.0f, Random(200.0f) - 100.0f, Random(200.0f) - 100.0f)); // Orient using random pitch, yaw and roll Euler angles boxNode->SetRotation(Quaternion(Random(360.0f), Random(360.0f), Random(360.0f))); StaticModel* boxObject = boxNode->CreateComponent<StaticModel>(); boxObject->SetModel(cache->GetResource<Model>("Models/Box.mdl")); boxObject->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); // Add our custom Rotator component which will rotate the scene node each frame, when the scene sends its update event. // Simply set same rotation speed for all objects Rotator* rotator = boxNode->CreateComponent<Rotator>(); rotator->SetRotationSpeed(Vector3(10.0f, 20.0f, 30.0f)); } // Create a camera for the render-to-texture scene. Simply leave it at the world origin and let it observe the scene rttCameraNode_ = rttScene_->CreateChild("Camera"); Camera* camera = rttCameraNode_->CreateComponent<Camera>(); camera->SetFarClip(100.0f); // Create a point light to the camera scene node Light* light = rttCameraNode_->CreateComponent<Light>(); light->SetLightType(LIGHT_POINT); light->SetRange(30.0f); } { // Create the scene in which we move around scene_ = new Scene(context_); // Create octree, use also default volume (-1000, -1000, -1000) to (1000, 1000, 1000) scene_->CreateComponent<Octree>(); // 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.1f, 0.1f, 0.1f)); zone->SetFogStart(100.0f); zone->SetFogEnd(300.0f); // Create a directional light without shadows Node* lightNode = scene_->CreateChild("DirectionalLight"); lightNode->SetDirection(Vector3(0.5f, -1.0f, 0.5f)); Light* light = lightNode->CreateComponent<Light>(); light->SetLightType(LIGHT_DIRECTIONAL); light->SetColor(Color(0.2f, 0.2f, 0.2f)); light->SetSpecularIntensity(1.0f); // Create a "floor" consisting of several tiles for (int y = -5; y <= 5; ++y) { for (int x = -5; x <= 5; ++x) { Node* floorNode = scene_->CreateChild("FloorTile"); floorNode->SetPosition(Vector3(x * 20.5f, -0.5f, y * 20.5f)); floorNode->SetScale(Vector3(20.0f, 1.0f, 20.f)); StaticModel* floorObject = floorNode->CreateComponent<StaticModel>(); floorObject->SetModel(cache->GetResource<Model>("Models/Box.mdl")); floorObject->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); } } // Create a "screen" like object for viewing the second scene. Construct it from two StaticModels, a box for the frame // and a plane for the actual view { Node* boxNode = scene_->CreateChild("ScreenBox"); boxNode->SetPosition(Vector3(0.0f, 10.0f, 0.0f)); boxNode->SetScale(Vector3(21.0f, 16.0f, 0.5f)); StaticModel* boxObject = boxNode->CreateComponent<StaticModel>(); boxObject->SetModel(cache->GetResource<Model>("Models/Box.mdl")); boxObject->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); Node* screenNode = scene_->CreateChild("Screen"); screenNode->SetPosition(Vector3(0.0f, 10.0f, -0.27f)); screenNode->SetRotation(Quaternion(-90.0f, 0.0f, 0.0f)); screenNode->SetScale(Vector3(20.0f, 0.0f, 15.0f)); StaticModel* screenObject = screenNode->CreateComponent<StaticModel>(); screenObject->SetModel(cache->GetResource<Model>("Models/Plane.mdl")); // Create a renderable texture (1024x768, RGB format), enable bilinear filtering on it SharedPtr<Texture2D> renderTexture(new Texture2D(context_)); renderTexture->SetSize(1024, 768, Graphics::GetRGBFormat(), TEXTURE_RENDERTARGET); renderTexture->SetFilterMode(FILTER_BILINEAR); // Create a new material from scratch, use the diffuse unlit technique, assign the render texture // as its diffuse texture, then assign the material to the screen plane object SharedPtr<Material> renderMaterial(new Material(context_)); renderMaterial->SetTechnique(0, cache->GetResource<Technique>("Techniques/DiffUnlit.xml")); renderMaterial->SetTexture(TU_DIFFUSE, renderTexture); screenObject->SetMaterial(renderMaterial); // Get the texture's RenderSurface object (exists when the texture has been created in rendertarget mode) // and define the viewport for rendering the second scene, similarly as how backbuffer viewports are defined // to the Renderer subsystem. By default the texture viewport will be updated when the texture is visible // in the main view RenderSurface* surface = renderTexture->GetRenderSurface(); SharedPtr<Viewport> rttViewport(new Viewport(context_, rttScene_, rttCameraNode_->GetComponent<Camera>())); surface->SetViewport(0, rttViewport); } // Create the camera which we will move around. 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, 7.0f, -30.0f)); } }
void PhysicsStressTest::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.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 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>(); CollisionShape* shape = floorNode->CreateComponent<CollisionShape>(); shape->SetBox(Vector3::ONE); } { // Create static mushrooms with triangle mesh collision const unsigned NUM_MUSHROOMS = 50; for (unsigned i = 0; i < NUM_MUSHROOMS; ++i) { Node* mushroomNode = scene_->CreateChild("Mushroom"); mushroomNode->SetPosition(Vector3(Random(400.0f) - 200.0f, 0.0f, Random(400.0f) - 200.0f)); mushroomNode->SetRotation(Quaternion(0.0f, Random(360.0f), 0.0f)); mushroomNode->SetScale(5.0f + Random(5.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); RigidBody* body = mushroomNode->CreateComponent<RigidBody>(); CollisionShape* shape = mushroomNode->CreateComponent<CollisionShape>(); // By default the highest LOD level will be used, the LOD level can be passed as an optional parameter shape->SetTriangleMesh(mushroomObject->GetModel()); } } { // Create a large amount of falling physics objects const unsigned NUM_OBJECTS = 1000; for (unsigned i = 0; i < NUM_OBJECTS; ++i) { Node* boxNode = scene_->CreateChild("Box"); boxNode->SetPosition(Vector3(0.0f, i * 2.0f + 100.0f, 0.0f)); StaticModel* boxObject = boxNode->CreateComponent<StaticModel>(); boxObject->SetModel(cache->GetResource<Model>("Models/Box.mdl")); boxObject->SetMaterial(cache->GetResource<Material>("Materials/StoneSmall.xml")); boxObject->SetCastShadows(true); // Give the RigidBody mass to make it movable and also adjust friction RigidBody* body = boxNode->CreateComponent<RigidBody>(); body->SetMass(1.0f); body->SetFriction(1.0f); // Disable collision event signaling to reduce CPU load of the physics simulation body->SetCollisionEventMode(COLLISION_NEVER); CollisionShape* shape = boxNode->CreateComponent<CollisionShape>(); shape->SetBox(Vector3::ONE); } } // 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)); }
void VehicleDemo::CreateScene() { ResourceCache* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); // Create scene subsystem components scene_->CreateComponent<Octree>(); scene_->CreateComponent<PhysicsWorld>(); // 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)); // 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.5f, 0.5f, 0.7f)); 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(10.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 1000 mushrooms in the terrain. Always face outward along the terrain normal const unsigned NUM_MUSHROOMS = 1000; for (unsigned i = 0; i < NUM_MUSHROOMS; ++i) { Node* objectNode = scene_->CreateChild("Mushroom"); Vector3 position(Random(2000.0f) - 1000.0f, 0.0f, Random(2000.0f) - 1000.0f); position.y_ = terrain->GetHeight(position) - 0.1f; 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>("Models/Mushroom.mdl")); object->SetMaterial(cache->GetResource<Material>("Materials/Mushroom.xml")); object->SetCastShadows(true); RigidBody* body = objectNode->CreateComponent<RigidBody>(); body->SetCollisionLayer(2); CollisionShape* shape = objectNode->CreateComponent<CollisionShape>(); shape->SetTriangleMesh(object->GetModel(), 0); } }
void LightAnimation::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 point light to the world so that we can see something. Node* lightNode = scene_->CreateChild("PointLight"); Light* light = lightNode->CreateComponent<Light>(); light->SetLightType(LIGHT_POINT); light->SetRange(10.0f); // Create light animation SharedPtr<ObjectAnimation> lightAnimation(new ObjectAnimation(context_)); // Create light position animation SharedPtr<ValueAnimation> positionAnimation(new ValueAnimation(context_)); // Use spline interpolation method positionAnimation->SetInterpolationMethod(IM_SPLINE); // Set spline tension positionAnimation->SetSplineTension(0.7f); positionAnimation->SetKeyFrame(0.0f, Vector3(-30.0f, 5.0f, -30.0f)); positionAnimation->SetKeyFrame(1.0f, Vector3( 30.0f, 5.0f, -30.0f)); positionAnimation->SetKeyFrame(2.0f, Vector3( 30.0f, 5.0f, 30.0f)); positionAnimation->SetKeyFrame(3.0f, Vector3(-30.0f, 5.0f, 30.0f)); positionAnimation->SetKeyFrame(4.0f, Vector3(-30.0f, 5.0f, -30.0f)); // Set position animation lightAnimation->AddAttributeAnimation("Position", positionAnimation); // Create text animation SharedPtr<ValueAnimation> textAnimation(new ValueAnimation(context_)); textAnimation->SetKeyFrame(0.0f, "WHITE"); textAnimation->SetKeyFrame(1.0f, "RED"); textAnimation->SetKeyFrame(2.0f, "YELLOW"); textAnimation->SetKeyFrame(3.0f, "GREEN"); textAnimation->SetKeyFrame(4.0f, "WHITE"); GetSubsystem<UI>()->GetRoot()->GetChild(String("animatingText"))->SetAttributeAnimation("Text", textAnimation); // Create light color animation SharedPtr<ValueAnimation> colorAnimation(new ValueAnimation(context_)); colorAnimation->SetKeyFrame(0.0f, Color::WHITE); colorAnimation->SetKeyFrame(1.0f, Color::RED); colorAnimation->SetKeyFrame(2.0f, Color::YELLOW); colorAnimation->SetKeyFrame(3.0f, Color::GREEN); colorAnimation->SetKeyFrame(4.0f, Color::WHITE); // Set Light component's color animation lightAnimation->AddAttributeAnimation("@Light/Color", colorAnimation); // Apply light animation to light node lightNode->SetObjectAnimation(lightAnimation); // 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->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")); } // 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 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]; const AnimationChannelFlags 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 CharacterDemo::CreateScene() { ResourceCache* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); // Create scene subsystem components scene_->CreateComponent<Octree>(); scene_->CreateComponent<PhysicsWorld>(); // 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(300.0f); GetSubsystem<Renderer>()->SetViewport(0, new Viewport(context_, scene_, camera)); // 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.5f, 0.5f, 0.7f)); zone->SetFogStart(100.0f); zone->SetFogEnd(300.0f); zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.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(10.0f, 50.0f, 200.0f, 0.0f, 0.8f)); light->SetSpecularIntensity(0.5f); // Create the floor object Node* floorNode = scene_->CreateChild("Floor"); floorNode->SetPosition(Vector3(0.0f, -0.5f, 0.0f)); floorNode->SetScale(Vector3(200.0f, 1.0f, 200.0f)); StaticModel* object = floorNode->CreateComponent<StaticModel>(); object->SetModel(cache->GetResource<Model>("Models/Box.mdl")); object->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); RigidBody* body = floorNode->CreateComponent<RigidBody>(); // Use collision layer bit 2 to mark world scenery. This is what we will raycast against to prevent camera from going // inside geometry body->SetCollisionLayer(2); CollisionShape* shape = floorNode->CreateComponent<CollisionShape>(); shape->SetBox(Vector3::ONE); // Create mushrooms of varying sizes const unsigned NUM_MUSHROOMS = 60; for (unsigned i = 0; i < NUM_MUSHROOMS; ++i) { Node* objectNode = scene_->CreateChild("Mushroom"); objectNode->SetPosition(Vector3(Random(180.0f) - 90.0f, 0.0f, Random(180.0f) - 90.0f)); objectNode->SetRotation(Quaternion(0.0f, Random(360.0f), 0.0f)); objectNode->SetScale(2.0f + Random(5.0f)); StaticModel* object = objectNode->CreateComponent<StaticModel>(); object->SetModel(cache->GetResource<Model>("Models/Mushroom.mdl")); object->SetMaterial(cache->GetResource<Material>("Materials/Mushroom.xml")); object->SetCastShadows(true); RigidBody* body = objectNode->CreateComponent<RigidBody>(); body->SetCollisionLayer(2); CollisionShape* shape = objectNode->CreateComponent<CollisionShape>(); shape->SetTriangleMesh(object->GetModel(), 0); } // Create movable boxes. Let them fall from the sky at first const unsigned NUM_BOXES = 100; for (unsigned i = 0; i < NUM_BOXES; ++i) { float scale = Random(2.0f) + 0.5f; Node* objectNode = scene_->CreateChild("Box"); objectNode->SetPosition(Vector3(Random(180.0f) - 90.0f, Random(10.0f) + 10.0f, Random(180.0f) - 90.0f)); objectNode->SetRotation(Quaternion(Random(360.0f), Random(360.0f), Random(360.0f))); objectNode->SetScale(scale); StaticModel* object = objectNode->CreateComponent<StaticModel>(); object->SetModel(cache->GetResource<Model>("Models/Box.mdl")); object->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); object->SetCastShadows(true); RigidBody* body = objectNode->CreateComponent<RigidBody>(); body->SetCollisionLayer(2); // Bigger boxes will be heavier and harder to move body->SetMass(scale * 2.0f); CollisionShape* shape = objectNode->CreateComponent<CollisionShape>(); shape->SetBox(Vector3::ONE); } }
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)); }
void AnimatedSprite2D::UpdateAnimation(float timeStep) { if (!animation_) return; currentTime_ += timeStep * speed_; float time; float animtationLength = animation_->GetLength(); if (looped_) { time = fmodf(currentTime_, animtationLength); if (time < 0.0f) time += animation_->GetLength(); } else time = Clamp(currentTime_, 0.0f, animtationLength); 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_ = Urho3D::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]; 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->SetUseHotSpot(nodeInfo.value.useHotSpot_); staticSprite->SetHotSpot(nodeInfo.value.hotSpot_); } } } } MarkForUpdate(); }
void Decals::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. Occluders will be software rasterized before // rendering to a low-resolution depth-only buffer to test the objects in the view frustum for visibility 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 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)); }
void Ragdolls::CreateScene() { ResourceCache* cache = GetContext()->m_ResourceCache.get(); scene_ = new Scene(GetContext()); // 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.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 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 Trigger mode makes the rigid body only detect collisions, but impart no forces on the // colliding objects body->SetTrigger(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(GetContext()); Camera* camera = cameraNode_->CreateComponent<Camera>(); camera->setFarClipDistance(300.0f); // Set an initial position for the camera scene node above the floor cameraNode_->SetPosition(Vector3(0.0f, 3.0f, -20.0f)); }
void Vehicle::Init() { auto* vehicle = node_->CreateComponent<RaycastVehicle>(); vehicle->Init(); auto* hullBody = node_->GetComponent<RigidBody>(); hullBody->SetMass(800.0f); hullBody->SetLinearDamping(0.2f); // Some air resistance hullBody->SetAngularDamping(0.5f); hullBody->SetCollisionLayer(1); // This function is called only from the main program when initially creating the vehicle, not on scene load auto* cache = GetSubsystem<ResourceCache>(); auto* hullObject = node_->CreateComponent<StaticModel>(); // Setting-up collision shape auto* hullColShape = node_->CreateComponent<CollisionShape>(); Vector3 v3BoxExtents = Vector3::ONE; hullColShape->SetBox(v3BoxExtents); node_->SetScale(Vector3(2.3f, 1.0f, 4.0f)); hullObject->SetModel(cache->GetResource<Model>("Models/Box.mdl")); hullObject->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); hullObject->SetCastShadows(true); float connectionHeight = -0.4f; bool isFrontWheel = true; Vector3 wheelDirection(0, -1, 0); Vector3 wheelAxle(-1, 0, 0); // We use not scaled coordinates here as everything will be scaled. // Wheels are on bottom at edges of the chassis // Note we don't set wheel nodes as children of hull (while we could) to avoid scaling to affect them. float wheelX = CHASSIS_WIDTH / 2.0f - wheelWidth_; // Front left connectionPoints_[0] = Vector3(-wheelX, connectionHeight, 2.5f - GetWheelRadius() * 2.0f); // Front right connectionPoints_[1] = Vector3(wheelX, connectionHeight, 2.5f - GetWheelRadius() * 2.0f); // Back left connectionPoints_[2] = Vector3(-wheelX, connectionHeight, -2.5f + GetWheelRadius() * 2.0f); // Back right connectionPoints_[3] = Vector3(wheelX, connectionHeight, -2.5f + GetWheelRadius() * 2.0f); const Color LtBrown(0.972f, 0.780f, 0.412f); for (int id = 0; id < sizeof(connectionPoints_) / sizeof(connectionPoints_[0]); id++) { Node* wheelNode = GetScene()->CreateChild(); Vector3 connectionPoint = connectionPoints_[id]; // Front wheels are at front (z > 0) // back wheels are at z < 0 // Setting rotation according to wheel position bool isFrontWheel = connectionPoints_[id].z_ > 0.0f; wheelNode->SetRotation(connectionPoint.x_ >= 0.0 ? Quaternion(0.0f, 0.0f, -90.0f) : Quaternion(0.0f, 0.0f, 90.0f)); wheelNode->SetWorldPosition(node_->GetWorldPosition() + node_->GetWorldRotation() * connectionPoints_[id]); vehicle->AddWheel(wheelNode, wheelDirection, wheelAxle, suspensionRestLength_, wheelRadius_, isFrontWheel); vehicle->SetWheelSuspensionStiffness(id, suspensionStiffness_); vehicle->SetWheelDampingRelaxation(id, suspensionDamping_); vehicle->SetWheelDampingCompression(id, suspensionCompression_); vehicle->SetWheelFrictionSlip(id, wheelFriction_); vehicle->SetWheelRollInfluence(id, rollInfluence_); wheelNode->SetScale(Vector3(1.0f, 0.65f, 1.0f)); auto* pWheel = wheelNode->CreateComponent<StaticModel>(); pWheel->SetModel(cache->GetResource<Model>("Models/Cylinder.mdl")); pWheel->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); pWheel->SetCastShadows(true); CreateEmitter(connectionPoints_[id]); } emittersCreated = true; vehicle->ResetWheels(); }
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("Directional light"); 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 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); // Enable full blending weight and looping state->SetWeight(1.0f); state->SetLooped(true); // 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)); }