bool psEffectObj::Update(csTicks elapsed) { if (!anchor || !anchor->IsReady() || !anchorMesh->GetMovable()->GetSectors()->GetCount()) // wait for anchor to be ready return true; const static csMatrix3 UP_FIX(1,0,0, 0,0,1, 0,1,0); const static csMatrix3 billboardFix = csXRotMatrix3(-3.14f/2.0f); iMovable* anchorMovable = anchorMesh->GetMovable(); iMovable* meshMovable = mesh->GetMovable(); csVector3 anchorPosition = anchorMovable->GetFullPosition(); life += elapsed; if (life > animLength && killTime <= 0) { life %= animLength; if (!life) { life += animLength; } } isAlive |= (life >= birth); if (isAlive) { meshMovable->SetSector(anchorMovable->GetSectors()->Get(0)); meshMovable->SetPosition(anchorPosition); if (dir == DT_NONE) { matBase = anchorMovable->GetFullTransform().GetT2O(); } } csMatrix3 matTransform; if (keyFrames->GetSize() == 0) { if (dir == DT_CAMERA) { // note that this is *very* expensive csVector3 camDir = -view->GetCamera()->GetTransform().GetO2TTranslation() + anchorPosition; csReversibleTransform rt; rt.LookAt(camDir, csVector3(0.f,1.f,0.f)); matBase = rt.GetT2O() * UP_FIX; } else if (dir == DT_BILLBOARD) { matBase = view->GetCamera()->GetTransform().GetT2O() * billboardFix; } baseScale = scale; matTransform = matBase / baseScale; } else { currKeyFrame = FindKeyFrameByTime(life); nextKeyFrame = (currKeyFrame + 1) % keyFrames->GetSize(); // grab and lerp values - expensive float lerpfactor = LERP_FACTOR; csVector3 lerpRot = LERP_VEC_KEY(KA_ROT,lerpfactor); csVector3 lerpSpin = LERP_VEC_KEY(KA_SPIN,lerpfactor); csVector3 objOffset = LERP_VEC_KEY(KA_POS,lerpfactor); // calculate rotation from lerped values - expensive csMatrix3 matRot = csZRotMatrix3(lerpRot.z) * csYRotMatrix3(lerpRot.y) * csXRotMatrix3(lerpRot.x); if (dir != DT_CAMERA && dir != DT_BILLBOARD) { matRot *= matBase; } // calculate new position csVector3 newPos = matRot * csVector3(-objOffset.x, objOffset.y, -objOffset.z); if (dir == DT_CAMERA) { // note that this is *very* expensive - again csVector3 camDir = -view->GetCamera()->GetTransform().GetO2TTranslation() + anchorPosition + newPos; csReversibleTransform rt; rt.LookAt(camDir, csVector3(sinf(lerpSpin.y),cosf(lerpSpin.y),0.f)); matBase = rt.GetT2O() * UP_FIX; newPos = rt.GetT2O() * newPos; // rotate and spin should have no effect on the transform when we want it to face the camera matTransform = matBase; } else if (dir == DT_BILLBOARD) { matBase = view->GetCamera()->GetTransform().GetT2O() * billboardFix; matTransform = matBase; } else { matTransform = matRot; matTransform *= csZRotMatrix3(lerpSpin.z) * csYRotMatrix3(lerpSpin.y) * csXRotMatrix3(lerpSpin.x); } // SCALE baseScale = LERP_KEY(KA_SCALE,lerpfactor) * scale; matTransform /= baseScale; // adjust position meshMovable->SetPosition(anchorPosition+newPos); } // set new transform meshMovable->SetTransform(matTransform); meshMovable->UpdateMove(); if (killTime > 0) { killTime -= elapsed; if (killTime <= 0) return false; } return true; }
csMatrix3 psEffectObj::BuildRotMatrix(const csVector3 &up) const { csVector3 forward = csVector3(0, 0, 1); csVector3 right = up % forward; return csMatrix3(right.x, right.y, right.z, up.x, up.y, up.z, forward.x, forward.y, forward.z); }
bool csShaderProgram::ProgramParamParser::ParseProgramParam ( iDocumentNode* node, ProgramParam& param, uint types) { const char* type = node->GetAttributeValue ("type"); if (type == 0) { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "No %s attribute", CS::Quote::Single ("type")); return false; } // Var for static data csRef<csShaderVariable> var; var.AttachNew (new csShaderVariable (CS::InvalidShaderVarStringID)); ProgramParamType paramType = ParamInvalid; if (strcmp (type, "shadervar") == 0) { const char* value = node->GetContentsValue(); if (!value) { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "Node has no contents"); return false; } CS::Graphics::ShaderVarNameParser nameParse (value); param.name = stringsSvName->Request (nameParse.GetShaderVarName()); for (size_t n = 0; n < nameParse.GetIndexNum(); n++) { param.indices.Push (nameParse.GetIndexValue (n)); } param.valid = true; return true; } else if (strcmp (type, "int") == 0) { paramType = ParamInt; } else if (strcmp (type, "float") == 0) { paramType = ParamFloat; } else if (strcmp (type, "vector2") == 0) { paramType = ParamVector2; } else if (strcmp (type, "vector3") == 0) { paramType = ParamVector3; } else if (strcmp (type, "vector4") == 0) { paramType = ParamVector4; } else if (strcmp (type, "matrix") == 0) { paramType = ParamMatrix; } else if (strcmp (type, "transform") == 0) { paramType = ParamTransform; } else if ((strcmp (type, "expression") == 0) || (strcmp (type, "expr") == 0)) { // Parse exp and save it csRef<iShaderVariableAccessor> acc = synsrv->ParseShaderVarExpr (node); var->SetAccessor (acc); param.var = var; param.valid = true; return true; } else if (strcmp (type, "array") == 0) { csArray<ProgramParam> allParams; ProgramParam tmpParam; csRef<iDocumentNodeIterator> it = node->GetNodes (); while (it->HasNext ()) { csRef<iDocumentNode> child = it->Next (); ParseProgramParam (child, tmpParam, types & 0x3F); allParams.Push (tmpParam); } //Save the params var->SetType (csShaderVariable::ARRAY); var->SetArraySize (allParams.GetSize ()); for (uint i = 0; i < allParams.GetSize (); i++) { var->SetArrayElement (i, allParams[i].var); } paramType = ParamArray; } else { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "Unknown type %s", CS::Quote::Single (type)); return false; } if (!(types & paramType)) { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "Type %s not supported by this parameter", CS::Quote::Single (type)); return false; } const uint directValueTypes = ParamInt | ParamFloat | ParamVector2 | ParamVector3 | ParamVector4 | ParamMatrix | ParamTransform; switch (paramType & directValueTypes) { case ParamInvalid: return false; break; case ParamInt: { int x = node->GetContentsValueAsInt (); var->SetValue (x); } break; case ParamFloat: { float x = node->GetContentsValueAsFloat (); var->SetValue (x); } break; case ParamVector2: { float x, y; const char* value = node->GetContentsValue(); if (!value) { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "Node has no contents"); return false; } if (csScanStr (value, "%f,%f", &x, &y) != 2) { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "Couldn't parse vector2 %s", CS::Quote::Single (value)); return false; } var->SetValue (csVector2 (x,y)); } break; case ParamVector3: { float x, y, z; const char* value = node->GetContentsValue(); if (!value) { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "Node has no contents"); return false; } if (csScanStr (value, "%f,%f,%f", &x, &y, &z) != 3) { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "Couldn't parse vector3 %s", CS::Quote::Single (value)); return false; } var->SetValue (csVector3 (x,y,z)); } break; case ParamVector4: { float x, y, z, w; const char* value = node->GetContentsValue(); if (!value) { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "Node has no contents"); return false; } if (csScanStr (value, "%f,%f,%f,%f", &x, &y, &z, &w) != 4) { synsrv->Report ("crystalspace.graphics3d.shader.common", CS_REPORTER_SEVERITY_WARNING, node, "Couldn't parse vector4 %s", CS::Quote::Single (value)); return false; } var->SetValue (csVector4 (x,y,z,w)); } break; case ParamMatrix: { csMatrix3 matrix; if (!synsrv->ParseMatrix (node, matrix)) return false; var->SetValue (matrix); } break; case ParamTransform: { csReversibleTransform t; csRef<iDocumentNode> matrix_node = node->GetNode ("matrix"); if (matrix_node) { csMatrix3 m; if (!synsrv->ParseMatrix (matrix_node, m)) return false; t.SetT2O (m); } csRef<iDocumentNode> vector_node = node->GetNode ("v"); if (vector_node) { csVector3 v; if (!synsrv->ParseVector (vector_node, v)) return false; t.SetOrigin (v); } var->SetValue (t); } break; } param.var = var; param.valid = true; return true; }
bool csWaterDemo::Initialize () { if (!csInitializer::SetupConfigManager (object_reg, "/config/waterdemo.cfg")) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "Failed to initialize config!"); return false; } if (!csInitializer::RequestPlugins (object_reg, CS_REQUEST_VFS, CS_REQUEST_PLUGIN ("crystalspace.graphics3d.opengl", iGraphics3D), CS_REQUEST_ENGINE, CS_REQUEST_IMAGELOADER, CS_REQUEST_FONTSERVER, CS_REQUEST_REPORTER, CS_REQUEST_REPORTERLISTENER, CS_REQUEST_CONSOLEOUT, CS_REQUEST_LEVELLOADER, CS_REQUEST_END)) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "Can't initialize plugins!"); return false; } FocusGained = csevFocusGained (object_reg); FocusLost = csevFocusLost (object_reg); Frame = csevFrame (object_reg); KeyboardDown = csevKeyboardDown (object_reg); if (!csInitializer::SetupEventHandler (object_reg, SimpleEventHandler)) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "Can't initialize event handler!"); return false; } // Check for commandline help. if (csCommandLineHelper::CheckHelp (object_reg)) { csCommandLineHelper::Help (object_reg); return false; } vc = csQueryRegistry<iVirtualClock> (object_reg); if (vc == 0) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "No iVirtualClock plugin!"); return false; } vfs = csQueryRegistry<iVFS> (object_reg); if (vfs == 0) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "No iVFS plugin!"); return false; } r3d = csQueryRegistry<iGraphics3D> (object_reg); if (r3d == 0) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "No iGraphics3D plugin!"); return false; } font = r3d->GetDriver2D ()->GetFontServer()->LoadFont(CSFONT_LARGE); engine = csQueryRegistry<iEngine> (object_reg); if (engine == 0) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "No iEngine plugin!"); return false; } kbd = csQueryRegistry<iKeyboardDriver> (object_reg); if (kbd == 0) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "No iKeyboardDriver plugin!"); return false; } mouse = csQueryRegistry<iMouseDriver> (object_reg); if (mouse == 0) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "No iMouseDriver plugin!"); return false; } csRef<iLoader> loader = csQueryRegistry<iLoader> (object_reg); if (loader == 0) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "No iLoader plugin!"); return false; } vfs->ChDir ("/tmp"); console = csQueryRegistry<iConsoleOutput> (object_reg); // Open the main system. This will open all the previously loaded plug-ins. if (!csInitializer::OpenApplication (object_reg)) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "Error opening system!"); return false; } csRef<iSector> room = engine->CreateSector ("room"); view = csPtr<iView> (new csView (engine, r3d)); view->GetCamera ()->SetSector (room); view->GetCamera ()->GetTransform ().SetOrigin (csVector3 (0, 5, 0)); view->GetCamera ()->GetTransform ().LookAt (csVector3(5,-5,20), csVector3(0,1,0)); csRef<iGraphics2D> g2d = r3d->GetDriver2D (); view->SetRectangle (0, 0, g2d->GetWidth (), g2d->GetHeight ()); bool hasAccel; if (g2d->PerformExtension ("hardware_accelerated", &hasAccel)) { csReport (object_reg, CS_REPORTER_SEVERITY_NOTIFY, "crystalspace.application.waterdemo", "Hardware acceleration %s.\n", hasAccel ? "present" : "not present"); } else { csReport (object_reg, CS_REPORTER_SEVERITY_NOTIFY, "crystalspace.application.waterdemo", "Hardware acceleration check not available.\n"); } r3d->GetDriver2D ()->SetMouseCursor( csmcNone ); csRef<iPluginManager> plugin_mgr ( csQueryRegistry<iPluginManager> (object_reg)); csRef<iStringSet> strings = csQueryRegistryTagInterface<iStringSet> (object_reg, "crystalspace.shared.stringset"); csRef<iShaderVarStringSet> stringsSvName = csQueryRegistryTagInterface<iShaderVarStringSet> (object_reg, "crystalspace.shader.variablenameset"); //get a custom renderloop csRef<iRenderLoop> rl = engine->GetRenderLoopManager ()->Create (); csRef<iRenderStepType> genType = csLoadPlugin<iRenderStepType> ( plugin_mgr, "crystalspace.renderloop.step.generic.type"); csRef<iRenderStepFactory> genFact = genType->NewFactory (); csRef<iRenderStep> step; csRef<iGenericRenderStep> genStep; step = genFact->Create (); rl->AddStep (step); genStep = scfQueryInterface<iGenericRenderStep> (step); genStep->SetShaderType ("general"); genStep->SetZBufMode (CS_ZBUF_USE); genStep->SetZOffset (false); engine->GetRenderLoopManager ()->Register ("waterdemoRL", rl); engine->SetCurrentDefaultRenderloop (rl); // Load in lighting shaders csRef<iVFS> vfs (csQueryRegistry<iVFS> (object_reg)); csRef<iFile> shaderFile = vfs->Open ("/shader/water.xml", VFS_FILE_READ); csRef<iDocumentSystem> docsys ( csQueryRegistry<iDocumentSystem> (object_reg)); csRef<iDocument> shaderDoc = docsys->CreateDocument (); shaderDoc->Parse (shaderFile, true); csRef<iShader> shader; csRef<iShaderManager> shmgr (csQueryRegistry<iShaderManager> (object_reg)); csRef<iShaderCompiler> shcom (shmgr->GetCompiler ("XMLShader")); csRef<iLoaderContext> ldr_context = engine->CreateLoaderContext (); shader = shcom->CompileShader (ldr_context, shaderDoc->GetRoot ()->GetNode ("shader")); // setup the mesh csRef<iMeshObjectType> gType = csLoadPluginCheck<iMeshObjectType> ( plugin_mgr, "crystalspace.mesh.object.genmesh"); if (!gType) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.waterdemo", "Error loading genmesh baseobject!"); return false; } gFact = gType->NewFactory (); csRef<iMeshFactoryWrapper> fw = engine->CreateMeshFactory (gFact, "waterFactory"); gFactState = scfQueryInterface<iGeneralFactoryState> (gFact); gMesh = gFact->NewInstance (); gMeshState = scfQueryInterface<iGeneralMeshState> (gMesh); gMeshState->SetShadowCasting (false); gMeshState->SetShadowReceiving (false); //setup a wrapper too gMeshW = engine->CreateMeshWrapper (gMesh, "water", room); csMatrix3 m; m.Identity (); gMeshW->GetMovable ()->SetTransform (m); gMeshW->GetMovable ()->SetPosition (csVector3(0,-5,0)); gMeshW->GetMovable ()->UpdateMove (); //setup a material csRef<iMaterial> mat = engine->CreateBaseMaterial (0); mat->SetShader (strings->Request ("general"), shader); csRef<iMaterialWrapper> matW = engine->GetMaterialList ()->NewMaterial (mat, "waterMaterial"); csRef<csImageCubeMapMaker> cubeMaker; cubeMaker.AttachNew (new csImageCubeMapMaker ()); csRef<iImage> img = loader->LoadImage ("/lib/cubemap/cubemap_rt.jpg"); cubeMaker->SetSubImage (0, img); img = loader->LoadImage ("/lib/cubemap/cubemap_lf.jpg"); cubeMaker->SetSubImage (1, img); img = loader->LoadImage ("/lib/cubemap/cubemap_up.jpg"); cubeMaker->SetSubImage (2, img); img = loader->LoadImage ("/lib/cubemap/cubemap_dn.jpg"); cubeMaker->SetSubImage (3, img); img = loader->LoadImage ("/lib/cubemap/cubemap_fr.jpg"); cubeMaker->SetSubImage (4, img); img = loader->LoadImage ("/lib/cubemap/cubemap_bk.jpg"); cubeMaker->SetSubImage (5, img); csRef<iTextureHandle> tex = r3d->GetTextureManager ()->RegisterTexture ( cubeMaker, CS_TEXTURE_3D | CS_TEXTURE_CLAMP | CS_TEXTURE_NOMIPMAPS); csRef<csShaderVariable> attvar (csPtr<csShaderVariable> ( new csShaderVariable (stringsSvName->Request ("tex diffuse")))); attvar->SetValue (tex); mat->AddVariable (attvar); gMesh->SetMaterialWrapper (matW); Width = Height = 64; water = new float[Width*Height]; water1 = new float[Width*Height]; water2 = new float[Width*Height]; memset(water,0,Width*Height*sizeof(float)); memset(water1,0,Width*Height*sizeof(float)); memset(water2,0,Width*Height*sizeof(float)); WaveSpeed = 0.3f; WaveLife = 0.1f; GridSize = 0.25f; TimeDelta = 0.12f; //setup the mesh gFactState->SetVertexCount (Width*Height); gFactState->SetTriangleCount (2*((Width-1)*(Height-1))); //setup ibuf int x, z, cnt=0,idx; csTriangle *ibuf=gFactState->GetTriangles (); for(x=0;x<(Height-1);x++) { for(z=0;z<(Width-1);z++) { idx = 2*(x*(Width-1)+z); ibuf[idx].a = x*Width+z; ibuf[idx].b = x*Width+z+1; ibuf[idx].c = (x+1)*Width+z; idx++; ibuf[idx].a = x*Width+z+1; ibuf[idx].b = (x+1)*Width+(z+1); ibuf[idx].c = (x+1)*Width+z; } } //setup our vbuf csVector3 *vbuf = gFactState->GetVertices (); cnt=0; for(x=0;x<Height;x++) { for(z=0;z<Width;z++) { idx = x*Width+z; vbuf[idx].x = x*GridSize; vbuf[idx].y = water[idx]; vbuf[idx].z = z*GridSize; } } //setup texture csVector2 *tbuf = gFactState->GetTexels (); for(x=0;x<Height;x++) { for(z=0;z<Width;z++) { idx = x*Width+z; tbuf[idx].x = (float)x/(float)Height; tbuf[idx].y = (float)z/(float)Width; } } lastSimTime = nextSimTime = 0.0f; gFactState->Invalidate (); engine->Prepare (); console->SetVisible (false); hasfocus = true; int w = r3d->GetDriver2D ()->GetWidth()/2; int h = r3d->GetDriver2D ()->GetHeight()/2; r3d->GetDriver2D ()->SetMousePosition (w, h); printer.AttachNew (new FramePrinter (object_reg)); return true; }
bool FrankieScene::CreateAvatar () { printf ("Loading Frankie...\n"); // Load animesh factory csLoadResult rc = hairTest->loader->Load ("/lib/frankie/frankie.xml"); if (!rc.success) return hairTest->ReportError ("Can't load Frankie library file!"); // Load some fur rc = hairTest->loader->Load ("/lib/hairtest/frankie_furmesh.xml"); if (!rc.success) return hairTest->ReportError ("Can't load frankie furmesh library!"); csRef<iMeshWrapper> frankieFurmeshObject = hairTest->engine->FindMeshObject("frankie_furmesh_object"); if (!frankieFurmeshObject) return hairTest->ReportError ("Can't find fur mesh object!"); csRef<iMeshFactoryWrapper> meshfact = hairTest->engine->FindMeshFactory ("franky_frankie"); if (!meshfact) return hairTest->ReportError ("Can't find Frankie's mesh factory!"); animeshFactory = scfQueryInterface<CS::Mesh::iAnimatedMeshFactory> (meshfact->GetMeshObjectFactory ()); if (!animeshFactory) return hairTest->ReportError ("Can't find Frankie's animesh factory!"); // Load bodymesh (animesh's physical properties) rc = hairTest->loader->Load ("/lib/frankie/skelfrankie_body"); if (!rc.success) return hairTest->ReportError ("Can't load Frankie's body mesh file!"); csRef<CS::Animation::iBodyManager> bodyManager = csQueryRegistry<CS::Animation::iBodyManager> (hairTest->GetObjectRegistry ()); csRef<CS::Animation::iBodySkeleton> bodySkeleton = bodyManager->FindBodySkeleton ("frankie_body"); if (!bodySkeleton) return hairTest->ReportError ("Can't find Frankie's body mesh description!"); // Create a new animation tree. The structure of the tree is: // + ragdoll controller node (root node - only if physics are enabled) // + 'LookAt' controller node // + 'speed' controller node // + animation nodes for all speeds csRef<CS::Animation::iSkeletonAnimPacketFactory> animPacketFactory = animeshFactory->GetSkeletonFactory ()->GetAnimationPacket (); // Create the 'random' node csRef<CS::Animation::iSkeletonRandomNodeFactory> randomNodeFactory = animPacketFactory->CreateRandomNode ("random"); randomNodeFactory->SetAutomaticSwitch (true); // Create the 'idle' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> idleNodeFactory = animPacketFactory->CreateAnimationNode ("idle"); idleNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("Frankie_Idle1")); // Create the 'walk_slow' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> walkSlowNodeFactory = animPacketFactory->CreateAnimationNode ("walk_slow"); walkSlowNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("Frankie_WalkSlow")); // Create the 'walk' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> walkNodeFactory = animPacketFactory->CreateAnimationNode ("walk"); walkNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("Frankie_Walk")); // Create the 'walk_fast' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> walkFastNodeFactory = animPacketFactory->CreateAnimationNode ("walk_fast"); walkFastNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("Frankie_WalkFast")); // Create the 'footing' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> footingNodeFactory = animPacketFactory->CreateAnimationNode ("footing"); footingNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("Frankie_Runs")); // Create the 'run_slow' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> runSlowNodeFactory = animPacketFactory->CreateAnimationNode ("run_slow"); runSlowNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("Frankie_RunSlow")); // Create the 'run' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> runNodeFactory = animPacketFactory->CreateAnimationNode ("run"); runNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("Frankie_Run")); // Create the 'run_fast' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> runFastNodeFactory = animPacketFactory->CreateAnimationNode ("run_fast"); runFastNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("Frankie_RunFaster")); // Create the 'run_jump' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> runJumpNodeFactory = animPacketFactory->CreateAnimationNode ("run_jump"); runJumpNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("Frankie_RunFast2Jump")); idleNodeFactory->SetAutomaticReset (true); walkSlowNodeFactory->SetAutomaticReset (true); walkNodeFactory->SetAutomaticReset (true); walkFastNodeFactory->SetAutomaticReset (true); footingNodeFactory->SetAutomaticReset (true); runSlowNodeFactory->SetAutomaticReset (true); runNodeFactory->SetAutomaticReset (true); runFastNodeFactory->SetAutomaticReset (true); runJumpNodeFactory->SetAutomaticReset (true); idleNodeFactory->SetAutomaticStop (false); walkSlowNodeFactory->SetAutomaticStop (false); walkNodeFactory->SetAutomaticStop (false); walkFastNodeFactory->SetAutomaticStop (false); footingNodeFactory->SetAutomaticStop (false); runSlowNodeFactory->SetAutomaticStop (false); runNodeFactory->SetAutomaticStop (false); runFastNodeFactory->SetAutomaticStop (false); runJumpNodeFactory->SetAutomaticStop (false); randomNodeFactory->AddNode (idleNodeFactory, 1.0f); randomNodeFactory->AddNode (walkSlowNodeFactory, 1.0f); randomNodeFactory->AddNode (walkNodeFactory, 1.0f); randomNodeFactory->AddNode (walkFastNodeFactory, 1.0f); randomNodeFactory->AddNode (footingNodeFactory, 1.0f); randomNodeFactory->AddNode (runSlowNodeFactory, 1.0f); randomNodeFactory->AddNode (runNodeFactory, 1.0f); randomNodeFactory->AddNode (runFastNodeFactory, 1.0f); randomNodeFactory->AddNode (runJumpNodeFactory, 1.0f); if (hairTest->physicsEnabled) { // Create the ragdoll controller csRef<CS::Animation::iSkeletonRagdollNodeFactory> ragdollNodeFactory = hairTest->ragdollManager->CreateAnimNodeFactory ("ragdoll"); animPacketFactory->SetAnimationRoot (ragdollNodeFactory); ragdollNodeFactory->SetBodySkeleton (bodySkeleton); ragdollNodeFactory->SetChildNode (randomNodeFactory); // Create a bone chain for the whole body and add it to the ragdoll controller. // The chain will be in kinematic mode when Frankie is alive, and in dynamic state // when Frankie has been killed. bodyChain = bodySkeleton->CreateBodyChain ("body_chain", animeshFactory->GetSkeletonFactory ()->FindBone ("Frankie_Main")); bodyChain->AddSubChain (animeshFactory->GetSkeletonFactory ()->FindBone ("CTRL_Pelvis")); bodyChain->AddSubChain (animeshFactory->GetSkeletonFactory ()->FindBone ("CTRL_Head")); ragdollNodeFactory->AddBodyChain (bodyChain, CS::Animation::STATE_KINEMATIC); // Create a bone chain for the tail of Frankie and add it to the ragdoll controller. // The chain will be in kinematic mode most of the time, and in dynamic mode when the // user ask for it with the 'f' key or when Frankie has been killed. tailChain = bodySkeleton->CreateBodyChain ("tail_chain", animeshFactory->GetSkeletonFactory ()->FindBone ("Tail_1")); tailChain->AddSubChain (animeshFactory->GetSkeletonFactory ()->FindBone ("Tail_8")); ragdollNodeFactory->AddBodyChain (tailChain, CS::Animation::STATE_KINEMATIC); } else animPacketFactory->SetAnimationRoot (randomNodeFactory); // Create the animated mesh csRef<iMeshWrapper> avatarMesh = hairTest->engine->CreateMeshWrapper (meshfact, "Frankie", hairTest->room, csVector3 (0.0f)); animesh = scfQueryInterface<CS::Mesh::iAnimatedMesh> (avatarMesh->GetMeshObject ()); // When the animated mesh is created, the animation nodes are created too. // We can therefore set them up now. CS::Animation::iSkeletonAnimNode* rootNode = animesh->GetSkeleton ()->GetAnimationPacket ()->GetAnimationRoot (); // Setup of the ragdoll controller if (hairTest->physicsEnabled) { ragdollNode = scfQueryInterface<CS::Animation::iSkeletonRagdollNode> (rootNode->FindNode ("ragdoll")); // Start the ragdoll animation node in order to have the rigid bodies created ragdollNode->SetDynamicSystem (hairTest->dynamicSystem); ragdollNode->Play (); } // Load fur material rc = hairTest-> loader ->Load ("/lib/hairtest/fur_material_frankie.xml"); if (!rc.success) hairTest->ReportError("Can't load Fur library file!"); // Load material shader csRef<iMaterialWrapper> materialWrapper = hairTest->engine->FindMaterial("kajiya_and_kay_frankie"); if (!materialWrapper) hairTest->ReportError("Can't find fur material!"); // Surface properties animesh->GetSubMesh(0)->SetMaterial(materialWrapper); // Get plugin manager csRef<iPluginManager> plugmgr = csQueryRegistry<iPluginManager> (hairTest->GetObjectRegistry ()); if (!plugmgr) return hairTest->ReportError("Failed to locate Plugin Manager!"); // Load furMesh csRef<CS::Mesh::iFurMeshType> furMeshType = csQueryRegistry<CS::Mesh::iFurMeshType> (hairTest->GetObjectRegistry ()); if (!furMeshType) return hairTest->ReportError("Failed to locate CS::Mesh::iFurMeshType plugin!"); csRef<iRigidBody> mainBody = ragdollNode->GetBoneRigidBody (animeshFactory->GetSkeletonFactory ()->FindBone ("Frankie_Main")); // Load animationPhysicsControl animationPhysicsControl = scfQueryInterface<CS::Animation::iFurAnimatedMeshControl> (furMeshType->CreateFurAnimatedMeshControl("frankie_fur_animation")); animationPhysicsControl->SetAnimatedMesh(animesh); furPhysicsControl = scfQueryInterface<CS::Animation::iFurPhysicsControl> (furMeshType->CreateFurPhysicsControl("frankie_fur_physics")); furPhysicsControl->SetBulletDynamicSystem(hairTest->bulletDynamicSystem); furPhysicsControl->SetRigidBody(mainBody); furPhysicsControl->SetAnimatedMesh(animesh); // Create hairMeshProperties csRef<CS::Mesh::iFurMeshMaterialProperties> hairMeshProperties = furMeshType->CreateFurMeshBasicProperties("frankie_kajiya_and_kay"); hairMeshProperties->SetMaterial(materialWrapper->GetMaterial()); iSector* sector = hairTest->engine->FindSector("room"); if (!sector) return hairTest->ReportError("Could not find default room!"); frankieFurmeshObject->GetMovable()->SetSector(sector); frankieFurmeshObject->GetMovable()->UpdateMove(); csRef<iMeshObject> imo = frankieFurmeshObject->GetMeshObject(); // Get reference to the iFurMesh interface furMesh = scfQueryInterface<CS::Mesh::iFurMesh>(imo); furMesh->SetFurMeshProperties(hairMeshProperties); furMesh->SetAnimatedMesh(animesh); furMesh->SetMeshFactory(animeshFactory); furMesh->SetMeshFactorySubMesh(animesh -> GetSubMesh(0)->GetFactorySubMesh()); furMesh->GenerateGeometry(hairTest->view, hairTest->room); furMesh->SetAnimationControl(animationPhysicsControl); furMesh->StartAnimationControl(); furMesh->SetGuideLOD(0); furMesh->SetStrandLOD(1); // Reset the scene so as to put the parameters of the animation nodes in a default state ResetScene (); return true; }
bool KrystalScene::CreateAvatar () { printf ("Loading Krystal...\n"); // Load animesh factory csLoadResult rc = hairTest->loader->Load ("/lib/krystal/krystal.xml"); if (!rc.success) return hairTest->ReportError ("Can't load Krystal library file!"); csRef<iMeshFactoryWrapper> meshfact = hairTest->engine->FindMeshFactory ("krystal"); if (!meshfact) return hairTest->ReportError ("Can't find Krystal's mesh factory!"); animeshFactory = scfQueryInterface<CS::Mesh::iAnimatedMeshFactory> (meshfact->GetMeshObjectFactory ()); if (!animeshFactory) return hairTest->ReportError ("Can't find Krystal's animesh factory!"); // Load bodymesh (animesh's physical properties) rc = hairTest->loader->Load ("/lib/krystal/skelkrystal_body"); if (!rc.success) return hairTest->ReportError ("Can't load Krystal's body mesh file!"); csRef<CS::Animation::iBodyManager> bodyManager = csQueryRegistry<CS::Animation::iBodyManager> (hairTest->GetObjectRegistry ()); csRef<CS::Animation::iBodySkeleton> bodySkeleton = bodyManager->FindBodySkeleton ("krystal_body"); if (!bodySkeleton) return hairTest->ReportError ("Can't find Krystal's body mesh description!"); // Load some fur rc = hairTest->loader->Load ("/lib/hairtest/krystal_furmesh.xml"); if (!rc.success) return hairTest->ReportError ("Can't load krystal furmesh library!"); csRef<iMeshWrapper> krystalFurmeshObject = hairTest->engine->FindMeshObject ("krystal_furmesh_object"); if (!krystalFurmeshObject) return hairTest->ReportError ("Can't find fur mesh object!"); // Get plugin manager csRef<iPluginManager> plugmgr = csQueryRegistry<iPluginManager> (hairTest->GetObjectRegistry ()); if (!plugmgr) return hairTest->ReportError("Failed to locate Plugin Manager!"); // Find the fur mesh plugin csRef<CS::Mesh::iFurMeshType> furMeshType = csQueryRegistry<CS::Mesh::iFurMeshType> (hairTest->GetObjectRegistry ()); if (!furMeshType) return hairTest->ReportError("Failed to locate CS::Mesh::iFurMeshType plugin!"); // Create a new animation tree. The structure of the tree is: // + ragdoll controller node (root node - only if physics are enabled) // + Random node // + idle animation nodes csRef<CS::Animation::iSkeletonAnimPacketFactory> animPacketFactory = animeshFactory->GetSkeletonFactory ()->GetAnimationPacket (); // Create the 'random' node csRef<CS::Animation::iSkeletonRandomNodeFactory> randomNodeFactory = animPacketFactory->CreateRandomNode ("random"); randomNodeFactory->SetAutomaticSwitch (true); // Create the 'idle01' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> idle01NodeFactory = animPacketFactory->CreateAnimationNode ("idle01"); idle01NodeFactory->SetAnimation (animPacketFactory->FindAnimation ("idle01")); // Create the 'idle02' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> idle02NodeFactory = animPacketFactory->CreateAnimationNode ("idle02"); idle02NodeFactory->SetAnimation (animPacketFactory->FindAnimation ("idle02")); // Create the 'idle03' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> idle03NodeFactory = animPacketFactory->CreateAnimationNode ("idle03"); idle03NodeFactory->SetAnimation (animPacketFactory->FindAnimation ("idle03")); // Create the 'idle04' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> idle04NodeFactory = animPacketFactory->CreateAnimationNode ("idle04"); idle04NodeFactory->SetAnimation (animPacketFactory->FindAnimation ("idle04")); // Create the 'idle05' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> idle05NodeFactory = animPacketFactory->CreateAnimationNode ("idle05"); idle05NodeFactory->SetAnimation (animPacketFactory->FindAnimation ("idle05")); // Create the 'idle06' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> idle06NodeFactory = animPacketFactory->CreateAnimationNode ("idle06"); idle06NodeFactory->SetAnimation (animPacketFactory->FindAnimation ("idle06")); // Create the 'stand' animation node csRef<CS::Animation::iSkeletonAnimationNodeFactory> standNodeFactory = animPacketFactory->CreateAnimationNode ("stand"); standNodeFactory->SetAnimation (animPacketFactory->FindAnimation ("stand")); idle01NodeFactory->SetAutomaticReset (true); idle02NodeFactory->SetAutomaticReset (true); idle03NodeFactory->SetAutomaticReset (true); idle04NodeFactory->SetAutomaticReset (true); idle05NodeFactory->SetAutomaticReset (true); idle06NodeFactory->SetAutomaticReset (true); standNodeFactory->SetAutomaticReset (true); idle01NodeFactory->SetAutomaticStop (false); idle02NodeFactory->SetAutomaticStop (false); idle03NodeFactory->SetAutomaticStop (false); idle04NodeFactory->SetAutomaticStop (false); idle05NodeFactory->SetAutomaticStop (false); idle06NodeFactory->SetAutomaticStop (false); standNodeFactory->SetAutomaticStop (false); randomNodeFactory->AddNode (idle01NodeFactory, 1.0f); randomNodeFactory->AddNode (idle02NodeFactory, 1.0f); // randomNodeFactory->AddNode (idle03NodeFactory, 1.0f); randomNodeFactory->AddNode (idle04NodeFactory, 1.0f); // randomNodeFactory->AddNode (idle05NodeFactory, 1.0f); randomNodeFactory->AddNode (idle06NodeFactory, 1.0f); randomNodeFactory->AddNode (standNodeFactory, 1.0f); if (hairTest->physicsEnabled) { // Create the ragdoll controller csRef<CS::Animation::iSkeletonRagdollNodeFactory> ragdollNodeFactory = hairTest->ragdollManager->CreateAnimNodeFactory ("ragdoll"); animPacketFactory->SetAnimationRoot (ragdollNodeFactory); ragdollNodeFactory->SetBodySkeleton (bodySkeleton); ragdollNodeFactory->SetChildNode (randomNodeFactory); // Create bone chain for whole body and add it to the ragdoll controller. The chain // will be in kinematic mode when Krystal is alive, and in dynamic state when // Krystal has been killed. bodyChain = bodySkeleton->CreateBodyChain ("body_chain", animeshFactory->GetSkeletonFactory ()->FindBone ("Hips")); bodyChain->AddSubChain (animeshFactory->GetSkeletonFactory ()->FindBone ("Head")); bodyChain->AddSubChain (animeshFactory->GetSkeletonFactory ()->FindBone ("RightFoot")); bodyChain->AddSubChain (animeshFactory->GetSkeletonFactory ()->FindBone ("RightHand")); bodyChain->AddSubChain (animeshFactory->GetSkeletonFactory ()->FindBone ("LeftFoot")); bodyChain->AddSubChain (animeshFactory->GetSkeletonFactory ()->FindBone ("LeftHand")); ragdollNodeFactory->AddBodyChain (bodyChain, CS::Animation::STATE_KINEMATIC); } else animPacketFactory->SetAnimationRoot (randomNodeFactory); // Create the animated mesh csRef<iMeshWrapper> avatarMesh = hairTest->engine->CreateMeshWrapper (meshfact, "krystal", hairTest->room, csVector3 (0.0f)); animesh = scfQueryInterface<CS::Mesh::iAnimatedMesh> (avatarMesh->GetMeshObject ()); // When the animated mesh is created, the animation nodes are created too. // We can therefore set them up now. CS::Animation::iSkeletonAnimNode* rootNode = animesh->GetSkeleton ()->GetAnimationPacket ()->GetAnimationRoot (); // Setup of the ragdoll controller if (hairTest->physicsEnabled) { ragdollNode = scfQueryInterface<CS::Animation::iSkeletonRagdollNode> (rootNode->FindNode ("ragdoll")); // Start the ragdoll animation node in order to have the rigid bodies created ragdollNode->SetDynamicSystem (hairTest->dynamicSystem); ragdollNode->Play (); } csRef<iRigidBody> headBody = ragdollNode->GetBoneRigidBody (animeshFactory->GetSkeletonFactory ()->FindBone ("Head")); // Load the fur material rc = hairTest-> loader ->Load ("/lib/hairtest/fur_material_krystal.xml"); if (!rc.success) hairTest->ReportError ("Can't load Fur library file!"); // Load the Marschner shader csRef<iMaterialWrapper> materialWrapper = hairTest->engine->FindMaterial ("marschner_material"); if (!materialWrapper) hairTest->ReportError ("Can't find marschner material!"); // Create the fur properties for the hairs csRef<CS::Mesh::iFurMeshMaterialProperties> hairMeshProperties = furMeshType->CreateHairMeshMarschnerProperties ("krystal_marschner"); hairMeshProperties->SetMaterial(materialWrapper->GetMaterial ()); animesh->GetSubMesh (1)->SetMaterial (materialWrapper); // Create the two possible animation control's. We'll switch between than at the user request. hairPhysicsControl = scfQueryInterface<CS::Animation::iFurPhysicsControl> (furMeshType->CreateFurPhysicsControl ("krystal_hairs_physics")); animationPhysicsControl = scfQueryInterface<CS::Animation::iFurAnimatedMeshControl> (furMeshType->CreateFurAnimatedMeshControl ("krystal_hairs_animation")); hairPhysicsControl->SetBulletDynamicSystem (hairTest->bulletDynamicSystem); hairPhysicsControl->SetRigidBody (headBody); // hairPhysicsControl->SetAnimatedMesh(animesh); animationPhysicsControl->SetAnimatedMesh (animesh); iSector* sector = hairTest->engine->FindSector("room"); if (!sector) return hairTest->ReportError("Could not find default room!"); krystalFurmeshObject->GetMovable()->SetSector(sector); krystalFurmeshObject->GetMovable()->UpdateMove(); csRef<iMeshObject> imo = krystalFurmeshObject->GetMeshObject(); // Get reference to the iFurMesh interface furMesh = scfQueryInterface<CS::Mesh::iFurMesh> (imo); csRef<CS::Mesh::iFurMeshState> ifms = scfQueryInterface<CS::Mesh::iFurMeshState> (furMesh); animationPhysicsControl->SetDisplacement (ifms->GetDisplacement ()); furMesh->SetFurMeshProperties (hairMeshProperties); furMesh->SetAnimatedMesh (animesh); furMesh->SetMeshFactory (animeshFactory); furMesh->SetMeshFactorySubMesh (animesh->GetSubMesh (2)->GetFactorySubMesh ()); furMesh->GenerateGeometry (hairTest->view, hairTest->room); furMesh->SetAnimationControl (hairPhysicsControl); furMesh->StartAnimationControl (); furMesh->SetGuideLOD (0); furMesh->SetStrandLOD (1); furMesh->SetControlPointsLOD (0.0f); // Reset the scene so as to put the parameters of the animation nodes in a default state ResetScene (); return true; }
const csVector3 psLinearMovement::GetFullPosition () const { // user will get a warning and a nothing if theres no mesh if (!mesh) return csVector3 (); return mesh->GetMovable ()->GetFullPosition (); }
// Do the actual move int psLinearMovement::MoveV (float delta) { if (velBody < SMALL_EPSILON && velWorld < SMALL_EPSILON && (!colldet || colldet->IsOnGround ())) return PS_MOVE_DONTMOVE; // didn't move anywhere int ret = PS_MOVE_SUCCEED; iMovable* movable = mesh->GetMovable (); if (movable->GetSectors ()->GetCount () <= 0) return PS_MOVE_DONTMOVE; // didn't move anywhere csMatrix3 mat; // To test collision detection we use absolute position and transformation // (this is relevant if we are anchored). Later on we will correct that. csReversibleTransform fulltransf = movable->GetFullTransform (); mat = fulltransf.GetT2O (); delta *= speed; csVector3 worldVel (fulltransf.This2OtherRelative (velBody) + velWorld); csVector3 oldpos (fulltransf.GetOrigin ()); csVector3 newpos (worldVel*delta + oldpos); csVector3 bufpos = newpos; // Check for collisions and adjust position if (colldet) { if (!colldet->AdjustForCollisions (oldpos, newpos, worldVel, delta, movable)) { ret = PS_MOVE_FAIL; newpos = oldpos; } else { // check if we collided if ((newpos - bufpos).Norm () > 0.000001f) { ret = PS_MOVE_PARTIAL; } } } csVector3 origNewpos = newpos; bool mirror = false; // Update position to account for portals iSector* new_sector = movable->GetSectors ()->Get (0); iSector* old_sector = new_sector; // @@@ Jorrit: had to do this add! // We need to measure slightly above the position of the actor or else // we won't really cross a portal. float height5 = (bottomSize.y + topSize.y) / 10.0f; newpos.y += height5; csMatrix3 id; csOrthoTransform transform_oldpos (id, oldpos + csVector3 (0.0f, height5, 0.0f)); new_sector = new_sector->FollowSegment (transform_oldpos, newpos, mirror, PS_LINMOVE_FOLLOW_ONLY_PORTALS); newpos.y -= height5; if (new_sector != old_sector) movable->SetSector (new_sector); portalDisplaced += newpos - origNewpos; if(!IsOnGround ()) { //printf("Applying gravity: velY: %g.\n", velWorld.y); // gravity! move down! velWorld.y -= gravity * delta; /* * Terminal velocity * ((120 miles/hour / 3600 second/hour) * 5280 feet/mile) * / 3.28 feet/meter = 53.65 m/s */ // The body velocity is figured in here too. if (velWorld.y < 0) { if (fulltransf.This2OtherRelative (velBody).y + velWorld.y < -(ABS_MAX_FREEFALL_VELOCITY)) velWorld.y = -(ABS_MAX_FREEFALL_VELOCITY) - fulltransf.This2OtherRelative (velBody).y; if (velWorld.y > 0){ // printf("Reset other y %g\n", fulltransf.This2OtherRelative (velBody).y); velWorld.y = 0; } } } else { if(velWorld.y < 0) { velWorld.y = 0; } if (hugGround) HugGround (newpos, new_sector); } // Move to the new position. If we have an anchor we have to convert // the new position from absolute to relative. movable->GetTransform ().SetOrigin (newpos); movable->GetTransform ().SetT2O( movable->GetTransform ().GetT2O () * transform_oldpos.GetT2O ()); if (colldet) { // Part 4: Add us to all nearby sectors. mesh->PlaceMesh (); } movable->UpdateMove (); return ret; }
void AvatarTest::Frame () { // First get elapsed time from the virtual clock. csTicks elapsed_time = vc->GetElapsedTicks (); // Now rotate the camera according to keyboard state const float speed = elapsed_time / 1000.0f; // Compute camera and animesh position iCamera* c = view->GetCamera (); csVector3 cameraPosition = c->GetTransform ().GetOrigin (); csVector3 avatarPosition = avatarScene->GetCameraTarget (); // Move camera if (kbd->GetKeyState (CSKEY_SHIFT)) { // If the user is holding down shift, the Up/Down arrow keys will cause // the camera to go forwards and backwards (forward only allowed if camera // not too close). Left/Right arrows work also when shift is hold. if (kbd->GetKeyState (CSKEY_UP) && (cameraPosition - avatarPosition).Norm () > 0.5f) c->Move (CS_VEC_FORWARD * 4 * speed); if (kbd->GetKeyState (CSKEY_DOWN)) c->Move (CS_VEC_BACKWARD * 4 * speed); if (kbd->GetKeyState (CSKEY_RIGHT)) c->Move (CS_VEC_RIGHT * 4 * speed); if (kbd->GetKeyState (CSKEY_LEFT)) c->Move (CS_VEC_LEFT * 4 * speed); } else { // Left and right arrows cause the camera to strafe on the X axis; up and // down arrows cause the camera to strafe on the Y axis if (kbd->GetKeyState (CSKEY_RIGHT)) c->Move (CS_VEC_RIGHT * 4 * speed); if (kbd->GetKeyState (CSKEY_LEFT)) c->Move (CS_VEC_LEFT * 4 * speed); // Avoid gimbal lock of camera cameraPosition.Normalize (); float cameraDot = cameraPosition * csVector3 (0.0f, 1.0f, 0.0f); if (kbd->GetKeyState (CSKEY_UP) && cameraDot < 0.98f) c->Move (CS_VEC_UP * 4 * speed); if (kbd->GetKeyState (CSKEY_DOWN) && cameraDot > -0.98f) c->Move (CS_VEC_DOWN * 4 * speed); } // Make the camera look at the animesh c->GetTransform ().LookAt (avatarPosition - c->GetTransform ().GetOrigin (), csVector3 (0.0f, 1.0f, 0.0f) ); // Step the dynamic simulation (we slow down artificially the simulation in // order to achieve a 'slow motion' effect) if (physicsEnabled) dynamics->Step (speed / 4.0f); // Update the avatar avatarScene->Frame (); // Tell 3D driver we're going to display 3D things. if (!g3d->BeginDraw (engine->GetBeginDrawFlags () | CSDRAW_3DGRAPHICS)) return; // Tell the camera to render into the frame buffer. view->Draw (); // Write FPS and other info if(!g3d->BeginDraw (CSDRAW_2DGRAPHICS)) return; avatarScene->DisplayKeys (); }