PyObject *KX_MouseFocusSensor::pyattr_get_ray_direction(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_MouseFocusSensor* self = static_cast<KX_MouseFocusSensor*>(self_v); MT_Vector3 dir = self->RayTarget() - self->RaySource(); if (MT_fuzzyZero(dir)) dir.setValue(0,0,0); else dir.normalize(); return PyObjectFrom(dir); }
/* vectomat function obtained from constrain.c and modified to work with MOTO library */ static MT_Matrix3x3 vectomat(MT_Vector3 vec, short axis, short upflag, short threedimup) { MT_Matrix3x3 mat; MT_Vector3 y(MT_Scalar(0.0f), MT_Scalar(1.0f), MT_Scalar(0.0f)); MT_Vector3 z(MT_Scalar(0.0f), MT_Scalar(0.0f), MT_Scalar(1.0f)); /* world Z axis is the global up axis */ MT_Vector3 proj; MT_Vector3 right; MT_Scalar mul; int right_index; /* Normalized Vec vector*/ vec = vec.safe_normalized_vec(z); /* if 2D doesn't move the up vector */ if (!threedimup) { vec.setValue(MT_Scalar(vec[0]), MT_Scalar(vec[1]), MT_Scalar(0.0f)); vec = (vec - z.dot(vec)*z).safe_normalized_vec(z); } if (axis > 2) axis -= 3; else vec = -vec; /* project the up vector onto the plane specified by vec */ /* first z onto vec... */ mul = z.dot(vec) / vec.dot(vec); proj = vec * mul; /* then onto the plane */ proj = z - proj; /* proj specifies the transformation of the up axis */ proj = proj.safe_normalized_vec(y); /* Normalized cross product of vec and proj specifies transformation of the right axis */ right = proj.cross(vec); right.normalize(); if (axis != upflag) { right_index = 3 - axis - upflag; /* account for up direction, track direction */ right = right * basis_cross(axis, upflag); mat.setRow(right_index, right); mat.setRow(upflag, proj); mat.setRow(axis, vec); mat = mat.inverse(); } /* identity matrix - don't do anything if the two axes are the same */ else { mat.setIdentity(); } return mat; }
void RAS_CalcTexMatrix(RAS_TexVert p[3],MT_Point3& origin,MT_Vector3& udir,MT_Vector3& vdir) { // precondition: 3 vertices are non-colinear MT_Vector3 vec1 = p[1].xyz()-p[0].xyz(); MT_Vector3 vec2 = p[2].xyz()-p[0].xyz(); MT_Vector3 normal = vec1.cross(vec2); normal.normalize(); // determine which coordinate we drop, ie. max coordinate in the normal int ZCOORD = normal.closestAxis(); int XCOORD = (ZCOORD+1)%3; int YCOORD = (ZCOORD+2)%3; // ax+by+cz+d=0 MT_Scalar d = -p[0].xyz().dot(normal); MT_Matrix3x3 mat3( p[0].getUV1()[0],p[0].getUV1()[1], 1, p[1].getUV1()[0],p[1].getUV1()[1], 1, p[2].getUV1()[0],p[2].getUV1()[1], 1); MT_Matrix3x3 mat3inv = mat3.inverse(); MT_Vector3 p123x(p[0].xyz()[XCOORD],p[1].xyz()[XCOORD],p[2].xyz()[XCOORD]); MT_Vector3 resultx = mat3inv*p123x; MT_Vector3 p123y(p[0].xyz()[YCOORD],p[1].xyz()[YCOORD],p[2].xyz()[YCOORD]); MT_Vector3 resulty = mat3inv*p123y; // normal[ZCOORD] is not zero, because it's chosen to be maximal (absolute), and normal has length 1, // so at least on of the coords is <> 0 //droppedvalue udir.dot(normal) =0 MT_Scalar droppedu = -(resultx.x()*normal[XCOORD]+resulty.x()*normal[YCOORD])/normal[ZCOORD]; udir[XCOORD] = resultx.x(); udir[YCOORD] = resulty.x(); udir[ZCOORD] = droppedu; MT_Scalar droppedv = -(resultx.y()*normal[XCOORD]+resulty.y()*normal[YCOORD])/normal[ZCOORD]; vdir[XCOORD] = resultx.y(); vdir[YCOORD] = resulty.y(); vdir[ZCOORD] = droppedv; // droppedvalue b = -(ax+cz+d)/y; MT_Scalar droppedvalue = -((resultx.z()*normal[XCOORD] + resulty.z()*normal[YCOORD]+d))/normal[ZCOORD]; origin[XCOORD] = resultx.z(); origin[YCOORD] = resulty.z(); origin[ZCOORD] = droppedvalue; }
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) */
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); } } }
bool KX_RaySensor::Evaluate() { bool result = false; bool reset = m_reset && m_level; m_rayHit = false; m_hitObject = NULL; m_hitPosition[0] = 0; m_hitPosition[1] = 0; m_hitPosition[2] = 0; m_hitNormal[0] = 1; m_hitNormal[1] = 0; m_hitNormal[2] = 0; KX_GameObject* obj = (KX_GameObject*)GetParent(); MT_Point3 frompoint = obj->NodeGetWorldPosition(); MT_Matrix3x3 matje = obj->NodeGetWorldOrientation(); MT_Matrix3x3 invmat = matje.inverse(); MT_Vector3 todir; m_reset = false; switch (m_axis) { case SENS_RAY_X_AXIS: // X { todir[0] = invmat[0][0]; todir[1] = invmat[0][1]; todir[2] = invmat[0][2]; break; } case SENS_RAY_Y_AXIS: // Y { todir[0] = invmat[1][0]; todir[1] = invmat[1][1]; todir[2] = invmat[1][2]; break; } case SENS_RAY_Z_AXIS: // Z { todir[0] = invmat[2][0]; todir[1] = invmat[2][1]; todir[2] = invmat[2][2]; break; } case SENS_RAY_NEG_X_AXIS: // -X { todir[0] = -invmat[0][0]; todir[1] = -invmat[0][1]; todir[2] = -invmat[0][2]; break; } case SENS_RAY_NEG_Y_AXIS: // -Y { todir[0] = -invmat[1][0]; todir[1] = -invmat[1][1]; todir[2] = -invmat[1][2]; break; } case SENS_RAY_NEG_Z_AXIS: // -Z { todir[0] = -invmat[2][0]; todir[1] = -invmat[2][1]; todir[2] = -invmat[2][2]; break; } } todir.normalize(); m_rayDirection[0] = todir[0]; m_rayDirection[1] = todir[1]; m_rayDirection[2] = todir[2]; MT_Point3 topoint = frompoint + (m_distance) * todir; PHY_IPhysicsEnvironment* pe = m_scene->GetPhysicsEnvironment(); if (!pe) { std::cout << "WARNING: Ray sensor " << GetName() << ": There is no physics environment!" << std::endl; std::cout << " Check universe for malfunction." << std::endl; return false; } KX_IPhysicsController *spc = obj->GetPhysicsController(); KX_GameObject *parent = obj->GetParent(); if (!spc && parent) spc = parent->GetPhysicsController(); if (parent) parent->Release(); PHY_IPhysicsEnvironment* physics_environment = this->m_scene->GetPhysicsEnvironment(); KX_RayCast::Callback<KX_RaySensor> callback(this, spc); KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback); /* now pass this result to some controller */ if (m_rayHit) { if (!m_bTriggered) { // notify logicsystem that ray is now hitting result = true; m_bTriggered = true; } else { // notify logicsystem that ray is STILL hitting ... result = false; } } else { if (m_bTriggered) { m_bTriggered = false; // notify logicsystem that ray JUST left the Object result = true; } else { result = false; } } if (reset) // force an event result = true; return result; }
void KX_SteeringActuator::HandleActorFace(MT_Vector3& velocity) { if (m_facingMode==0 && (!m_navmesh || !m_normalUp)) return; KX_GameObject* curobj = (KX_GameObject*) GetParent(); MT_Vector3 dir = m_facingMode==0 ? curobj->NodeGetLocalOrientation().getColumn(1) : velocity; if (dir.fuzzyZero()) return; dir.normalize(); MT_Vector3 up(0,0,1); MT_Vector3 left; MT_Matrix3x3 mat; if (m_navmesh && m_normalUp) { dtStatNavMesh* navmesh = m_navmesh->GetNavMesh(); MT_Vector3 normal; MT_Vector3 trpos = m_navmesh->TransformToLocalCoords(curobj->NodeGetWorldPosition()); if (getNavmeshNormal(navmesh, trpos, normal)) { left = (dir.cross(up)).safe_normalized(); dir = (-left.cross(normal)).safe_normalized(); up = normal; } } switch (m_facingMode) { case 1: // TRACK X { left = dir.safe_normalized(); dir = -(left.cross(up)).safe_normalized(); break; }; case 2: // TRACK Y { left = (dir.cross(up)).safe_normalized(); break; } case 3: // track Z { left = up.safe_normalized(); up = dir.safe_normalized(); dir = left; left = (dir.cross(up)).safe_normalized(); break; } case 4: // TRACK -X { left = -dir.safe_normalized(); dir = -(left.cross(up)).safe_normalized(); break; }; case 5: // TRACK -Y { left = (-dir.cross(up)).safe_normalized(); dir = -dir; break; } case 6: // track -Z { left = up.safe_normalized(); up = -dir.safe_normalized(); dir = left; left = (dir.cross(up)).safe_normalized(); break; } } mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], left[2], dir[2],up[2] ); KX_GameObject* parentObject = curobj->GetParent(); if (parentObject) { MT_Vector3 localpos; localpos = curobj->GetSGNode()->GetLocalPosition(); MT_Matrix3x3 parentmatinv; parentmatinv = parentObject->NodeGetWorldOrientation ().inverse (); mat = parentmatinv * mat; mat = m_parentlocalmat * mat; curobj->NodeSetLocalOrientation(mat); curobj->NodeSetLocalPosition(localpos); } else { curobj->NodeSetLocalOrientation(mat); } }
bool KX_TrackToActuator::Update(double curtime, bool frame) { bool result = false; bool bNegativeEvent = IsNegativeEvent(); RemoveAllEvents(); if (bNegativeEvent) { // do nothing on negative events } else if (m_object) { KX_GameObject* curobj = (KX_GameObject*) GetParent(); MT_Vector3 dir = ((KX_GameObject*)m_object)->NodeGetWorldPosition() - curobj->NodeGetWorldPosition(); if (dir.length2()) dir.normalize(); MT_Vector3 up(0,0,1); #ifdef DSADSA switch (m_upflag) { case 0: { up.setValue(1.0,0,0); break; } case 1: { up.setValue(0,1.0,0); break; } case 2: default: { up.setValue(0,0,1.0); } } #endif if (m_allow3D) { up = (up - up.dot(dir) * dir).safe_normalized(); } else { dir = (dir - up.dot(dir)*up).safe_normalized(); } MT_Vector3 left; MT_Matrix3x3 mat; switch (m_trackflag) { case 0: // TRACK X { // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up left = dir.safe_normalized(); dir = (left.cross(up)).safe_normalized(); mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], left[2], dir[2],up[2] ); break; }; case 1: // TRACK Y { // (0.0 , 1.0 , 0.0 ) y direction is forward, z (0.0 , 0.0 , 1.0 ) up left = (dir.cross(up)).safe_normalized(); mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], left[2], dir[2],up[2] ); break; } case 2: // track Z { left = up.safe_normalized(); up = dir.safe_normalized(); dir = left; left = (dir.cross(up)).safe_normalized(); mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], left[2], dir[2],up[2] ); break; } case 3: // TRACK -X { // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up left = -dir.safe_normalized(); dir = -(left.cross(up)).safe_normalized(); mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], left[2], dir[2],up[2] ); break; }; case 4: // TRACK -Y { // (0.0 , -1.0 , 0.0 ) -y direction is forward, z (0.0 , 0.0 , 1.0 ) up left = (-dir.cross(up)).safe_normalized(); mat.setValue ( left[0], -dir[0],up[0], left[1], -dir[1],up[1], left[2], -dir[2],up[2] ); break; } case 5: // track -Z { left = up.safe_normalized(); up = -dir.safe_normalized(); dir = left; left = (dir.cross(up)).safe_normalized(); mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], left[2], dir[2],up[2] ); break; } default: { // (1.0 , 0.0 , 0.0 ) -x direction is forward, z (0.0 , 0.0 , 1.0 ) up left = -dir.safe_normalized(); dir = -(left.cross(up)).safe_normalized(); mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], left[2], dir[2],up[2] ); } } MT_Matrix3x3 oldmat; oldmat= curobj->NodeGetWorldOrientation(); /* erwin should rewrite this! */ mat= matrix3x3_interpol(oldmat, mat, m_time); if(m_parentobj){ // check if the model is parented and calculate the child transform MT_Point3 localpos; localpos = curobj->GetSGNode()->GetLocalPosition(); // Get the inverse of the parent matrix MT_Matrix3x3 parentmatinv; parentmatinv = m_parentobj->NodeGetWorldOrientation ().inverse (); // transform the local coordinate system into the parents system mat = parentmatinv * mat; // append the initial parent local rotation matrix mat = m_parentlocalmat * mat; // set the models tranformation properties curobj->NodeSetLocalOrientation(mat); curobj->NodeSetLocalPosition(localpos); //curobj->UpdateTransform(); } else { curobj->NodeSetLocalOrientation(mat); } result = true; } return result; }