bool KX_WorldIpoController::Update(double currentTime) { if (m_modified) { T_InterpolatorList::iterator i; for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { (*i)->Execute(m_ipotime); } KX_WorldInfo *world = KX_GetActiveScene()->GetWorldInfo(); if (m_modify_mist_start) { world->setMistStart(m_mist_start); } if (m_modify_mist_dist) { world->setMistDistance(m_mist_dist); } if (m_modify_mist_intensity) { world->setMistIntensity(m_mist_intensity); } if (m_modify_horizon_color) { world->setBackColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); world->setMistColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); } if (m_modify_ambient_color) { world->setAmbientColor(m_ambi_rgb[0], m_ambi_rgb[1], m_ambi_rgb[2]); } m_modified = false; } return false; }
void KX_NavMeshObject::ProcessReplica() { KX_GameObject::ProcessReplica(); m_navMesh = NULL; /* without this, building frees the navmesh we copied from */ BuildNavMesh(); KX_Scene* scene = KX_GetActiveScene(); KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation(); if (obssimulation) obssimulation->AddObstaclesForNavMesh(this); }
void KX_NavMeshObject::ProcessReplica() { KX_GameObject::ProcessReplica(); BuildNavMesh(); KX_Scene* scene = KX_GetActiveScene(); KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation(); if (obssimulation) obssimulation->AddObstaclesForNavMesh(this); }
PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) { PyObject *pylistPos,*pylistDir,*pylistAxleDir; PyObject *wheelGameObject; float suspensionRestLength,wheelRadius; int hasSteering; if (PyArg_ParseTuple(args,"OOOOffi:addWheel",&wheelGameObject,&pylistPos,&pylistDir,&pylistAxleDir,&suspensionRestLength,&wheelRadius,&hasSteering)) { KX_GameObject *gameOb; if (!ConvertPythonToGameObject(KX_GetActiveScene()->GetLogicManager(), wheelGameObject, &gameOb, false, "vehicle.addWheel(...): KX_VehicleWrapper (first argument)")) return NULL; if (gameOb->GetSGNode()) { MT_Vector3 attachPos,attachDir,attachAxle; if (!PyVecTo(pylistPos,attachPos)) { PyErr_SetString(PyExc_AttributeError, "addWheel(...) Unable to add wheel. attachPos must be a vector with 3 elements."); return NULL; } if (!PyVecTo(pylistDir,attachDir)) { PyErr_SetString(PyExc_AttributeError, "addWheel(...) Unable to add wheel. downDir must be a vector with 3 elements."); return NULL; } if (!PyVecTo(pylistAxleDir,attachAxle)) { PyErr_SetString(PyExc_AttributeError, "addWheel(...) Unable to add wheel. axleDir must be a vector with 3 elements."); return NULL; } //someone reverse some conventions inside Bullet (axle winding) attachAxle = -attachAxle; if (wheelRadius <= 0) { PyErr_SetString(PyExc_AttributeError, "addWheel(...) Unable to add wheel. wheelRadius must be positive."); return NULL; } PHY_IMotionState *motionState = new KX_MotionState(gameOb->GetSGNode()); m_vehicle->AddWheel(motionState,attachPos,attachDir,attachAxle,suspensionRestLength,wheelRadius,hasSteering); } } else { return NULL; } Py_RETURN_NONE; }
bool KX_ParentActuator::Update() { bool bNegativeEvent = IsNegativeEvent(); RemoveAllEvents(); if (bNegativeEvent) return false; // do nothing on negative events KX_GameObject *obj = (KX_GameObject*) GetParent(); KX_Scene *scene = KX_GetActiveScene(); switch (m_mode) { case KX_PARENT_SET: if (m_ob) obj->SetParent(scene, (KX_GameObject*)m_ob, m_addToCompound, m_ghost); break; case KX_PARENT_REMOVE: obj->RemoveParent(scene); break; }; return false; }
bool KX_SoundActuator::Update(double curtime, bool frame) { if (!frame) return true; bool result = false; #ifdef WITH_AUDASPACE // do nothing on negative events, otherwise sounds are played twice! bool bNegativeEvent = IsNegativeEvent(); bool bPositiveEvent = m_posevent; #endif // WITH_AUDASPACE RemoveAllEvents(); #ifdef WITH_AUDASPACE if (!m_sound) return false; // actual audio device playing state bool isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false; if (bNegativeEvent) { // here must be a check if it is still playing if (m_isplaying && isplaying) { switch (m_type) { case KX_SOUNDACT_PLAYSTOP: case KX_SOUNDACT_LOOPSTOP: case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: { // stop immediately if (m_handle) { AUD_Handle_stop(m_handle); m_handle = NULL; } break; } case KX_SOUNDACT_PLAYEND: { // do nothing, sound will stop anyway when it's finished break; } case KX_SOUNDACT_LOOPEND: case KX_SOUNDACT_LOOPBIDIRECTIONAL: { // stop the looping so that the sound stops when it finished if (m_handle) AUD_Handle_setLoopCount(m_handle, 0); break; } default: // implement me !! break; } } // remember that we tried to stop the actuator m_isplaying = false; } #if 1 // Warning: when de-activating the actuator, after a single negative event this runs again with... // m_posevent==false && m_posevent==false, in this case IsNegativeEvent() returns false // and assumes this is a positive event. // check that we actually have a positive event so as not to play sounds when being disabled. else if (bPositiveEvent) /* <- added since 2.49 */ #else else // <- works in most cases except a loop-end sound will never stop unless // the negative pulse is done continuesly #endif { if (!m_isplaying) play(); } // verify that the sound is still playing isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false; if (isplaying) { if (m_is3d) { KX_Camera* cam = KX_GetActiveScene()->GetActiveCamera(); if (cam) { KX_GameObject* obj = (KX_GameObject*)this->GetParent(); MT_Vector3 p; MT_Matrix3x3 Mo; float data[4]; Mo = cam->NodeGetWorldOrientation().inverse(); p = (obj->NodeGetWorldPosition() - cam->NodeGetWorldPosition()); p = Mo * p; p.getValue(data); AUD_Handle_setLocation(m_handle, data); p = (obj->GetLinearVelocity() - cam->GetLinearVelocity()); p = Mo * p; p.getValue(data); AUD_Handle_setVelocity(m_handle, data); (Mo * obj->NodeGetWorldOrientation()).getRotation().getValue(data); AUD_Handle_setOrientation(m_handle, data); } } result = true; } else { m_isplaying = false; result = false; } #endif // WITH_AUDASPACE return result; }
bool BL_Action::Play(const char* name, float start, float end, short priority, float blendin, short play_mode, float layer_weight, short ipo_flags, float playback_speed) { // Only start playing a new action if we're done, or if // the new action has a higher priority if (!IsDone() && priority > m_priority) return false; m_priority = priority; bAction* prev_action = m_action; // First try to load the action m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name); if (!m_action) { printf("Failed to load action: %s\n", name); m_done = true; return false; } // If we have the same settings, don't play again // This is to resolve potential issues with pulses on sensors such as the ones // reported in bug #29412. The fix is here so it works for both logic bricks and Python. // However, this may eventually lead to issues where a user wants to override an already // playing action with the same action and settings. If this becomes an issue, // then this fix may have to be re-evaluated. if (!IsDone() && m_action == prev_action && m_startframe == start && m_endframe == end && m_priority == priority && m_speed == playback_speed) return false; if (prev_action != m_action) { // First get rid of any old controllers ClearControllerList(); // Create an SG_Controller SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); // Extra controllers if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) { sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA) { sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } } m_ipo_flags = ipo_flags; InitIPO(); // Setup blendin shapes/poses if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; obj->GetMRDPose(&m_blendinpose); } else { BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); if (shape_deformer && shape_deformer->GetKey()) { obj->GetShape(m_blendinshape); // Now that we have the previous blend shape saved, we can clear out the key to avoid any // further interference. KeyBlock *kb; for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next) kb->curval = 0.f; } } // Now that we have an action, we have something we can play m_starttime = -1.f; // We get the start time on our first update m_startframe = m_localtime = start; m_endframe = end; m_blendin = blendin; m_playmode = play_mode; m_endtime = 0.f; m_blendframe = 0.f; m_blendstart = 0.f; m_speed = playback_speed; m_layer_weight = layer_weight; m_done = false; return true; }
bool KX_ConstraintActuator::Update(double curtime, bool frame) { bool result = false; bool bNegativeEvent = IsNegativeEvent(); RemoveAllEvents(); if (!bNegativeEvent) { /* Constraint clamps the values to the specified range, with a sort of */ /* low-pass filtered time response, if the damp time is unequal to 0. */ /* Having to retrieve location/rotation and setting it afterwards may not */ /* be efficient enough... Something to look at later. */ KX_GameObject *obj = (KX_GameObject*) GetParent(); MT_Vector3 position = obj->NodeGetWorldPosition(); MT_Vector3 newposition; MT_Vector3 normal, direction, refDirection; MT_Matrix3x3 rotation = obj->NodeGetWorldOrientation(); MT_Scalar filter, newdistance, cosangle; int axis, sign; if (m_posDampTime) { filter = m_posDampTime/(1.0f+m_posDampTime); } else { filter = 0.0f; } switch (m_locrot) { case KX_ACT_CONSTRAINT_ORIX: case KX_ACT_CONSTRAINT_ORIY: case KX_ACT_CONSTRAINT_ORIZ: switch (m_locrot) { case KX_ACT_CONSTRAINT_ORIX: direction[0] = rotation[0][0]; direction[1] = rotation[1][0]; direction[2] = rotation[2][0]; axis = 0; break; case KX_ACT_CONSTRAINT_ORIY: direction[0] = rotation[0][1]; direction[1] = rotation[1][1]; direction[2] = rotation[2][1]; axis = 1; break; default: direction[0] = rotation[0][2]; direction[1] = rotation[1][2]; direction[2] = rotation[2][2]; axis = 2; break; } if ((m_maximumBound < (1.0f-FLT_EPSILON)) || (m_minimumBound < (1.0f-FLT_EPSILON))) { // reference direction needs to be evaluated // 1. get the cosine between current direction and target cosangle = direction.dot(m_refDirVector); if (cosangle >= (m_maximumBound-FLT_EPSILON) && cosangle <= (m_minimumBound+FLT_EPSILON)) { // no change to do result = true; goto CHECK_TIME; } // 2. define a new reference direction // compute local axis with reference direction as X and // Y in direction X refDirection plane MT_Vector3 zaxis = m_refDirVector.cross(direction); if (MT_fuzzyZero2(zaxis.length2())) { // direction and refDirection are identical, // choose any other direction to define plane if (direction[0] < 0.9999f) zaxis = m_refDirVector.cross(MT_Vector3(1.0f,0.0f,0.0f)); else zaxis = m_refDirVector.cross(MT_Vector3(0.0f,1.0f,0.0f)); } MT_Vector3 yaxis = zaxis.cross(m_refDirVector); yaxis.normalize(); if (cosangle > m_minimumBound) { // angle is too close to reference direction, // choose a new reference that is exactly at minimum angle refDirection = m_minimumBound * m_refDirVector + m_minimumSine * yaxis; } else { // angle is too large, choose new reference direction at maximum angle refDirection = m_maximumBound * m_refDirVector + m_maximumSine * yaxis; } } else { refDirection = m_refDirVector; } // apply damping on the direction direction = filter*direction + (1.0f-filter)*refDirection; obj->AlignAxisToVect(direction, axis); result = true; goto CHECK_TIME; case KX_ACT_CONSTRAINT_DIRPX: case KX_ACT_CONSTRAINT_DIRPY: case KX_ACT_CONSTRAINT_DIRPZ: case KX_ACT_CONSTRAINT_DIRNX: case KX_ACT_CONSTRAINT_DIRNY: case KX_ACT_CONSTRAINT_DIRNZ: switch (m_locrot) { case KX_ACT_CONSTRAINT_DIRPX: normal[0] = rotation[0][0]; normal[1] = rotation[1][0]; normal[2] = rotation[2][0]; axis = 0; // axis according to KX_GameObject::AlignAxisToVect() sign = 0; // X axis will be parrallel to direction of ray break; case KX_ACT_CONSTRAINT_DIRPY: normal[0] = rotation[0][1]; normal[1] = rotation[1][1]; normal[2] = rotation[2][1]; axis = 1; sign = 0; break; case KX_ACT_CONSTRAINT_DIRPZ: normal[0] = rotation[0][2]; normal[1] = rotation[1][2]; normal[2] = rotation[2][2]; axis = 2; sign = 0; break; case KX_ACT_CONSTRAINT_DIRNX: normal[0] = -rotation[0][0]; normal[1] = -rotation[1][0]; normal[2] = -rotation[2][0]; axis = 0; sign = 1; break; case KX_ACT_CONSTRAINT_DIRNY: normal[0] = -rotation[0][1]; normal[1] = -rotation[1][1]; normal[2] = -rotation[2][1]; axis = 1; sign = 1; break; case KX_ACT_CONSTRAINT_DIRNZ: normal[0] = -rotation[0][2]; normal[1] = -rotation[1][2]; normal[2] = -rotation[2][2]; axis = 2; sign = 1; break; } normal.normalize(); if (m_option & KX_ACT_CONSTRAINT_LOCAL) { // direction of the ray is along the local axis direction = normal; } else { switch (m_locrot) { case KX_ACT_CONSTRAINT_DIRPX: direction = MT_Vector3(1.0f,0.0f,0.0f); break; case KX_ACT_CONSTRAINT_DIRPY: direction = MT_Vector3(0.0f,1.0f,0.0f); break; case KX_ACT_CONSTRAINT_DIRPZ: direction = MT_Vector3(0.0f,0.0f,1.0f); break; case KX_ACT_CONSTRAINT_DIRNX: direction = MT_Vector3(-1.0f,0.0f,0.0f); break; case KX_ACT_CONSTRAINT_DIRNY: direction = MT_Vector3(0.0f,-1.0f,0.0f); break; case KX_ACT_CONSTRAINT_DIRNZ: direction = MT_Vector3(0.0f,0.0f,-1.0f); break; } } { MT_Vector3 topoint = position + (m_maximumBound) * direction; PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment(); PHY_IPhysicsController *spc = obj->GetPhysicsController(); if (!pe) { CM_LogicBrickWarning(this, "there is no physics environment!"); goto CHECK_TIME; } if (!spc) { // the object is not physical, we probably want to avoid hitting its own parent KX_GameObject *parent = obj->GetParent(); if (parent) { spc = parent->GetPhysicsController(); } } KX_RayCast::Callback<KX_ConstraintActuator, void> callback(this,dynamic_cast<PHY_IPhysicsController*>(spc)); result = KX_RayCast::RayTest(pe, position, topoint, callback); if (result) { MT_Vector3 newnormal = callback.m_hitNormal; // compute new position & orientation if ((m_option & (KX_ACT_CONSTRAINT_NORMAL|KX_ACT_CONSTRAINT_DISTANCE)) == 0) { // if none option is set, the actuator does nothing but detect ray // (works like a sensor) goto CHECK_TIME; } if (m_option & KX_ACT_CONSTRAINT_NORMAL) { MT_Scalar rotFilter; // apply damping on the direction if (m_rotDampTime) { rotFilter = m_rotDampTime/(1.0f+m_rotDampTime); } else { rotFilter = filter; } newnormal = rotFilter*normal - (1.0f-rotFilter)*newnormal; obj->AlignAxisToVect((sign)?-newnormal:newnormal, axis); if (m_option & KX_ACT_CONSTRAINT_LOCAL) { direction = newnormal; direction.normalize(); } } if (m_option & KX_ACT_CONSTRAINT_DISTANCE) { if (m_posDampTime) { newdistance = filter*(position-callback.m_hitPoint).length()+(1.0f-filter)*m_minimumBound; } else { newdistance = m_minimumBound; } // logically we should cancel the speed along the ray direction as we set the // position along that axis spc = obj->GetPhysicsController(); if (spc && spc->IsDynamic()) { MT_Vector3 linV = spc->GetLinearVelocity(); // cancel the projection along the ray direction MT_Scalar fallspeed = linV.dot(direction); if (!MT_fuzzyZero(fallspeed)) spc->SetLinearVelocity(linV-fallspeed*direction,false); } } else { newdistance = (position-callback.m_hitPoint).length(); } newposition = callback.m_hitPoint-newdistance*direction; } else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) { // no contact but still keep running result = true; goto CHECK_TIME; } } break; case KX_ACT_CONSTRAINT_FHPX: case KX_ACT_CONSTRAINT_FHPY: case KX_ACT_CONSTRAINT_FHPZ: case KX_ACT_CONSTRAINT_FHNX: case KX_ACT_CONSTRAINT_FHNY: case KX_ACT_CONSTRAINT_FHNZ: switch (m_locrot) { case KX_ACT_CONSTRAINT_FHPX: normal[0] = -rotation[0][0]; normal[1] = -rotation[1][0]; normal[2] = -rotation[2][0]; direction = MT_Vector3(1.0f,0.0f,0.0f); break; case KX_ACT_CONSTRAINT_FHPY: normal[0] = -rotation[0][1]; normal[1] = -rotation[1][1]; normal[2] = -rotation[2][1]; direction = MT_Vector3(0.0f,1.0f,0.0f); break; case KX_ACT_CONSTRAINT_FHPZ: normal[0] = -rotation[0][2]; normal[1] = -rotation[1][2]; normal[2] = -rotation[2][2]; direction = MT_Vector3(0.0f,0.0f,1.0f); break; case KX_ACT_CONSTRAINT_FHNX: normal[0] = rotation[0][0]; normal[1] = rotation[1][0]; normal[2] = rotation[2][0]; direction = MT_Vector3(-1.0f,0.0f,0.0f); break; case KX_ACT_CONSTRAINT_FHNY: normal[0] = rotation[0][1]; normal[1] = rotation[1][1]; normal[2] = rotation[2][1]; direction = MT_Vector3(0.0f,-1.0f,0.0f); break; case KX_ACT_CONSTRAINT_FHNZ: normal[0] = rotation[0][2]; normal[1] = rotation[1][2]; normal[2] = rotation[2][2]; direction = MT_Vector3(0.0f,0.0f,-1.0f); break; } normal.normalize(); { PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment(); PHY_IPhysicsController *spc = obj->GetPhysicsController(); if (!pe) { CM_LogicBrickWarning(this, "there is no physics environment!"); goto CHECK_TIME; } if (!spc || !spc->IsDynamic()) { // the object is not dynamic, it won't support setting speed goto CHECK_TIME; } m_hitObject = NULL; // distance of Fh area is stored in m_minimum MT_Vector3 topoint = position + (m_minimumBound+spc->GetRadius()) * direction; KX_RayCast::Callback<KX_ConstraintActuator, void> callback(this, spc); result = KX_RayCast::RayTest(pe, position, topoint, callback); // we expect a hit object if (!m_hitObject) result = false; if (result) { MT_Vector3 newnormal = callback.m_hitNormal; // compute new position & orientation MT_Scalar distance = (callback.m_hitPoint-position).length()-spc->GetRadius(); // estimate the velocity of the hit point MT_Vector3 relativeHitPoint; relativeHitPoint = (callback.m_hitPoint-m_hitObject->NodeGetWorldPosition()); MT_Vector3 velocityHitPoint = m_hitObject->GetVelocity(relativeHitPoint); MT_Vector3 relativeVelocity = spc->GetLinearVelocity() - velocityHitPoint; MT_Scalar relativeVelocityRay = direction.dot(relativeVelocity); MT_Scalar springExtent = 1.0f - distance/m_minimumBound; // Fh force is stored in m_maximum MT_Scalar springForce = springExtent * m_maximumBound; // damping is stored in m_refDirection [0] = damping, [1] = rot damping MT_Scalar springDamp = relativeVelocityRay * m_refDirVector[0]; MT_Vector3 newVelocity = spc->GetLinearVelocity()-(springForce+springDamp)*direction; if (m_option & KX_ACT_CONSTRAINT_NORMAL) { newVelocity+=(springForce+springDamp)*(newnormal-newnormal.dot(direction)*direction); } spc->SetLinearVelocity(newVelocity, false); if (m_option & KX_ACT_CONSTRAINT_DOROTFH) { MT_Vector3 angSpring = (normal.cross(newnormal))*m_maximumBound; MT_Vector3 angVelocity = spc->GetAngularVelocity(); // remove component that is parallel to normal angVelocity -= angVelocity.dot(newnormal)*newnormal; MT_Vector3 angDamp = angVelocity * ((m_refDirVector[1]>MT_EPSILON)?m_refDirVector[1]:m_refDirVector[0]); spc->SetAngularVelocity(spc->GetAngularVelocity()+(angSpring-angDamp), false); } } else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) { // no contact but still keep running result = true; } // don't set the position with this constraint goto CHECK_TIME; } break; case KX_ACT_CONSTRAINT_LOCX: case KX_ACT_CONSTRAINT_LOCY: case KX_ACT_CONSTRAINT_LOCZ: newposition = position = obj->GetSGNode()->GetLocalPosition(); switch (m_locrot) { case KX_ACT_CONSTRAINT_LOCX: Clamp(newposition[0], m_minimumBound, m_maximumBound); break; case KX_ACT_CONSTRAINT_LOCY: Clamp(newposition[1], m_minimumBound, m_maximumBound); break; case KX_ACT_CONSTRAINT_LOCZ: Clamp(newposition[2], m_minimumBound, m_maximumBound); break; } result = true; if (m_posDampTime) { newposition = filter*position + (1.0f-filter)*newposition; } obj->NodeSetLocalPosition(newposition); goto CHECK_TIME; } if (result) { // set the new position but take into account parent if any obj->NodeSetWorldPosition(newposition); } CHECK_TIME: if (result && m_activeTime > 0 ) { if (++m_currentTime >= m_activeTime) result = false; } } if (!result) { m_currentTime = 0; } return result; } /* end of KX_ConstraintActuator::Update(double curtime,double deltatime) */
bool BL_Action::Play(const char* name, float start, float end, short priority, float blendin, short play_mode, float layer_weight, short ipo_flags, float playback_speed) { // Only start playing a new action if we're done, or if // the new action has a higher priority if (priority != 0 && !IsDone() && priority >= m_priority) return false; m_priority = priority; bAction* prev_action = m_action; // First try to load the action m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name); if (!m_action) { printf("Failed to load action: %s\n", name); m_done = true; return false; } if (prev_action != m_action) { // First get rid of any old controllers ClearControllerList(); // Create an SG_Controller SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); // Extra controllers if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) { sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA) { sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); m_sg_contr_list.push_back(sg_contr); m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); } } m_ipo_flags = ipo_flags; InitIPO(); // Setup blendin shapes/poses if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; obj->GetMRDPose(&m_blendinpose); } else { BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); if (shape_deformer && shape_deformer->GetKey()) { obj->GetShape(m_blendinshape); // Now that we have the previous blend shape saved, we can clear out the key to avoid any // further interference. KeyBlock *kb; for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next) kb->curval = 0.f; } } // Now that we have an action, we have something we can play m_starttime = KX_GetActiveEngine()->GetFrameTime(); m_startframe = m_localtime = start; m_endframe = end; m_blendin = blendin; m_playmode = play_mode; m_endtime = 0.f; m_blendframe = 0.f; m_blendstart = 0.f; m_speed = playback_speed; m_layer_weight = layer_weight; m_done = false; return true; }
bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts, unsigned short* &polys, int& npolys, unsigned short *&dmeshes, float *&dvertices, int &ndvertsuniq, unsigned short *&dtris, int& ndtris, int &vertsPerPoly) { DerivedMesh* dm = mesh_create_derived_no_virtual(KX_GetActiveScene()->GetBlenderScene(), GetBlenderObject(), NULL, CD_MASK_MESH); int* recastData = (int*) dm->getFaceDataArray(dm, CD_RECAST); if (recastData) { int *dtrisToPolysMap=NULL, *dtrisToTrisMap=NULL, *trisToFacesMap=NULL; int nAllVerts = 0; float *allVerts = NULL; buildNavMeshDataByDerivedMesh(dm, &vertsPerPoly, &nAllVerts, &allVerts, &ndtris, &dtris, &npolys, &dmeshes, &polys, &dtrisToPolysMap, &dtrisToTrisMap, &trisToFacesMap); MEM_freeN(dtrisToPolysMap); MEM_freeN(dtrisToTrisMap); MEM_freeN(trisToFacesMap); unsigned short *verticesMap = new unsigned short[nAllVerts]; memset(verticesMap, 0xffff, sizeof(unsigned short)*nAllVerts); int curIdx = 0; //vertices - mesh verts //iterate over all polys and create map for their vertices first... for (int polyidx=0; polyidx<npolys; polyidx++) { unsigned short* poly = &polys[polyidx*vertsPerPoly*2]; for (int i=0; i<vertsPerPoly; i++) { unsigned short idx = poly[i]; if (idx==0xffff) break; if (verticesMap[idx]==0xffff) { verticesMap[idx] = curIdx++; } poly[i] = verticesMap[idx]; } } nverts = curIdx; //...then iterate over detailed meshes //transform indices to local ones (for each navigation polygon) for (int polyidx=0; polyidx<npolys; polyidx++) { unsigned short *poly = &polys[polyidx*vertsPerPoly*2]; int nv = polyNumVerts(poly, vertsPerPoly); unsigned short *dmesh = &dmeshes[4*polyidx]; unsigned short tribase = dmesh[2]; unsigned short trinum = dmesh[3]; unsigned short vbase = curIdx; for (int j=0; j<trinum; j++) { unsigned short* dtri = &dtris[(tribase+j)*3*2]; for (int k=0; k<3; k++) { int newVertexIdx = verticesMap[dtri[k]]; if (newVertexIdx==0xffff) { newVertexIdx = curIdx++; verticesMap[dtri[k]] = newVertexIdx; } if (newVertexIdx<nverts) { //it's polygon vertex ("shared") int idxInPoly = polyFindVertex(poly, vertsPerPoly, newVertexIdx); if (idxInPoly==-1) { printf("Building NavMeshObject: Error! Can't find vertex in polygon\n"); return false; } dtri[k] = idxInPoly; } else { dtri[k] = newVertexIdx - vbase + nv; } } } dmesh[0] = vbase-nverts; //verts base dmesh[1] = curIdx-vbase; //verts num } vertices = new float[nverts*3]; ndvertsuniq = curIdx - nverts; if (ndvertsuniq>0) { dvertices = new float[ndvertsuniq*3]; } for (int vi=0; vi<nAllVerts; vi++) { int newIdx = verticesMap[vi]; if (newIdx!=0xffff) { if (newIdx<nverts) { //navigation mesh vertex memcpy(vertices+3*newIdx, allVerts+3*vi, 3*sizeof(float)); } else { //detailed mesh vertex memcpy(dvertices+3*(newIdx-nverts), allVerts+3*vi, 3*sizeof(float)); } } } MEM_freeN(allVerts); } else { //create from RAS_MeshObject (detailed mesh is fake) RAS_MeshObject* meshobj = GetMesh(0); vertsPerPoly = 3; nverts = meshobj->m_sharedvertex_map.size(); if (nverts >= 0xffff) return false; //calculate count of tris int nmeshpolys = meshobj->NumPolygons(); npolys = nmeshpolys; for (int p=0; p<nmeshpolys; p++) { int vertcount = meshobj->GetPolygon(p)->VertexCount(); npolys+=vertcount-3; } //create verts vertices = new float[nverts*3]; float* vert = vertices; for (int vi=0; vi<nverts; vi++) { const float* pos = !meshobj->m_sharedvertex_map[vi].empty() ? meshobj->GetVertexLocation(vi) : NULL; if (pos) copy_v3_v3(vert, pos); else { memset(vert, 0, 3*sizeof(float)); //vertex isn't in any poly, set dummy zero coordinates } vert+=3; } //create tris polys = new unsigned short[npolys*3*2]; memset(polys, 0xff, sizeof(unsigned short)*3*2*npolys); unsigned short *poly = polys; RAS_Polygon* raspoly; for (int p=0; p<nmeshpolys; p++) { raspoly = meshobj->GetPolygon(p); for (int v=0; v<raspoly->VertexCount()-2; v++) { poly[0]= raspoly->GetVertex(0)->getOrigIndex(); for (size_t i=1; i<3; i++) { poly[i]= raspoly->GetVertex(v+i)->getOrigIndex(); } poly += 6; } } dmeshes = NULL; dvertices = NULL; ndvertsuniq = 0; dtris = NULL; ndtris = npolys; } dm->release(dm); return true; }
void KX_FontObject::ProcessReplica() { KX_GameObject::ProcessReplica(); KX_GetActiveScene()->AddFont(this); }
bool KX_KetsjiEngine::NextFrame() { double timestep = 1.0/m_ticrate; double framestep = timestep; // static hidden::Clock sClock; m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); //float dt = sClock.getTimeMicroseconds() * 0.000001f; //sClock.reset(); if (m_bFixedTime) m_clockTime += timestep; else { // m_clockTime += dt; m_clockTime = m_kxsystem->GetTimeInSeconds(); } double deltatime = m_clockTime - m_frameTime; if (deltatime<0.f) { printf("problem with clock\n"); deltatime = 0.f; m_clockTime = 0.f; m_frameTime = 0.f; } // Compute the number of logic frames to do each update (fixed tic bricks) int frames =int(deltatime*m_ticrate+1e-6); // if (frames>1) // printf("****************************************"); // printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames); // if (!frames) // PIL_sleep_ms(1); KX_SceneList::iterator sceneit; if (frames>m_maxPhysicsFrame) { // printf("framedOut: %d\n",frames); m_frameTime+=(frames-m_maxPhysicsFrame)*timestep; frames = m_maxPhysicsFrame; } bool doRender = frames>0; if (frames > m_maxLogicFrame) { framestep = (frames*timestep)/m_maxLogicFrame; frames = m_maxLogicFrame; } while (frames) { m_frameTime += framestep; for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) // for each scene, call the proceed functions { KX_Scene* scene = *sceneit; /* Suspension holds the physics and logic processing for an * entire scene. Objects can be suspended individually, and * the settings for that preceed the logic and physics * update. */ m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); m_sceneconverter->resetNoneDynamicObjectToIpo();//this is for none dynamic objects with ipo scene->UpdateObjectActivity(); if (!scene->IsSuspended()) { // if the scene was suspended recalcutlate the delta tu "curtime" m_suspendedtime = scene->getSuspendedTime(); if (scene->getSuspendedTime()!=0.0) scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime()); m_suspendeddelta = scene->getSuspendedDelta(); m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_NETWORK); scene->GetNetworkScene()->proceed(m_frameTime); //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); //SG_SetActiveStage(SG_STAGE_NETWORK_UPDATE); //scene->UpdateParents(m_frameTime); m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS1); // set Python hooks for each scene #ifdef WITH_PYTHON PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); #endif KX_SetActiveScene(scene); scene->GetPhysicsEnvironment()->endFrame(); // Update scenegraph after physics step. This maps physics calculations // into node positions. //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); //SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE); //scene->UpdateParents(m_frameTime); // Process sensors, and controllers m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_CONTROLLER); scene->LogicBeginFrame(m_frameTime); // Scenegraph needs to be updated again, because Logic Controllers // can affect the local matrices. m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_CONTROLLER_UPDATE); scene->UpdateParents(m_frameTime); // Process actuators // Do some cleanup work for this logic frame m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ACTUATOR); scene->LogicUpdateFrame(m_frameTime, true); scene->LogicEndFrame(); // Actuators can affect the scenegraph m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE); scene->UpdateParents(m_frameTime); if (!GetRestrictAnimationFPS()) { m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE); scene->UpdateAnimations(m_frameTime); } m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2); scene->GetPhysicsEnvironment()->beginFrame(); // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,timestep,framestep);//m_deltatimerealDeltaTime); m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE); scene->UpdateParents(m_frameTime); if (m_animation_record) { m_sceneconverter->WritePhysicsObjectToAnimationIpo(++m_currentFrame); } scene->setSuspendedTime(0.0); } // suspended else if(scene->getSuspendedTime()==0.0) scene->setSuspendedTime(m_clockTime); m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true); } // update system devices m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); if (m_keyboarddevice) m_keyboarddevice->NextFrame(); if (m_mousedevice) m_mousedevice->NextFrame(); if (m_networkdevice) m_networkdevice->NextFrame(); // scene management ProcessScheduledScenes(); frames--; } bool bUseAsyncLogicBricks= false;//true; if (bUseAsyncLogicBricks) { // Logic update sub frame: this will let some logic bricks run at the // full frame rate. for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) // for each scene, call the proceed functions { KX_Scene* scene = *sceneit; if (!scene->IsSuspended()) { // if the scene was suspended recalcutlate the delta tu "curtime" m_suspendedtime = scene->getSuspendedTime(); if (scene->getSuspendedTime()!=0.0) scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime()); m_suspendeddelta = scene->getSuspendedDelta(); // set Python hooks for each scene #ifdef WITH_PYTHON PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); #endif KX_SetActiveScene(scene); m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS1); scene->UpdateParents(m_clockTime); // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep); // Update scenegraph after physics step. This maps physics calculations // into node positions. m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2); scene->UpdateParents(m_clockTime); // Do some cleanup work for this logic frame m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); scene->LogicUpdateFrame(m_clockTime, false); // Actuators can affect the scenegraph m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ACTUATOR); scene->UpdateParents(m_clockTime); scene->setSuspendedTime(0.0); } // suspended else if(scene->getSuspendedTime()==0.0) scene->setSuspendedTime(m_clockTime); m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true); } } // Handle the animations independently of the logic time step if (GetRestrictAnimationFPS()) { m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE); double anim_timestep = 1.0/KX_GetActiveScene()->GetAnimationFPS(); if (m_clockTime - m_previousAnimTime > anim_timestep) { // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep) // printf("Anim fps: %f\n", 1.0/(m_clockTime - m_previousAnimTime)); m_previousAnimTime = m_clockTime; for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) { (*sceneit)->UpdateAnimations(m_frameTime); } } m_previousClockTime = m_clockTime; } // Start logging time spend outside main loop m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true); return doRender; }
int BL_ArmatureConstraint::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { BL_ArmatureConstraint* self = static_cast<BL_ArmatureConstraint*>(self_v); bConstraint* constraint = self->m_constraint; bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL; int attr_order = attrdef-Attributes; int ival; double dval; // char* sval; SCA_LogicManager *logicmgr = KX_GetActiveScene()->GetLogicManager(); KX_GameObject *oval; if (!constraint) { PyErr_SetString(PyExc_AttributeError, "constraint is NULL"); return PY_SET_ATTR_FAIL; } switch (attr_order) { case BCA_ENFORCE: dval = PyFloat_AsDouble(value); if (dval < 0.0 || dval > 1.0) { /* also accounts for non float */ PyErr_SetString(PyExc_AttributeError, "constraint.enforce = float: BL_ArmatureConstraint, expected a float between 0 and 1"); return PY_SET_ATTR_FAIL; } constraint->enforce = dval; return PY_SET_ATTR_SUCCESS; case BCA_HEADTAIL: dval = PyFloat_AsDouble(value); if (dval < 0.0 || dval > 1.0) { /* also accounts for non float */ PyErr_SetString(PyExc_AttributeError, "constraint.headtail = float: BL_ArmatureConstraint, expected a float between 0 and 1"); return PY_SET_ATTR_FAIL; } constraint->headtail = dval; return PY_SET_ATTR_SUCCESS; case BCA_TARGET: if (!ConvertPythonToGameObject(logicmgr, value, &oval, true, "constraint.target = value: BL_ArmatureConstraint")) return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error self->SetTarget(oval); return PY_SET_ATTR_SUCCESS; case BCA_SUBTARGET: if (!ConvertPythonToGameObject(logicmgr, value, &oval, true, "constraint.subtarget = value: BL_ArmatureConstraint")) return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error self->SetSubtarget(oval); return PY_SET_ATTR_SUCCESS; case BCA_ACTIVE: ival = PyObject_IsTrue( value ); if (ival == -1) { PyErr_SetString(PyExc_AttributeError, "constraint.active = bool: BL_ArmatureConstraint, expected True or False"); return PY_SET_ATTR_FAIL; } self->m_constraint->flag = (self->m_constraint->flag & ~CONSTRAINT_OFF) | ((ival)?0:CONSTRAINT_OFF); return PY_SET_ATTR_SUCCESS; case BCA_IKWEIGHT: case BCA_IKDIST: case BCA_IKMODE: if (!ikconstraint) { PyErr_SetString(PyExc_AttributeError, "constraint is not of IK type"); return PY_SET_ATTR_FAIL; } switch (attr_order) { case BCA_IKWEIGHT: dval = PyFloat_AsDouble(value); if (dval < 0.0 || dval > 1.0) { /* also accounts for non float */ PyErr_SetString(PyExc_AttributeError, "constraint.weight = float: BL_ArmatureConstraint, expected a float between 0 and 1"); return PY_SET_ATTR_FAIL; } ikconstraint->weight = dval; return PY_SET_ATTR_SUCCESS; case BCA_IKDIST: dval = PyFloat_AsDouble(value); if (dval < 0.0) { /* also accounts for non float */ PyErr_SetString(PyExc_AttributeError, "constraint.ik_dist = float: BL_ArmatureConstraint, expected a positive float"); return PY_SET_ATTR_FAIL; } ikconstraint->dist = dval; return PY_SET_ATTR_SUCCESS; case BCA_IKMODE: ival = PyLong_AsLong(value); if (ival < 0) { PyErr_SetString(PyExc_AttributeError, "constraint.ik_mode = integer: BL_ArmatureConstraint, expected a positive integer"); return PY_SET_ATTR_FAIL; } ikconstraint->mode = ival; return PY_SET_ATTR_SUCCESS; } // should not come here break; } PyErr_SetString(PyExc_AttributeError, "constraint unknown attribute"); return PY_SET_ATTR_FAIL; }