void Polyhedron<Real>::transform(const matrix4<Real>& matrix) { for (uint i = 0; i < planes.size(); ++i) planes[i] = matrix.transformPlane(planes[i]); for (uint i = 0; i < vertices.size(); ++i) vertices[i] = matrix.transformVertex(vertices[i]); }
static bool transformPlane(const vector3df & point, const vector3df & normal, const matrix4 & matrix, const plane3df & expected) { plane3df plane(point, vector3df(normal).normalize()); logTestString("\n Pre: (%.3ff,%.3ff,%.3ff), %.3ff\n", plane.Normal.X, plane.Normal.Y, plane.Normal.Z, plane.D); matrix.transformPlane(plane); logTestString(" Post: (%.3ff,%.3ff,%.3ff), %.3ff\n", plane.Normal.X, plane.Normal.Y, plane.Normal.Z, plane.D); logTestString("Expected: (%.3ff,%.3ff,%.3ff), %.3ff\n", expected.Normal.X, expected.Normal.Y, expected.Normal.Z, expected.D); if(!sloppyComparePlanes(plane, expected)) { logTestString("Unexpected result\n"); assert_log(false); return false; } return true; }
void matrix4::ToInverse( const matrix4& in ) { // first transpose the rotation matrix _11 = in._11; _12 = in._21; _13 = in._31; _21 = in._12; _22 = in._22; _23 = in._32; _31 = in._13; _32 = in._23; _33 = in._33; // fix right column _14 = 0; _24 = 0; _34 = 0; _44 = 1; // now get the new translation vector point3 temp = in.GetLoc(); _41 = -(temp.x * in._11 + temp.y * in._12 + temp.z * in._13); _42 = -(temp.x * in._21 + temp.y * in._22 + temp.z * in._23); _43 = -(temp.x * in._31 + temp.y * in._32 + temp.z * in._33); }
void matrix4::multiply(matrix4 m) { matrix4 product; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { product.set_at(i, j, matrix[i][0] * m.get_at(0, j) + matrix[i][1] * m.get_at(1, j) + matrix[i][2] * m.get_at(2, j) + matrix[i][3] * m.get_at(3, j)); } } float* data = product.get_data(); for (int i_2 = 0; i_2 < 4; i_2++) { for (int j_2 = 0; j_2 < 4; j_2++) { int index = putils::get_index_2d(i_2, j_2, 4); matrix[i_2][j_2] = data[index]; } } delete data; }
/********************************************************************************* * Draw 'beethovan' object. **********************************************************************************/ void drawBet() { glPushMatrix(); glMultMatrixd(bet2wld.GLmatrix()); drawFrame(8); float frontColor[] = {0.8, 0.3, 0.1, 1.0}; glEnable(GL_LIGHTING); glMaterialfv(GL_FRONT, GL_AMBIENT, frontColor); glMaterialfv(GL_FRONT, GL_DIFFUSE, frontColor); glCallList(betID); glPopMatrix(); }
Plane makePlane(vector3 const& a, vector3 const& b, vector3 const& n) { vector3 v=a; for(int i=0; i<3; i++) { if(n[i]==1.0) v[i]=b[i]; else if(n[i]==-1.0) v[i]=a[i]; else assert(n[i]==0.0); } //std::cout<<n<<v<<std::endl; return Plane(cow2wld.rotate(n),cow2wld*v); }
void quater::setRotation(const matrix4& m) { #ifdef USE_D3DFUNC D3DXMATRIX dxmat; m.toDXmat(dxmat); D3DXQuaternionRotationMatrix(*this,&dxmat); #else // jehee lee implementation quater &q=*this; double tr, s; int i, j, k; static int next[3] = { 1, 2, 0 }; tr = m.m[0][0] + m.m[1][1] + m.m[2][2]; if ( tr > 0.0 ) { s = sqrt( tr + 1.0 ); q[0] = ( s * 0.5 ); s = 0.5 / s; q.x = ( m.m[2][1] - m.m[1][2] ) * s; q.y = ( m.m[0][2] - m.m[2][0] ) * s; q.z = ( m.m[1][0] - m.m[0][1] ) * s; } else { i = 0; if ( m.m[1][1] > m.m[0][0] ) i = 1; if ( m.m[2][2] > m.m[i][i] ) i = 2; j = next[i]; k = next[j]; s = sqrt( (m.m[i][i] - (m.m[j][j] + m.m[k][k])) + 1.0 ); q[i+1] = s * 0.5; s = 0.5 / s; q.w = ( m.m[k][j] - m.m[j][k] ) * s; q[j+1] = ( m.m[j][i] + m.m[i][j] ) * s; q[k+1] = ( m.m[k][i] + m.m[i][k] ) * s; } #endif }
void setTransform(const matrix4<Type>& m) { m_matrix = m; m_invertedMatrix = m.inverse(); }
void onMouseDrag( GLFWwindow* window, double fx, double fy) { int x=fx; int y=fy; #else void onMouseDrag( int x, int y) { #endif if (isDrag) { printf( "in drag mode %d\n", isDrag); if (isDrag==V_DRAG && cowFlag) { // vertical dragging // TODO: // create a dragging plane perpendicular to the ray direction, // and test intersection with the screen ray. // When dragged just change Y position Ray ray; screenCoordToRay(clickX, y, ray); PickInfo &pp=pickInfo; std::pair<bool, double> c=ray.intersects(dragPlane); vector3 currentPos=ray.getPoint(c.second); matrix4 T; T.setTranslation(currentPos - pp.cowPickPosition, false); cow2wld.mult(T, pp.cowPickConfiguration); } else { // horizontal dragging // Hint: read carefully the following block to implement vertical dragging. if(cursorOnCowBoundingBox) { Ray ray; screenCoordToRay(x, y, ray); PickInfo &pp=pickInfo; Plane p(vector3(0,1,0), pp.cowPickPosition); std::pair<bool, double> c=ray.intersects(p); vector3 currentPos=ray.getPoint(c.second); matrix4 T; T.setTranslation(currentPos-pp.cowPickPosition, false); cow2wld.mult(T, pp.cowPickConfiguration); } } } else { Ray ray; screenCoordToRay(x, y, ray); std::vector<Plane> planes; vector3 bbmin(cow->bbmin.x, cow->bbmin.y, cow->bbmin.z); vector3 bbmax(cow->bbmax.x, cow->bbmax.y, cow->bbmax.z); planes.push_back(makePlane(bbmin, bbmax, vector3(0,1,0))); planes.push_back(makePlane(bbmin, bbmax, vector3(0,-1,0))); planes.push_back(makePlane(bbmin, bbmax, vector3(1,0,0))); planes.push_back(makePlane(bbmin, bbmax, vector3(-1,0,0))); planes.push_back(makePlane(bbmin, bbmax, vector3(0,0,1))); planes.push_back(makePlane(bbmin, bbmax, vector3(0,0,-1))); std::pair<bool,double> o=ray.intersects(planes); cursorOnCowBoundingBox=o.first; PickInfo &pp=pickInfo; pp.cursorRayT=o.second; pp.cowPickPosition=ray.getPoint(pp.cursorRayT); pp.cowPickConfiguration=cow2wld; matrix4 invWorld; invWorld.inverse(cow2wld); // the local position (relative to the cow frame) of the pick position. pp.cowPickPositionLocal=invWorld*pp.cowPickPosition; } } /********************************************************************************* * Call this part whenever user types keyboard. **********************************************************************************/ #if GLFW_VERSION_MAJOR==3 void onKeyPress(GLFWwindow *__win, int key, int __scancode, int action, int __mods) #else void onKeyPress( int key, int action) #endif { if (action==GLFW_RELEASE) return ; // do nothing // If 'c' or space bar are pressed, alter the camera. // If a number is pressed, alter the camera corresponding the number. if ((key == ' ') || (key == 'c')) { printf( "Toggle camera %d\n", cameraIndex ); cameraIndex += 1; } else if ((key >= '0') && (key <= '9')) cameraIndex = key - '0'; if (cameraIndex >= (int)wld2cam.size() ) cameraIndex = 0; } void screenCoordToRay(int x, int y, Ray& ray) { int height , width; #if GLFW_VERSION_MAJOR==3 glfwGetWindowSize(g_window, &width, &height); #else glfwGetWindowSize(&width, &height); #endif matrix4 matProjection; matProjection.getCurrentOpenGLmatrix(GL_PROJECTION_MATRIX); matProjection*=wld2cam[cameraIndex]; matrix4 invMatProjection; invMatProjection.inverse(matProjection); vector3 vecAfterProjection, vecAfterProjection2; // -1<=v.x<1 when 0<=x<width // -1<=v.y<1 when 0<=y<height vecAfterProjection.x = ((double)(x - 0)/(double)width)*2.0-1.0; vecAfterProjection.y = ((double)(y - 0)/(double)height)*2.0-1.0; vecAfterProjection.y*=-1; vecAfterProjection.z = -10; //std::cout<<"cowPosition in clip coordinate (NDC)"<<matProjection*cow2wld.getTranslation()<<std::endl; vector3 vecBeforeProjection=invMatProjection*vecAfterProjection; // camera position ray.origin()=cam2wld[cameraIndex].getTranslation(); ray.direction()=vecBeforeProjection-ray.origin(); ray.direction().normalize(); //std::cout<<"dir" <<ray.direction()<<std::endl; }
//------------------------------------------------------------------------------ void initialize() { cursorOnCowBoundingBox=false; // Set up OpenGL state glShadeModel(GL_SMOOTH); // Set Smooth Shading glEnable(GL_DEPTH_TEST); // Enables Depth Testing glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do // Use perspective correct interpolation if available glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Initialize the matrix stacks reshape(width, height); // Define lighting for the scene float lightDirection[] = {1.0, 1.0, 1.0, 0}; float ambientIntensity[] = {0.1, 0.1, 0.1, 1.0}; float lightIntensity[] = {0.9, 0.9, 0.9, 1.0}; glLightfv(GL_LIGHT0, GL_AMBIENT, ambientIntensity); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightIntensity); glLightfv(GL_LIGHT0, GL_POSITION, lightDirection); glEnable(GL_LIGHT0); // initialize floor { // After making checker-patterned texture, use this repetitively. // Insert color into checker[] according to checker pattern. const int size = 8; unsigned char checker[size*size*3]; for( int i=0; i < size*size; i++ ) { if (((i/size) ^ i) & 1) { checker[3*i+0] = 200; checker[3*i+1] = 32; checker[3*i+2] = 32; } else { checker[3*i+0] = 200; checker[3*i+1] = 200; checker[3*i+2] = 32; } } // Make texture which is accessible through floorTexID. glGenTextures( 1, &floorTexID ); glBindTexture(GL_TEXTURE_2D, floorTexID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexImage2D(GL_TEXTURE_2D, 0, 3, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, checker); } // initialize cow { // Read information from cow.obj. cow = new WaveFrontOBJ( "cow.obj" ); // Make display list. After this, you can draw cow using 'cowID'. cowID = glGenLists(1); // Create display lists glNewList(cowID, GL_COMPILE); // Begin compiling the display list using cowID cow->Draw(); // Draw the cow on display list. glEndList(); // Terminate compiling the display list. Now, you can draw cow using 'cowID'. glPushMatrix(); // Push the current matrix of GL into stack. glLoadIdentity(); // Set the GL matrix Identity matrix. glTranslated(0,-cow->bbmin.y,-8); // Set the location of cow. glRotated(-90, 0, 1, 0); // Set the direction of cow. These information are stored in the matrix of GL. // Read the modelview matrix about location and direction set above, and store it in cow2wld matrix. cow2wld.getCurrentOpenGLmatrix( GL_MODELVIEW_MATRIX); glPopMatrix(); // Pop the matrix on stack to GL. } // initialize bethoben { // Read information from beethovan.obj. bet = new WaveFrontOBJ( "beethovan.obj" ); // Make display list. After this, you can draw beethovan using 'betID'. betID = glGenLists(1); glNewList(betID, GL_COMPILE); bet->Draw(); glEndList(); glPushMatrix(); glLoadIdentity(); glTranslated(0,-bet->bbmin.y,8); glRotated(180, 0, 1, 0); // bet2wld will become T * R bet2wld.getCurrentOpenGLmatrix(GL_MODELVIEW_MATRIX); glPopMatrix(); } // intialize camera model. { cam = new WaveFrontOBJ("camera.obj"); // Read information of camera from camera.obj. camID = glGenLists(1); // Create display list of the camera. glNewList(camID, GL_COMPILE); // Begin compiling the display list using camID. cam->Draw(); // Draw the camera. you can do this job again through camID.. glEndList(); // Terminate compiling the display list. // initialize camera frame transforms. for (int i=0; i < cameraCount; i++ ) { double* c = cameras[i]; // 'c' points the coordinate of i-th camera. wld2cam.push_back(matrix4()); // Insert {0} matrix to wld2cam vector. glPushMatrix(); // Push the current matrix of GL into stack. glLoadIdentity(); // Set the GL matrix Identity matrix. gluLookAt(c[0],c[1],c[2], c[3],c[4],c[5], c[6],c[7],c[8]); // Setting the coordinate of camera. wld2cam[i].getCurrentOpenGLmatrix(GL_MODELVIEW_MATRIX); glPopMatrix(); // Transfer the matrix that was pushed the stack to GL. matrix4 invmat; invmat.inverse(wld2cam[i]); cam2wld.push_back(invmat); } cameraIndex = 0; } }
/********************************************************************************* * Draw 'cow' object. **********************************************************************************/ void drawCow(matrix4 const& _cow2wld, bool drawBB) { glPushMatrix(); // Push the current matrix of GL into stack. This is because the matrix of GL will be change while drawing cow. // The information about location of cow to be drawn is stored in cow2wld matrix. // (Project2 hint) If you change the value of the cow2wld matrix or the current matrix, cow would rotate or move. glMultMatrixd(_cow2wld.GLmatrix()); drawFrame(5); // Draw x, y, and z axis. float frontColor[] = {0.8, 0.2, 0.9, 1.0}; glEnable(GL_LIGHTING); glMaterialfv(GL_FRONT, GL_AMBIENT, frontColor); // Set ambient property frontColor. glMaterialfv(GL_FRONT, GL_DIFFUSE, frontColor); // Set diffuse property frontColor. glCallList(cowID); // Draw cow. glDisable(GL_LIGHTING); if(drawBB){ glBegin(GL_LINES); glColor3d(1,1,1); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmax.z); glColor3d(1,1,1); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmax.z); glColor3d(1,1,1); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmax.z); glColor3d(1,1,1); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmax.z); glColor3d(1,1,1); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmin.y, cow->bbmax.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmin.x, cow->bbmax.y, cow->bbmax.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmin.z); glVertex3d( cow->bbmax.x, cow->bbmax.y, cow->bbmax.z); glEnd(); } glPopMatrix(); // Pop the matrix in stack to GL. Change it the matrix before drawing cow. }
void Water::_drawQuad() { #if 0 static float radius = 0.5f; static float strength = 1.0f; glViewport(0,0,m_frameBufferA->GetWidth(),m_frameBufferA->GetHeight()); m_frameBufferA->Begin(); m_shader_drop->bind(); kmVec2 vec2; vec2.x = 0.5f; vec2.y = 0.5f; m_shader_drop->uniform(RTHASH("center"), vec2); m_shader_drop->uniform(RTHASH("radius"), radius); m_shader_drop->uniform(RTHASH("strength"), strength); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,m_frameBufferB->GetColorTexture()); glBindTexture(GL_TEXTURE_2D,m_textureObject); _renderMesh(m_screenRect,m_shader_drop); m_shader_drop->unbind(); m_frameBufferA->End(); #endif #if 0 glViewport(0,0,m_screenWidth,m_screenHeight); m_quadShader->bind(); glActiveTexture(GL_TEXTURE0); //glBindTexture(GL_TEXTURE_2D, m_frameBufferB->GetColorTexture()); glBindTexture(GL_TEXTURE_2D, m_textureObject); m_quadShader->uniform(RTHASH("s_texture"), 0); _renderMesh(m_screenRect,m_quadShader); m_quadShader->unbind(); glGetError(); // #else //vector4df transformedVertexs[3]; //vector4df originalVertex[] = //{ // vector4df(0.0f, 0.0f, 0.5f, 1.0f), // vector4df(1.0f, 0.0f, 0.5f, 1.0f), // vector4df(0.0f, 0.0f, -1.0f, 1.0f) //}; //for (int i=0; i<3; ++i) //{ // g_viewProjectMatrix.transformVect(transformedVertexs[i],originalVertex[i]); //} matrix4 transposedMatrix = g_viewProjectMatrix.getTransposed(); vector2df screenSize((float)m_screenWidth, (float)m_screenHeight); //vector2df screenSize(10.0f, 10.0f); // static const float inverseWidth = 1.0f/m_fbWrite->GetWidth(); static const float inverseHeight = 1.0f/m_fbWrite->GetHeight(); // glViewport(0, 0, m_screenWidth, m_screenHeight); m_shader_water->bind(); glActiveTexture(GL_TEXTURE0); #if 1 glBindTexture(GL_TEXTURE_2D, m_fbRead->GetColorTexture()); #else glBindTexture(GL_TEXTURE_2D, m_frameBufferCaustic->GetColorTexture()); #endif m_shader_water->uniform(RTHASH("water"),0); #if 0 glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, m_textureObject); m_shader_water->uniform(RTHASH("base"),1); #endif m_shader_water->uniform(RTHASH("screenSize"), screenSize); #if 1 m_shader_water->uniform(RTHASH("WVPMatrix"), g_viewProjectMatrixOrc); #else m_shader_water->uniform(RTHASH("WVPMatrix"), g_viewProjectMatrix); #endif vector2df delta(inverseWidth, inverseHeight); m_shader_water->uniform(RTHASH("delta"), delta); _renderMesh(m_screenRect,m_shader_water); m_shader_water->unbind(); glGetError(); #endif }
//----------------------------------------------------------------------- // T M e s h S h a p e //----------------------------------------------------------------------- TMeshShape::TMeshShape(IMesh* mesh, const matrix4& transform, bool isConvex) : TCollisionShape(), m_baseCount(0), m_hullCount(0) { TApplication* app = getApplication(); app->logMessage(LOG_INFO, "TMeshShape isConvex: %d", isConvex); u32 vcount=0, tcount=0; for(u32 i=0; i<mesh->getMeshBufferCount(); i++) { tcount += mesh->getMeshBuffer(i)->getIndexCount() / 3; vcount += mesh->getMeshBuffer(i)->getVertexCount(); } app->logMessage(LOG_INFO, " org vert count: %d", vcount); app->logMessage(LOG_INFO, " org tri count: %d", tcount); btQuaternion q(TMath::HALF_PI,0.f,0.f); m_localTransform = transform; m_localScale = transform.getScale(); m_triMesh = extractTriangles(mesh, true); app->logMessage(LOG_INFO, " ext tri count: %d", m_triMesh->getNumTriangles()); if(isConvex) { if(1) { // using Bullet's btShapeHull class - faster, typically produces less verts/tris btConvexShape* tmpConvexShape = new btConvexTriangleMeshShape(m_triMesh); m_shape = tmpConvexShape; btShapeHull* hull = new btShapeHull(tmpConvexShape); btScalar margin = tmpConvexShape->getMargin(); hull->buildHull(margin); tmpConvexShape->setUserPointer(hull); app->logMessage(LOG_INFO, " hull vert count: %d", hull->numVertices()); app->logMessage(LOG_INFO, " hull tri count: %d", hull->numTriangles()); //btConvexHullShape* chShape = new btConvexHullShape((const btScalar *)hull->getVertexPointer(),hull->numVertices()); btConvexHullShape* chShape = new btConvexHullShape(); const btVector3* vp = hull->getVertexPointer(); const unsigned int* ip = hull->getIndexPointer(); for (int i=0;i<hull->numTriangles();i++) { chShape->addPoint(vp[ip[i*3]]); chShape->addPoint(vp[ip[i*3+1]]); chShape->addPoint(vp[ip[i*3+2]]); } m_shape = chShape; delete hull; delete tmpConvexShape; } else { // using Bullet's hull library directly HullResult result; HullLibrary hl; HullDesc desc; desc.mMaxFaces = 256; desc.mMaxVertices = 256; desc.SetHullFlag(QF_TRIANGLES); PHY_ScalarType type, indicestype; const unsigned char* indexbase; int istride,numfaces; m_triMesh->getLockedReadOnlyVertexIndexBase((const unsigned char**)&desc.mVertices, (int&)desc.mVcount, type, (int&)desc.mVertexStride, &indexbase, istride, numfaces, indicestype); HullError ret = hl.CreateConvexHull(desc,result); if(ret == QE_OK) { app->logMessage(LOG_INFO, " hull vert count: %d", result.mNumOutputVertices); app->logMessage(LOG_INFO, " hull tri count: %d", result.mNumFaces); btConvexHullShape* chShape = new btConvexHullShape(); for (unsigned int i=0;i<result.mNumFaces;i++) { chShape->addPoint(result.m_OutputVertices[result.m_Indices[i*3]]); chShape->addPoint(result.m_OutputVertices[result.m_Indices[i*3+1]]); chShape->addPoint(result.m_OutputVertices[result.m_Indices[i*3+2]]); } m_shape = chShape; } else { m_shape = new btBvhTriangleMeshShape(m_triMesh,true,true); } hl.ReleaseResult(result); } } else { //m_shape = _decomposeTriMesh(); m_shape = new btBvhTriangleMeshShape(m_triMesh,true,true); } btVector3 scale(m_localScale.X, m_localScale.Y, m_localScale.Z); m_shape->setLocalScaling(scale); }