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); }
void MT_ExpMap:: angleUpdated( ){ m_theta = m_v.length(); reParametrize(); // compute quaternion, sinp and cosp if (m_theta < MT_EXPMAP_MINANGLE) { m_sinp = MT_Scalar(0.0); /* Taylor Series for sinc */ MT_Vector3 temp = m_v * MT_Scalar(MT_Scalar(.5) - m_theta*m_theta/MT_Scalar(48.0)); m_q.x() = temp.x(); m_q.y() = temp.y(); m_q.z() = temp.z(); m_q.w() = MT_Scalar(1.0); } else { m_sinp = MT_Scalar(sin(.5*m_theta)); /* Taylor Series for sinc */ MT_Vector3 temp = m_v * (m_sinp/m_theta); m_q.x() = temp.x(); m_q.y() = temp.y(); m_q.z() = temp.z(); m_q.w() = MT_Scalar(cos(.5*m_theta)); } }
void init(MT_Vector3 min,MT_Vector3 max) { GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 0.5}; /* Red diffuse light. */ GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */ GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 0.5}; /* Red diffuse light. */ GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */ /* Enable a single OpenGL light. */ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0); glLightfv(GL_LIGHT0, GL_POSITION, light_position0); glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1); glLightfv(GL_LIGHT1, GL_POSITION, light_position1); glEnable(GL_LIGHT0); // glEnable(GL_LIGHT1); glEnable(GL_LIGHTING); // use two sided lighting model glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); /* Use depth buffering for hidden surface elimination. */ glEnable(GL_DEPTH_TEST); /* Setup the view of the cube. */ glMatrixMode(GL_PROJECTION); // center of the box + 3* depth of box MT_Vector3 center = (min + max) * 0.5; MT_Vector3 diag = max - min; float depth = diag.length(); float distance = 2; gluPerspective( /* field of view in degree */ 40.0, /* aspect ratio */ 1.0, /* Z near */ 1.0, /* Z far */ distance * depth * 2 ); glMatrixMode(GL_MODELVIEW); gluLookAt( center.x(), center.y(), center.z() + distance*depth, /* eye is at (0,0,5) */ center.x(), center.y(), center.z(), /* center is at (0,0,0) */ 0.0, 1.0, 0.); /* up is in positive Y direction */ glPushMatrix(); }
/** * Computes the intersection between two lines (on the same plane). * @param vL1 first line vector * @param pL1 first line point * @param vL2 second line vector * @param pL2 second line point * @param intersection intersection point (if exists) * @return false if lines are parallels, true otherwise */ bool BOP_intersect(const MT_Vector3& vL1, const MT_Point3& pL1, const MT_Vector3& vL2, const MT_Point3& pL2, MT_Point3 &intersection) { // NOTE: // If the lines aren't on the same plane, the intersection point will not be valid. // So be careful !! MT_Scalar t = -1; MT_Scalar den = (vL1.y()*vL2.x() - vL1.x() * vL2.y()); if (!BOP_fuzzyZero(den)) { t = (pL2.y()*vL1.x() - vL1.y()*pL2.x() + pL1.x()*vL1.y() - pL1.y()*vL1.x()) / den ; } else { den = (vL1.y()*vL2.z() - vL1.z() * vL2.y()); if (!BOP_fuzzyZero(den)) { t = (pL2.y()*vL1.z() - vL1.y()*pL2.z() + pL1.z()*vL1.y() - pL1.y()*vL1.z()) / den ; } else { den = (vL1.x()*vL2.z() - vL1.z() * vL2.x()); if (!BOP_fuzzyZero(den)) { t = (pL2.x()*vL1.z() - vL1.x()*pL2.z() + pL1.z()*vL1.x() - pL1.x()*vL1.z()) / den ; } else { return false; } } } intersection.setValue(vL2.x()*t + pL2.x(), vL2.y()*t + pL2.y(), vL2.z()*t + pL2.z()); return true; }
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; }
void IK_QJacobian::SetDerivatives(int id, int dof_id, const MT_Vector3& v, MT_Scalar norm_weight) { m_jacobian[id + 0][dof_id] = v.x() * m_weight_sqrt[dof_id]; m_jacobian[id + 1][dof_id] = v.y() * m_weight_sqrt[dof_id]; m_jacobian[id + 2][dof_id] = v.z() * m_weight_sqrt[dof_id]; m_d_norm_weight[dof_id] = norm_weight; }
/** * Returns if three points lay on the same line (are collinears). * @param p1 point * @param p2 point * @param p3 point * @return true if the three points lay on the same line, false otherwise */ bool BOP_collinear(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3) { if( BOP_comp(p1,p2) == 0 || BOP_comp(p2,p3) == 0 ) return true; MT_Vector3 v1 = p2 - p1; MT_Vector3 v2 = p3 - p2; /* normalize vectors before taking their cross product, so its length * has some actual meaning */ // if(MT_fuzzyZero(v1.length()) || MT_fuzzyZero(v2.length())) return true; v1.normalize(); v2.normalize(); MT_Vector3 w = v1.cross(v2); return (BOP_fuzzyZero(w.x()) && BOP_fuzzyZero(w.y()) && BOP_fuzzyZero(w.z())); }
MT_Vector3 BSP_GhostTestApp3D:: UnProject( const MT_Vector3 & vec ) { GLint viewport[4]; GLdouble mvmatrix[16],projmatrix[16]; glGetIntegerv(GL_VIEWPORT,viewport); glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix); glGetDoublev(GL_PROJECTION_MATRIX,projmatrix); GLdouble realy = viewport[3] - vec.y() - 1; GLdouble outx,outy,outz; gluUnProject(vec.x(),realy,vec.z(),mvmatrix,projmatrix,viewport,&outx,&outy,&outz); return MT_Vector3(outx,outy,outz); }
void RAS_OpenGLRasterizer::FlushDebugShapes() { if (m_debugShapes.empty()) return; // DrawDebugLines GLboolean light, tex; light= glIsEnabled(GL_LIGHTING); tex= glIsEnabled(GL_TEXTURE_2D); if (light) glDisable(GL_LIGHTING); if (tex) glDisable(GL_TEXTURE_2D); //draw lines glBegin(GL_LINES); for (unsigned int i=0;i<m_debugShapes.size();i++) { if (m_debugShapes[i].m_type != OglDebugShape::LINE) continue; glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f); const MT_Scalar* fromPtr = &m_debugShapes[i].m_pos.x(); const MT_Scalar* toPtr= &m_debugShapes[i].m_param.x(); glVertex3dv(fromPtr); glVertex3dv(toPtr); } glEnd(); //draw circles for (unsigned int i=0;i<m_debugShapes.size();i++) { if (m_debugShapes[i].m_type != OglDebugShape::CIRCLE) continue; glBegin(GL_LINE_LOOP); glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f); static const MT_Vector3 worldUp(0.0, 0.0, 1.0); MT_Vector3 norm = m_debugShapes[i].m_param; MT_Matrix3x3 tr; if (norm.fuzzyZero() || norm == worldUp) { tr.setIdentity(); } else { MT_Vector3 xaxis, yaxis; xaxis = MT_cross(norm, worldUp); yaxis = MT_cross(xaxis, norm); tr.setValue(xaxis.x(), xaxis.y(), xaxis.z(), yaxis.x(), yaxis.y(), yaxis.z(), norm.x(), norm.y(), norm.z()); } MT_Scalar rad = m_debugShapes[i].m_param2.x(); int n = (int) m_debugShapes[i].m_param2.y(); for (int j = 0; j<n; j++) { MT_Scalar theta = j*M_PI*2/n; MT_Vector3 pos(cos(theta) * rad, sin(theta) * rad, 0.0); pos = pos*tr; pos += m_debugShapes[i].m_pos; const MT_Scalar* posPtr = &pos.x(); glVertex3dv(posPtr); } glEnd(); } if (light) glEnable(GL_LIGHTING); if (tex) glEnable(GL_TEXTURE_2D); m_debugShapes.clear(); }
void KX_BulletPhysicsController::setScaling(const MT_Vector3& scaling) { CcdPhysicsController::setScaling(scaling.x(),scaling.y(),scaling.z()); }
void KX_BulletPhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool local) { CcdPhysicsController::SetLinearVelocity(lin_vel.x(),lin_vel.y(),lin_vel.z(),local); }
void KX_BulletPhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local) { CcdPhysicsController::SetAngularVelocity(ang_vel.x(),ang_vel.y(),ang_vel.z(),local); }
void KX_BulletPhysicsController::ApplyForce(const MT_Vector3& force,bool local) { CcdPhysicsController::ApplyForce(force.x(),force.y(),force.z(),local); }
LOD_Decimation_InfoPtr NewVertsFromFile( char * file_name, MT_Vector3 &min, MT_Vector3 &max ) { min = MT_Vector3(MT_INFINITY,MT_INFINITY,MT_INFINITY); max = MT_Vector3(-MT_INFINITY,-MT_INFINITY,-MT_INFINITY); PlyProperty vert_props[] = { /* list of property information for a vertex */ {"x", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,x), 0, 0, 0, 0}, {"y", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,y), 0, 0, 0, 0}, {"z", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,z), 0, 0, 0, 0}, }; PlyProperty face_props[] = { /* list of property information for a vertex */ {"intensity", PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,intensity), 0, 0, 0, 0}, {"vertex_indices", PLY_INT, PLY_INT, offsetof(LoadFace,verts), 1, PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,nverts)}, }; #if 0 MEM_SmartPtr<std::vector<float> > verts = new std::vector<float>; MEM_SmartPtr<std::vector<float> > vertex_normals = new std::vector<float>; MEM_SmartPtr<std::vector<int> > faces = new std::vector<int>; #else std::vector<float>* verts = new std::vector<float>; std::vector<float>* vertex_normals = new std::vector<float>; std::vector<int> * faces = new std::vector<int>; #endif int i,j; PlyFile *ply; int nelems; char **elist; int file_type; float version; int nprops; int num_elems; PlyProperty **plist; char *elem_name; LoadVertex load_vertex; LoadFace load_face; /* open a PLY file for reading */ ply = ply_open_for_reading(file_name, &nelems, &elist, &file_type, &version); if (ply == NULL) return NULL; /* go through each kind of element that we learned is in the file */ /* and read them */ for (i = 0; i < nelems; i++) { /* get the description of the first element */ elem_name = elist[i]; plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops); /* print the name of the element, for debugging */ /* if we're on vertex elements, read them in */ if (equal_strings ("vertex", elem_name)) { /* set up for getting vertex elements */ ply_get_property (ply, elem_name, &vert_props[0]); ply_get_property (ply, elem_name, &vert_props[1]); ply_get_property (ply, elem_name, &vert_props[2]); // make some memory for the vertices verts->reserve(num_elems); /* grab all the vertex elements */ for (j = 0; j < num_elems; j++) { /* grab and element from the file */ ply_get_element (ply, (void *)&load_vertex); // pass the vertex into the mesh builder. if (load_vertex.x < min.x()) { min.x() = load_vertex.x; } else if (load_vertex.x > max.x()) { max.x()= load_vertex.x; } if (load_vertex.y < min.y()) { min.y() = load_vertex.y; } else if (load_vertex.y > max.y()) { max.y()= load_vertex.y; } if (load_vertex.z < min.z()) { min.z() = load_vertex.z; } else if (load_vertex.z > max.z()) { max.z()= load_vertex.z; } verts->push_back(load_vertex.x); verts->push_back(load_vertex.y); verts->push_back(load_vertex.z); vertex_normals->push_back(1.0f); vertex_normals->push_back(0.0f); vertex_normals->push_back(0.0f); } } /* if we're on face elements, read them in */ if (equal_strings ("face", elem_name)) { /* set up for getting face elements */ // ply_get_property (ply, elem_name, &face_props[0]); ply_get_property (ply, elem_name, &face_props[1]); /* grab all the face elements */ for (j = 0; j < num_elems; j++) { ply_get_element (ply, (void *)&load_face); faces->push_back(load_face.verts[0]); faces->push_back(load_face.verts[1]); faces->push_back(load_face.verts[2]); // free up the memory this pile of shit used to allocate the polygon's vertices free (load_face.verts); } } } /* close the PLY file */ ply_close (ply); LOD_Decimation_InfoPtr output = new LOD_Decimation_Info; output->vertex_buffer = verts->begin(); output->vertex_num = verts->size()/3; output->triangle_index_buffer = faces->begin(); output->face_num = faces->size()/3; output->intern = NULL; output->vertex_normal_buffer = vertex_normals->begin(); // memory leaks 'r' us #if 0 verts.Release(); vertex_normals.Release(); faces.Release(); #endif return output; }
void IK_QJacobian::SetBetas(int id, int, const MT_Vector3& v) { m_beta[id] = v.x(); m_beta[id+1] = v.y(); m_beta[id+2] = v.z(); }
void IK_QJacobian::SetDerivatives(int id, int dof_id, const MT_Vector3& v) { m_jacobian[id][dof_id] = v.x()*m_weight_sqrt[dof_id]; m_jacobian[id+1][dof_id] = v.y()*m_weight_sqrt[dof_id]; m_jacobian[id+2][dof_id] = v.z()*m_weight_sqrt[dof_id]; }
bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp) { if (m_locked[0] && m_locked[1]) return false; MT_Vector3 dq; dq.x() = jacobian.AngleUpdate(m_DoF_id); dq.y() = 0.0; dq.z() = jacobian.AngleUpdate(m_DoF_id+1); // Directly update the rotation matrix, with Rodrigues' rotation formula, // to avoid singularities and allow smooth integration. MT_Scalar theta = dq.length(); if (!MT_fuzzyZero(theta)) { MT_Vector3 w = dq*(1.0/theta); MT_Scalar sine = sin(theta); MT_Scalar cosine = cos(theta); MT_Scalar cosineInv = 1-cosine; MT_Scalar xsine = w.x()*sine; MT_Scalar zsine = w.z()*sine; MT_Scalar xxcosine = w.x()*w.x()*cosineInv; MT_Scalar xzcosine = w.x()*w.z()*cosineInv; MT_Scalar zzcosine = w.z()*w.z()*cosineInv; MT_Matrix3x3 M( cosine + xxcosine, -zsine, xzcosine, zsine, cosine, -xsine, xzcosine, xsine, cosine + zzcosine); m_new_basis = m_basis*M; RemoveTwist(m_new_basis); } else m_new_basis = m_basis; if (m_limit_x == false && m_limit_z == false) return false; MT_Vector3 a = SphericalRangeParameters(m_new_basis); MT_Scalar ax = 0, az = 0; clamp[0] = clamp[1] = false; if (m_limit_x && m_limit_z) { ax = a.x(); az = a.z(); if (EllipseClamp(ax, az, m_min, m_max)) clamp[0] = clamp[1] = true; } else if (m_limit_x) { if (ax < m_min[0]) { ax = m_min[0]; clamp[0] = true; } else if (ax > m_max[0]) { ax = m_max[0]; clamp[0] = true; } } else if (m_limit_z) { if (az < m_min[1]) { az = m_min[1]; clamp[1] = true; } else if (az > m_max[1]) { az = m_max[1]; clamp[1] = true; } } if (clamp[0] == false && clamp[1] == false) return false; m_new_basis = ComputeSwingMatrix(ax, az); delta = MatrixToAxisAngle(m_basis.transposed()*m_new_basis); delta[1] = delta[2]; delta[2] = 0.0; return true; }
void BSP_GhostTestApp3D:: InitOpenGl( const MT_Vector3 &min, const MT_Vector3 &max ){ GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 0.5}; /* Red diffuse light. */ GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */ GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 0.5}; /* Red diffuse light. */ GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */ /* Enable a single OpenGL light. */ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0); glLightfv(GL_LIGHT0, GL_POSITION, light_position0); glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1); glLightfv(GL_LIGHT1, GL_POSITION, light_position1); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glEnable(GL_LIGHTING); // make sure there is no back face culling. // glDisable(GL_CULL_FACE); // use two sided lighting model glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); /* Use depth buffering for hidden surface elimination. */ glEnable(GL_DEPTH_TEST); /* Setup the view of the cube. */ glMatrixMode(GL_PROJECTION); // center of the box + 3* depth of box MT_Vector3 center = (min + max) * 0.5; MT_Vector3 diag = max - min; float depth = diag.length(); float distance = 5; gluPerspective( /* field of view in degree */ 40.0, /* aspect ratio */ 1.0, /* Z near */ 1.0, /* Z far */ distance * depth * 2 ); glMatrixMode(GL_MODELVIEW); gluLookAt( center.x(), center.y(), center.z() + distance*depth, //eye center.x(), center.y(), center.z(), //center 0.0, 1.0, 0. ); /* up is in positive Y direction */ }
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; }
void KX_BulletPhysicsController::ApplyTorque(const MT_Vector3& torque,bool local) { CcdPhysicsController::ApplyTorque(torque.x(),torque.y(),torque.z(),local); }
MEM_SmartPtr<BSP_TMesh> BSP_PlyLoader:: NewMeshFromFile( char * file_name, MT_Vector3 &min, MT_Vector3 &max ) { min = MT_Vector3(MT_INFINITY,MT_INFINITY,MT_INFINITY); max = MT_Vector3(-MT_INFINITY,-MT_INFINITY,-MT_INFINITY); PlyProperty vert_props[] = { /* list of property information for a vertex */ {"x", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,x), 0, 0, 0, 0}, {"y", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,y), 0, 0, 0, 0}, {"z", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,z), 0, 0, 0, 0}, }; PlyProperty face_props[] = { /* list of property information for a vertex */ {"vertex_indices", PLY_INT, PLY_INT, offsetof(LoadFace,verts), 1, PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,nverts)}, }; MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh; if (mesh == NULL) return NULL; int i,j; PlyFile *ply; int nelems; char **elist; int file_type; float version; int nprops; int num_elems; PlyProperty **plist; char *elem_name; LoadVertex load_vertex; LoadFace load_face; /* open a PLY file for reading */ ply = ply_open_for_reading( file_name, &nelems, &elist, &file_type, &version ); if (ply == NULL) return NULL; /* go through each kind of element that we learned is in the file */ /* and read them */ for (i = 0; i < nelems; i++) { /* get the description of the first element */ elem_name = elist[i]; plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops); /* print the name of the element, for debugging */ /* if we're on vertex elements, read them in */ if (equal_strings ("vertex", elem_name)) { /* set up for getting vertex elements */ ply_get_property (ply, elem_name, &vert_props[0]); ply_get_property (ply, elem_name, &vert_props[1]); ply_get_property (ply, elem_name, &vert_props[2]); // make some memory for the vertices mesh->VertexSet().reserve(num_elems); /* grab all the vertex elements */ for (j = 0; j < num_elems; j++) { /* grab and element from the file */ ply_get_element (ply, (void *)&load_vertex); // pass the vertex into the mesh builder. if (load_vertex.x < min.x()) { min.x() = load_vertex.x; } else if (load_vertex.x > max.x()) { max.x()= load_vertex.x; } if (load_vertex.y < min.y()) { min.y() = load_vertex.y; } else if (load_vertex.y > max.y()) { max.y()= load_vertex.y; } if (load_vertex.z < min.z()) { min.z() = load_vertex.z; } else if (load_vertex.z > max.z()) { max.z()= load_vertex.z; } BSP_TVertex my_vert; my_vert.m_pos = MT_Vector3(load_vertex.x,load_vertex.y,load_vertex.z); mesh->VertexSet().push_back(my_vert); } } /* if we're on face elements, read them in */ if (equal_strings ("face", elem_name)) { /* set up for getting face elements */ ply_get_property (ply, elem_name, &face_props[0]); /* grab all the face elements */ for (j = 0; j < num_elems; j++) { ply_get_element (ply, (void *)&load_face); int v; for (v = 2; v< load_face.nverts; v++) { BSP_TFace f; f.m_verts[0] = load_face.verts[0]; f.m_verts[1] = load_face.verts[v-1]; f.m_verts[2] = load_face.verts[v]; mesh->BuildNormal(f); mesh->FaceSet().push_back(f); } // free up the memory this pile of shit used to allocate the polygon's vertices free (load_face.verts); } } } /* close the PLY file */ ply_close (ply); return mesh; }
bool KX_SoftBodyDeformer::Apply(RAS_IPolyMaterial *polymat, RAS_MeshMaterial *meshmat) { CcdPhysicsController *ctrl = (CcdPhysicsController *)m_gameobj->GetPhysicsController(); if (!ctrl) return false; btSoftBody *softBody = ctrl->GetSoftBody(); if (!softBody) return false; // update the vertex in m_transverts Update(); RAS_MeshSlot *slot = meshmat->m_slots[(void *)m_gameobj->getClientInfo()]; if (!slot) { return false; } RAS_IDisplayArray *array = slot->GetDisplayArray(); RAS_IDisplayArray *origarray = meshmat->m_baseslot->GetDisplayArray(); btSoftBody::tNodeArray& nodes(softBody->m_nodes); if (m_needUpdateAabb) { m_boundingBox->SetAabb(MT_Vector3(0.0f, 0.0f, 0.0f), MT_Vector3(0.0f, 0.0f, 0.0f)); m_needUpdateAabb = false; } // AABB Box : min/max. MT_Vector3 aabbMin; MT_Vector3 aabbMax; for (unsigned int i = 0, size = array->GetVertexCount(); i < size; ++i) { RAS_ITexVert *v = array->GetVertex(i); const RAS_TexVertInfo& vinfo = origarray->GetVertexInfo(i); /* The physics converter write the soft body index only in the original * vertex array because at this moment it doesn't know which is the * game object. It didn't cause any issues because it's always the same * vertex order. */ const unsigned int softbodyindex = vinfo.getSoftBodyIndex(); MT_Vector3 pt( nodes[softbodyindex].m_x.getX(), nodes[softbodyindex].m_x.getY(), nodes[softbodyindex].m_x.getZ()); v->SetXYZ(pt); MT_Vector3 normal( nodes[softbodyindex].m_n.getX(), nodes[softbodyindex].m_n.getY(), nodes[softbodyindex].m_n.getZ()); v->SetNormal(normal); if (!m_gameobj->GetAutoUpdateBounds()) { continue; } const MT_Vector3& scale = m_gameobj->NodeGetWorldScaling(); const MT_Vector3& invertscale = MT_Vector3(1.0f / scale.x(), 1.0f / scale.y(), 1.0f / scale.z()); const MT_Vector3& pos = m_gameobj->NodeGetWorldPosition(); const MT_Matrix3x3& rot = m_gameobj->NodeGetWorldOrientation(); // Extract object transform from the vertex position. pt = (pt - pos) * rot * invertscale; // if the AABB need an update. if (i == 0) { aabbMin = aabbMax = pt; } else { aabbMin.x() = std::min(aabbMin.x(), pt.x()); aabbMin.y() = std::min(aabbMin.y(), pt.y()); aabbMin.z() = std::min(aabbMin.z(), pt.z()); aabbMax.x() = std::max(aabbMax.x(), pt.x()); aabbMax.y() = std::max(aabbMax.y(), pt.y()); aabbMax.z() = std::max(aabbMax.z(), pt.z()); } } array->UpdateFrom(origarray, origarray->GetModifiedFlag() & (RAS_IDisplayArray::TANGENT_MODIFIED | RAS_IDisplayArray::UVS_MODIFIED | RAS_IDisplayArray::COLORS_MODIFIED)); m_boundingBox->ExtendAabb(aabbMin, aabbMax); return true; }