void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() { KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; for (i=0;i<numScenes;i++) { KX_Scene* scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); CListValue* parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; for (g=0;g<numObjects;g++) { KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); if (gameObj->IsDynamic()) { //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = gameObj->GetBlenderObject(); if (blenderObject && blenderObject->ipo) { // XXX animato #if 0 Ipo* ipo = blenderObject->ipo; //create the curves, if not existing //testhandles_ipocurve checks for NULL testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX")); testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocY")); testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ")); testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotX")); testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotY")); testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ")); #endif } } } } }
void KX_BulletPhysicsController::SetObject (SG_IObject* object) { SG_Controller::SetObject(object); // cheating here... //should not be necessary, is it for duplicates ? KX_GameObject* gameobj = (KX_GameObject*) object->GetSGClientObject(); gameobj->SetPhysicsController(this,gameobj->IsDynamic()); CcdPhysicsController::setNewClientInfo(gameobj->getClientInfo()); if (m_bSensor) { // use a different callback function for sensor object, // bullet will not synchronize, we must do it explicitly SG_Callbacks& callbacks = gameobj->GetSGNode()->GetCallBackFunctions(); callbacks.m_updatefunc = KX_GameObject::SynchronizeTransformFunc; } }
void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() { if (addInitFromFrame) { KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); if (numScenes>=0) { KX_Scene* scene = scenes->at(0); CListValue* parentList = scene->GetRootParentList(); for (int ix=0;ix<parentList->GetCount();ix++) { KX_GameObject* gameobj = (KX_GameObject*)parentList->GetValue(ix); if (!gameobj->IsDynamic()) { Object* blenderobject = gameobj->GetBlenderObject(); if (!blenderobject) continue; if (blenderobject->type==OB_ARMATURE) continue; float eu[3]; mat4_to_eul(eu,blenderobject->obmat); MT_Point3 pos = MT_Point3( blenderobject->obmat[3][0], blenderobject->obmat[3][1], blenderobject->obmat[3][2] ); MT_Vector3 eulxyz = MT_Vector3( eu[0], eu[1], eu[2] ); MT_Vector3 scale = MT_Vector3( blenderobject->size[0], blenderobject->size[1], blenderobject->size[2] ); gameobj->NodeSetLocalPosition(pos); gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz)); gameobj->NodeSetLocalScale(scale); gameobj->NodeUpdateGS(0); } } } } }
///this generates ipo curves for position, rotation, allowing to use game physics in animation void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) { KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; for (i=0;i<numScenes;i++) { KX_Scene* scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); CListValue* parentList = scene->GetObjectList(); int numObjects = parentList->GetCount(); int g; for (g=0;g<numObjects;g++) { KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); Object* blenderObject = gameObj->GetBlenderObject(); if (blenderObject && blenderObject->parent==NULL && gameObj->IsDynamic()) { //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); if (blenderObject->adt==NULL) BKE_id_add_animdata(&blenderObject->id); if (blenderObject->adt) { const MT_Point3& position = gameObj->NodeGetWorldPosition(); //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); position.getValue(blenderObject->loc); float tmat[3][3]; for (int r=0;r<3;r++) for (int c=0;c<3;c++) tmat[r][c] = (float)orn[c][r]; mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat); insert_keyframe(NULL, &blenderObject->id, NULL, NULL, "location", -1, (float)frameNumber, INSERTKEY_FAST); insert_keyframe(NULL, &blenderObject->id, NULL, NULL, "rotation_euler", -1, (float)frameNumber, INSERTKEY_FAST); #if 0 const MT_Point3& position = gameObj->NodeGetWorldPosition(); //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); float eulerAngles[3]; float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f}; float tmat[3][3]; // XXX animato Ipo* ipo = blenderObject->ipo; //create the curves, if not existing, set linear if new IpoCurve *icu_lx = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu_lx) { icu_lx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); if (icu_lx) icu_lx->ipo = IPO_LIN; } IpoCurve *icu_ly = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu_ly) { icu_ly = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); if (icu_ly) icu_ly->ipo = IPO_LIN; } IpoCurve *icu_lz = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu_lz) { icu_lz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); if (icu_lz) icu_lz->ipo = IPO_LIN; } IpoCurve *icu_rx = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu_rx) { icu_rx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); if (icu_rx) icu_rx->ipo = IPO_LIN; } IpoCurve *icu_ry = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu_ry) { icu_ry = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); if (icu_ry) icu_ry->ipo = IPO_LIN; } IpoCurve *icu_rz = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu_rz) { icu_rz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); if (icu_rz) icu_rz->ipo = IPO_LIN; } if (icu_rx) eulerAnglesOld[0]= eval_icu( icu_rx, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); if (icu_ry) eulerAnglesOld[1]= eval_icu( icu_ry, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); if (icu_rz) eulerAnglesOld[2]= eval_icu( icu_rz, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); // orn.getValue((float *)tmat); // uses the wrong ordering, cant use this for (int r=0;r<3;r++) for (int c=0;c<3;c++) tmat[r][c] = orn[c][r]; // mat3_to_eul( eulerAngles,tmat); // better to use Mat3ToCompatibleEul mat3_to_compatible_eul( eulerAngles, eulerAnglesOld,tmat); //eval_icu for (int x = 0; x < 3; x++) eulerAngles[x] *= (float) ((180 / 3.14159265f) / 10.0); //fill the curves with data if (icu_lx) insert_vert_icu(icu_lx, frameNumber, position.x(), 1); if (icu_ly) insert_vert_icu(icu_ly, frameNumber, position.y(), 1); if (icu_lz) insert_vert_icu(icu_lz, frameNumber, position.z(), 1); if (icu_rx) insert_vert_icu(icu_rx, frameNumber, eulerAngles[0], 1); if (icu_ry) insert_vert_icu(icu_ry, frameNumber, eulerAngles[1], 1); if (icu_rz) insert_vert_icu(icu_rz, frameNumber, eulerAngles[2], 1); // Handles are corrected at the end, testhandles_ipocurve isn't needed yet #endif } } } } }
void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) { KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; for (i=0;i<numScenes;i++) { KX_Scene* scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); CListValue* parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; for (g=0;g<numObjects;g++) { KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); if (gameObj->IsDynamic()) { //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = gameObj->GetBlenderObject(); if (blenderObject) { #if 0 //erase existing ipo's Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2); if (ipo) { //clear the curve data if (clearIpo) {//rcruiz IpoCurve *icu1; int numCurves = 0; for ( icu1 = (IpoCurve*)ipo->curve.first; icu1; ) { IpoCurve* tmpicu = icu1; /*int i; BezTriple *bezt; for ( bezt = tmpicu->bezt, i = 0; i < tmpicu->totvert; i++, bezt++) { printf("(%f,%f,%f),(%f,%f,%f),(%f,%f,%f)\n",bezt->vec[0][0],bezt->vec[0][1],bezt->vec[0][2],bezt->vec[1][0],bezt->vec[1][1],bezt->vec[1][2],bezt->vec[2][0],bezt->vec[2][1],bezt->vec[2][2]); }*/ icu1 = icu1->next; numCurves++; BLI_remlink( &( blenderObject->ipo->curve ), tmpicu ); if ( tmpicu->bezt ) MEM_freeN( tmpicu->bezt ); MEM_freeN( tmpicu ); localDel_ipoCurve( tmpicu ); } } } else { ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); blenderObject->ipo = ipo; } #endif } } } } }
bool KX_SteeringActuator::Update(double curtime, bool frame) { if (frame) { double delta = curtime - m_updateTime; m_updateTime = curtime; if (m_posevent && !m_isActive) { delta = 0.0; m_pathUpdateTime = -1.0; m_updateTime = curtime; m_isActive = true; } bool bNegativeEvent = IsNegativeEvent(); if (bNegativeEvent) m_isActive = false; RemoveAllEvents(); if (!delta) return true; if (bNegativeEvent || !m_target) return false; // do nothing on negative events KX_GameObject *obj = (KX_GameObject*) GetParent(); const MT_Vector3& mypos = obj->NodeGetWorldPosition(); const MT_Vector3& targpos = m_target->NodeGetWorldPosition(); MT_Vector3 vectotarg = targpos - mypos; MT_Vector3 vectotarg2d = vectotarg; vectotarg2d.z() = 0.0f; m_steerVec = MT_Vector3(0.0f, 0.0f, 0.0f); bool apply_steerforce = false; bool terminate = true; switch (m_mode) { case KX_STEERING_SEEK: if (vectotarg2d.length2()>m_distance*m_distance) { terminate = false; m_steerVec = vectotarg; m_steerVec.normalize(); apply_steerforce = true; } break; case KX_STEERING_FLEE: if (vectotarg2d.length2()<m_distance*m_distance) { terminate = false; m_steerVec = -vectotarg; m_steerVec.normalize(); apply_steerforce = true; } break; case KX_STEERING_PATHFOLLOWING: if (m_navmesh && vectotarg.length2()>m_distance*m_distance) { terminate = false; static const MT_Scalar WAYPOINT_RADIUS(0.25f); if (m_pathUpdateTime<0 || (m_pathUpdatePeriod>=0 && curtime - m_pathUpdateTime>((double)m_pathUpdatePeriod/1000.0))) { m_pathUpdateTime = curtime; m_pathLen = m_navmesh->FindPath(mypos, targpos, m_path, MAX_PATH_LENGTH); m_wayPointIdx = m_pathLen > 1 ? 1 : -1; } if (m_wayPointIdx>0) { MT_Vector3 waypoint(&m_path[3*m_wayPointIdx]); if ((waypoint-mypos).length2()<WAYPOINT_RADIUS*WAYPOINT_RADIUS) { m_wayPointIdx++; if (m_wayPointIdx>=m_pathLen) { m_wayPointIdx = -1; terminate = true; } else waypoint.setValue(&m_path[3*m_wayPointIdx]); } m_steerVec = waypoint - mypos; apply_steerforce = true; if (m_enableVisualization) { //debug draw static const MT_Vector4 PATH_COLOR(1.0f, 0.0f, 0.0f, 1.0f); m_navmesh->DrawPath(m_path, m_pathLen, PATH_COLOR); } } } break; } if (apply_steerforce) { bool isdyna = obj->IsDynamic(); if (isdyna) m_steerVec.z() = 0; if (!m_steerVec.fuzzyZero()) m_steerVec.normalize(); MT_Vector3 newvel = m_velocity * m_steerVec; //adjust velocity to avoid obstacles if (m_simulation && m_obstacle /*&& !newvel.fuzzyZero()*/) { if (m_enableVisualization) KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector4(1.0f, 0.0f, 0.0f, 1.0f)); m_simulation->AdjustObstacleVelocity(m_obstacle, m_mode!=KX_STEERING_PATHFOLLOWING ? m_navmesh : NULL, newvel, m_acceleration*(float)delta, m_turnspeed/(180.0f*(float)(M_PI*delta))); if (m_enableVisualization) KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector4(0.0f, 1.0f, 0.0f, 1.0f)); } HandleActorFace(newvel); if (isdyna) { //temporary solution: set 2D steering velocity directly to obj //correct way is to apply physical force MT_Vector3 curvel = obj->GetLinearVelocity(); if (m_lockzvel) newvel.z() = 0.0f; else newvel.z() = curvel.z(); obj->setLinearVelocity(newvel, false); } else { MT_Vector3 movement = delta*newvel; obj->ApplyMovement(movement, false); } } else { if (m_simulation && m_obstacle) { m_obstacle->dvel[0] = 0.f; m_obstacle->dvel[1] = 0.f; } } if (terminate && m_isSelfTerminated) return false; } return true; }