MT_CmMatrix4x4::MT_CmMatrix4x4(const MT_Point3& orig, const MT_Vector3& dir, const MT_Vector3 up) { MT_Vector3 z = -(dir.normalized()); MT_Vector3 x = (up.cross(z)).normalized(); MT_Vector3 y = (z.cross(x)); m_V[0][0] = x.x(); m_V[0][1] = y.x(); m_V[0][2] = z.x(); m_V[0][3] = 0.0f; m_V[1][0] = x.y(); m_V[1][1] = y.y(); m_V[1][2] = z.y(); m_V[1][3] = 0.0f; m_V[2][0] = x.z(); m_V[2][1] = y.z(); m_V[2][2] = z.z(); m_V[2][3] = 0.0f; m_V[3][0] = orig.x();//0.0f; m_V[3][1] = orig.y();//0.0f; m_V[3][2] = orig.z();//0.0f; m_V[3][3] = 1.0f; //Translate(-orig); }
static MT_Point3 nearestPointToObstacle(MT_Point3& pos ,KX_Obstacle* obstacle) { switch (obstacle->m_shape) { case KX_OBSTACLE_SEGMENT : { MT_Vector3 ab = obstacle->m_pos2 - obstacle->m_pos; if (!ab.fuzzyZero()) { MT_Vector3 abdir = ab.normalized(); MT_Vector3 v = pos - obstacle->m_pos; MT_Scalar proj = abdir.dot(v); CLAMP(proj, 0, ab.length()); MT_Point3 res = obstacle->m_pos + abdir*proj; return res; } } case KX_OBSTACLE_CIRCLE : default: return obstacle->m_pos; } }
bool KX_ObjectActuator::Update() { bool bNegativeEvent = IsNegativeEvent(); RemoveAllEvents(); KX_GameObject *parent = static_cast<KX_GameObject *>(GetParent()); PHY_ICharacter *character = parent->GetScene()->GetPhysicsEnvironment()->GetCharacterController(parent); if (bNegativeEvent) { // If we previously set the linear velocity we now have to inform // the physics controller that we no longer wish to apply it and that // it should reconcile the externally set velocity with it's // own velocity. if (m_active_combined_velocity) { if (parent) parent->ResolveCombinedVelocities( m_linear_velocity, m_angular_velocity, (m_bitLocalFlag.LinearVelocity) != 0, (m_bitLocalFlag.AngularVelocity) != 0 ); m_active_combined_velocity = false; } // Explicitly stop the movement if we're using character motion if (m_bitLocalFlag.CharacterMotion) { character->SetWalkDirection(MT_Vector3 (0.0f, 0.0f, 0.0f)); } m_linear_damping_active = false; m_angular_damping_active = false; m_error_accumulator.setValue(0.0f,0.0f,0.0f); m_previous_error.setValue(0.0f,0.0f,0.0f); m_jumping = false; return false; } else if (parent) { if (m_bitLocalFlag.ServoControl) { // In this mode, we try to reach a target speed using force // As we don't know the friction, we must implement a generic // servo control to achieve the speed in a configurable // v = current velocity // V = target velocity // e = V-v = speed error // dt = time interval since previous update // I = sum(e(t)*dt) // dv = e(t) - e(t-1) // KP, KD, KI : coefficient // F = KP*e+KI*I+KD*dv MT_Scalar mass = parent->GetMass(); if (mass < MT_EPSILON) return false; MT_Vector3 v = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity); if (m_reference) { const MT_Point3& mypos = parent->NodeGetWorldPosition(); const MT_Point3& refpos = m_reference->NodeGetWorldPosition(); MT_Point3 relpos; relpos = (mypos-refpos); MT_Vector3 vel= m_reference->GetVelocity(relpos); if (m_bitLocalFlag.LinearVelocity) // must convert in local space vel = parent->NodeGetWorldOrientation().transposed()*vel; v -= vel; } MT_Vector3 e = m_linear_velocity - v; MT_Vector3 dv = e - m_previous_error; MT_Vector3 I = m_error_accumulator + e; m_force = m_pid.x()*e+m_pid.y()*I+m_pid.z()*dv; // to automatically adapt the PID coefficient to mass; m_force *= mass; if (m_bitLocalFlag.Torque) { if (m_force[0] > m_dloc[0]) { m_force[0] = m_dloc[0]; I[0] = m_error_accumulator[0]; } else if (m_force[0] < m_drot[0]) { m_force[0] = m_drot[0]; I[0] = m_error_accumulator[0]; } } if (m_bitLocalFlag.DLoc) { if (m_force[1] > m_dloc[1]) { m_force[1] = m_dloc[1]; I[1] = m_error_accumulator[1]; } else if (m_force[1] < m_drot[1]) { m_force[1] = m_drot[1]; I[1] = m_error_accumulator[1]; } } if (m_bitLocalFlag.DRot) { if (m_force[2] > m_dloc[2]) { m_force[2] = m_dloc[2]; I[2] = m_error_accumulator[2]; } else if (m_force[2] < m_drot[2]) { m_force[2] = m_drot[2]; I[2] = m_error_accumulator[2]; } } m_previous_error = e; m_error_accumulator = I; parent->ApplyForce(m_force,(m_bitLocalFlag.LinearVelocity) != 0); } else if (m_bitLocalFlag.CharacterMotion) { MT_Vector3 dir = m_dloc; if (m_bitLocalFlag.DLoc) { MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation(); dir = basis * dir; } if (m_bitLocalFlag.AddOrSetCharLoc) { MT_Vector3 old_dir = character->GetWalkDirection(); if (!old_dir.fuzzyZero()) { MT_Scalar mag = old_dir.length(); dir = dir + old_dir; if (!dir.fuzzyZero()) dir = dir.normalized() * mag; } } // We always want to set the walk direction since a walk direction of (0, 0, 0) should stop the character character->SetWalkDirection(dir/parent->GetScene()->GetPhysicsEnvironment()->GetNumTimeSubSteps()); if (!m_bitLocalFlag.ZeroDRot) { parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0); } if (m_bitLocalFlag.CharacterJump) { if (!m_jumping) { character->Jump(); m_jumping = true; } else if (character->OnGround()) m_jumping = false; } } else { if (!m_bitLocalFlag.ZeroForce) { parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0); } if (!m_bitLocalFlag.ZeroTorque) { parent->ApplyTorque(m_torque,(m_bitLocalFlag.Torque) != 0); } if (!m_bitLocalFlag.ZeroDLoc) { parent->ApplyMovement(m_dloc,(m_bitLocalFlag.DLoc) != 0); } if (!m_bitLocalFlag.ZeroDRot) { parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0); } if (m_bitLocalFlag.ZeroLinearVelocity) { if (!m_bitLocalFlag.AddOrSetLinV) { /* No need to select local or world, as the velocity is zero anyway, * and setLinearVelocity() converts local to world first. We do need to * pass a true zero vector, as m_linear_velocity is only fuzzily zero. */ parent->setLinearVelocity(MT_Vector3(0, 0, 0), false); } } else { if (m_bitLocalFlag.AddOrSetLinV) { parent->addLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0); } else { m_active_combined_velocity = true; if (m_damping > 0) { MT_Vector3 linV; if (!m_linear_damping_active) { // delta and the start speed (depends on the existing speed in that direction) linV = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity); // keep only the projection along the desired direction m_current_linear_factor = linV.dot(m_linear_velocity)/m_linear_length2; m_linear_damping_active = true; } if (m_current_linear_factor < 1.0f) m_current_linear_factor += 1.0f/m_damping; if (m_current_linear_factor > 1.0f) m_current_linear_factor = 1.0f; linV = m_current_linear_factor * m_linear_velocity; parent->setLinearVelocity(linV,(m_bitLocalFlag.LinearVelocity) != 0); } else { parent->setLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0); } } } if (m_bitLocalFlag.ZeroAngularVelocity) { /* No need to select local or world, as the velocity is zero anyway, * and setAngularVelocity() converts local to world first. We do need to * pass a true zero vector, as m_angular_velocity is only fuzzily zero. */ parent->setAngularVelocity(MT_Vector3(0, 0, 0), false); } else { m_active_combined_velocity = true; if (m_damping > 0) { MT_Vector3 angV; if (!m_angular_damping_active) { // delta and the start speed (depends on the existing speed in that direction) angV = parent->GetAngularVelocity(m_bitLocalFlag.AngularVelocity); // keep only the projection along the desired direction m_current_angular_factor = angV.dot(m_angular_velocity)/m_angular_length2; m_angular_damping_active = true; } if (m_current_angular_factor < 1.0f) m_current_angular_factor += 1.0f/m_damping; if (m_current_angular_factor > 1.0f) m_current_angular_factor = 1.0f; angV = m_current_angular_factor * m_angular_velocity; parent->setAngularVelocity(angV,(m_bitLocalFlag.AngularVelocity) != 0); } else { parent->setAngularVelocity(m_angular_velocity,(m_bitLocalFlag.AngularVelocity) != 0); } } } } return true; }
void RAS_OpenGLRasterizer::applyTransform(double* oglmatrix,int objectdrawmode ) { /* FIXME: blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed. Program received signal SIGABRT, Aborted. [Switching to Thread 16384 (LWP 1519)] 0x40477571 in kill () from /lib/libc.so.6 (gdb) bt #7 0x08334368 in MT_Vector3::normalized() const () #8 0x0833e6ec in RAS_OpenGLRasterizer::applyTransform(RAS_IRasterizer*, double*, int) () */ if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) { // rotate the billboard/halo //page 360/361 3D Game Engine Design, David Eberly for a discussion // on screen aligned and axis aligned billboards // assumed is that the preprocessor transformed all billboard polygons // so that their normal points into the positive x direction (1.0, 0.0, 0.0) // when new parenting for objects is done, this rotation // will be moved into the object MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); MT_Point3 campos = GetCameraPosition(); MT_Vector3 dir = (campos - objpos).safe_normalized(); MT_Vector3 up(0,0,1.0); KX_GameObject* gameobj = (KX_GameObject*)m_clientobject; // get scaling of halo object MT_Vector3 size = gameobj->GetSGNode()->GetWorldScaling(); bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned if (screenaligned) { up = (up - up.dot(dir) * dir).safe_normalized(); } else { dir = (dir - up.dot(dir)*up).safe_normalized(); } MT_Vector3 left = dir.normalized(); dir = (up.cross(left)).normalized(); // we have calculated the row vectors, now we keep // local scaling into account: left *= size[0]; dir *= size[1]; up *= size[2]; double maat[16] = {left[0], left[1], left[2], 0, dir[0], dir[1], dir[2], 0, up[0], up[1], up[2], 0, 0, 0, 0, 1}; glTranslated(objpos[0],objpos[1],objpos[2]); glMultMatrixd(maat); } else { if (objectdrawmode & RAS_IPolyMaterial::SHADOW) { // shadow must be cast to the ground, physics system needed here! MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); KX_GameObject *gameobj = (KX_GameObject*)m_clientobject; MT_Vector3 direction = MT_Vector3(0,0,-1); direction.normalize(); direction *= 100000; MT_Point3 topoint = frompoint + direction; KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment(); PHY_IPhysicsController* physics_controller = gameobj->GetPhysicsController(); KX_GameObject *parent = gameobj->GetParent(); if (!physics_controller && parent) physics_controller = parent->GetPhysicsController(); if (parent) parent->Release(); KX_RayCast::Callback<RAS_OpenGLRasterizer> callback(this, physics_controller, oglmatrix); if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback)) { // couldn't find something to cast the shadow on... glMultMatrixd(oglmatrix); } else { // we found the "ground", but the cast matrix doesn't take // scaling in consideration, so we must apply the object scale MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); glScalef(size[0], size[1], size[2]); } } else { // 'normal' object glMultMatrixd(oglmatrix); } } }