virtual bool castRay(const NxF32 *orig,const NxF32 *dir,NxF32 *dest,NxF32 *hitNormal) { bool ret = false; NxF32 p2[3]; const NxF32 RAY_DIST=50; dest[0] = p2[0] = orig[0]+ dir[0]*RAY_DIST; dest[1] = p2[1] = orig[1]+ dir[1]*RAY_DIST; dest[2] = p2[2] = orig[2]+ dir[2]*RAY_DIST; NxF32 nearest = 1e9; NxU32 near_face=0; for (NxU32 i=0; i<mTcount; i++) { NxU32 i1 = mIndices[i*3+0]; NxU32 i2 = mIndices[i*3+1]; NxU32 i3 = mIndices[i*3+2]; const NxF32 *t1 = &mVertices[i1*3]; const NxF32 *t2 = &mVertices[i2*3]; const NxF32 *t3 = &mVertices[i3*3]; NxF32 t; if ( fm_rayIntersectsTriangle(orig,dir,t1,t2,t3,t) ) { if ( t < nearest ) { dest[0] = orig[0]+dir[0]*t; dest[1] = orig[1]+dir[1]*t; dest[2] = orig[2]+dir[2]*t; ret = true; near_face = i; nearest = t; } } } if ( ret ) { // If the nearest face we hit was back-facing, then reject this cast! NxU32 i1 = mIndices[near_face*3+0]; NxU32 i2 = mIndices[near_face*3+1]; NxU32 i3 = mIndices[near_face*3+2]; const NxF32 *t1 = &mVertices[i1*3]; const NxF32 *t2 = &mVertices[i2*3]; const NxF32 *t3 = &mVertices[i3*3]; fm_computePlane(t3,t2,t1,hitNormal); } return ret; }
// warning, this code will not work on big endian processors. virtual bool importMesh(const char *_meshName,const void *_data,NxU32 dlen,MeshImportInterface *callback,const char *options,MeshImportApplicationResource *appResource) { bool ret = false; const char *meshName = _meshName; const char *slash = lastSlash(meshName); if ( slash ) { slash++; meshName = slash; } char scratch[2048]; strncpy(scratch,_meshName,2048); char *psk = stristr(scratch,".psk"); if ( psk ) { *psk = 0; strcat(scratch,".psa"); } callback->importAssetName(meshName,0); callback->importMesh(meshName,meshName); // have to make a local copy of the data because we are going to modify some of it. // Primarily just truncating some whitespace from bone names. void *data = MEMALLOC_MALLOC(dlen); memcpy(data,_data,dlen); if ( appResource ) { NxU32 len; void *mem = appResource->getApplicationResource(meshName,scratch,len); if ( mem ) { char *scan = ( char *)mem; Header *baseHeader = ( Header *)scan; scan+=sizeof(Header); Header *bonesHeader = ( Header *)scan; scan+=sizeof(Header); Bone *bones = ( Bone *)scan; assert(sizeof(Bone)==bonesHeader->mLen); scan+=(bonesHeader->mLen*bonesHeader->mCount); Header *animInfo = ( Header *)scan; scan+=sizeof(Header); assert( animInfo->mLen == sizeof(AnimInfo)); AnimInfo *ainfo = ( AnimInfo *)scan; scan+=(animInfo->mLen*animInfo->mCount); Header *animKeysHeader = ( Header *)scan; scan+=sizeof(Header); assert( animKeysHeader->mLen == sizeof(AnimKey) ); AnimKey *keys = ( AnimKey *)scan; scan+=(animKeysHeader->mLen*animKeysHeader->mCount); Header *scaleKeysHeader = ( Header *)scan; scan+=sizeof(Header); MeshAnimation ma; ma.mName = ainfo->mName; ma.mTrackCount = ainfo->mTotalBones; ma.mFrameCount = ainfo->mNumRawFrames; ma.mDtime = 1.0f / (NxF32)(ainfo->mAnimRate); ma.mDuration = ma.mDtime*ainfo->mNumRawFrames; ma.mTracks = (MeshAnimTrack **)MEMALLOC_MALLOC(sizeof(MeshAnimTrack *)*ma.mTrackCount); for (NxI32 i=0; i<ma.mTrackCount; i++) { Bone &b = bones[i]; fixName(b.mName); MeshAnimTrack *track = MEMALLOC_NEW(MeshAnimTrack); ma.mTracks[i] = track; track->mName = b.mName; track->mFrameCount = ma.mFrameCount; track->mDuration = ma.mDuration; track->mDtime = ma.mDtime; track->mPose = MEMALLOC_NEW(MeshAnimPose)[track->mFrameCount]; for (NxI32 j=0; j<ma.mFrameCount; j++) { NxU32 index = (j*ma.mTrackCount)+i; AnimKey &key = keys[index]; MeshAnimPose &p = track->mPose[j]; p.mPos[0] = key.mPosition[0]*IMPORT_SCALE; #if HACK_ANIMATION_POSITION p.mPos[1] = -key.mPosition[1]*IMPORT_SCALE; #else p.mPos[1] = key.mPosition[1]*IMPORT_SCALE; #endif p.mPos[2] = key.mPosition[2]*IMPORT_SCALE; p.mQuat[0] = key.mOrientation[0]; #if HACK_ANIMATION_ROTATION p.mQuat[1] = -key.mOrientation[1]; #else p.mQuat[1] = key.mOrientation[1]; #endif p.mQuat[2] = key.mOrientation[2]; p.mQuat[3] = key.mOrientation[3]; #if HACK_ANIMATION_ROOT if ( i == 0) { p.mQuat[3] = -p.mQuat[3]; } #endif index++; } } callback->importAnimation(ma); for (NxI32 i=0; i<ma.mTrackCount; i++) { MeshAnimTrack *track = ma.mTracks[i]; delete []track->mPose; delete track; } delete []ma.mTracks; appResource->releaseApplicationResource(mem); } } char *scan = ( char *)data; char *end = scan+dlen; Header *baseHeader = ( Header *)scan; scan+=sizeof(Header); // skip first dummy header Header *h = 0; Header *positionsHeader = h = (Header *)scan; assert( positionsHeader->mLen == sizeof(Vector)); scan+=sizeof(Header); Vector *positions = ( Vector *)scan; scan+=h->mLen*h->mCount; #if HACK_MESH_POSITION for (NxI32 i=0; i<positionsHeader->mCount; i++) { Vector &v = positions[i]; v.y*=-1; // flip the Y-coordinate } #endif Header *verticesHeader = h = ( Header *)scan; assert( verticesHeader->mLen == sizeof(Vertex)); scan+=sizeof(Header); Vertex *vertices = ( Vertex *)scan; scan+=h->mLen*h->mCount; Header *trianglesHeader = h = ( Header *)scan; assert( trianglesHeader->mLen == sizeof(Triangle)); scan+=sizeof(Header); Triangle *triangles = ( Triangle *)scan; scan+=h->mLen*h->mCount; Header *materialsHeader = h = ( Header *)scan; assert( materialsHeader->mLen == sizeof(Material)); scan+=sizeof(Header); Material *materials= ( Material *)scan; scan+=h->mLen*h->mCount; Header *bonesHeader = h = ( Header *)scan; assert( bonesHeader->mLen == sizeof(Bone)); scan+=sizeof(Header); Bone *bones= ( Bone *)scan; scan+=h->mLen*h->mCount; Header *boneInfluencesHeader = h = ( Header *)scan; assert( boneInfluencesHeader->mLen == sizeof(BoneInfluence)); scan+=sizeof(Header); BoneInfluence *boneInfluences = ( BoneInfluence *)scan; scan+=h->mLen*h->mCount; if ( bonesHeader->mCount > 0 ) { MeshSkeleton *ms = MEMALLOC_NEW(MeshSkeleton); ms->mName = meshName; ms->mBoneCount = bonesHeader->mCount; ms->mBones = MEMALLOC_NEW(MeshBone)[ms->mBoneCount]; for (NxI32 i=0; i<ms->mBoneCount; i++) { MeshBone &dest = ms->mBones[i]; Bone &src = bones[i]; fixName(src.mName); dest.mName = src.mName; dest.mParentIndex = (i==0) ? -1 : src.mParentIndex; dest.mPosition[0] = src.mPosition[0]*IMPORT_SCALE; #if HACK_SKELETON_POSITION dest.mPosition[1] = -src.mPosition[1]*IMPORT_SCALE; #else dest.mPosition[1] = src.mPosition[1]*IMPORT_SCALE; #endif dest.mPosition[2] = src.mPosition[2]*IMPORT_SCALE; dest.mOrientation[0] = src.mOrientation[0]; #if HACK_SKELETON_ROTATION dest.mOrientation[1] = -src.mOrientation[1]; #else dest.mOrientation[1] = src.mOrientation[1]; #endif dest.mOrientation[2] = src.mOrientation[2]; dest.mOrientation[3] = src.mOrientation[3]; #if HACK_SKELETON_ROOT if ( i == 0 ) { dest.mOrientation[3]*=-1; } #endif dest.mScale[0] = 1; //src.mXSize; dest.mScale[1] = 1; //src.mYSize; dest.mScale[2] = 1; //src.mZSize; } callback->importSkeleton(*ms); delete []ms->mBones; delete ms; } assert( scan == end ); DeformVector *dvertices = MEMALLOC_NEW(DeformVector)[positionsHeader->mCount]; for (NxI32 i=0; i<boneInfluencesHeader->mCount; i++) { BoneInfluence &b = boneInfluences[i]; DeformVector &d = dvertices[b.mVertexIndex]; if ( d.mCount < 4 ) { d.mWeight[d.mCount] = b.mWeight; d.mBone[d.mCount] = (NxU16)b.mBoneIndex; d.mCount++; } } Vector *normals = (Vector *)MEMALLOC_MALLOC( sizeof(Vector)*positionsHeader->mCount); memset(normals,0,sizeof(Vector)*positionsHeader->mCount); for (NxI32 i=0; i<trianglesHeader->mCount; i++) { Triangle &t = triangles[i]; MeshVertex mv1,mv2,mv3; Vertex &v1 = vertices[t.mWedgeIndex[0]]; Vertex &v2 = vertices[t.mWedgeIndex[1]]; Vertex &v3 = vertices[t.mWedgeIndex[2]]; Vector &p1 = positions[v1.mIndex]; Vector &p2 = positions[v2.mIndex]; Vector &p3 = positions[v3.mIndex]; Vector &n1 = normals[v1.mIndex]; Vector &n2 = normals[v2.mIndex]; Vector &n3 = normals[v3.mIndex]; Vector normal; fm_computePlane( &p1.x, &p3.x, &p2.x, &normal.x ); n1.x+=normal.x; n1.y+=normal.y; n1.z+=normal.z; n2.x+=normal.x; n2.y+=normal.y; n2.z+=normal.z; n3.x+=normal.x; n3.y+=normal.y; n3.z+=normal.z; } for (NxI32 i=0; i<positionsHeader->mCount; i++) { Vector &n = normals[i]; fm_normalize(&n.x); } for (NxI32 i=0; i<trianglesHeader->mCount; i++) { Triangle &t = triangles[i]; MeshVertex mv1,mv2,mv3; Vertex &v1 = vertices[t.mWedgeIndex[0]]; Vertex &v2 = vertices[t.mWedgeIndex[1]]; Vertex &v3 = vertices[t.mWedgeIndex[2]]; Vector &p1 = positions[v1.mIndex]; Vector &p2 = positions[v2.mIndex]; Vector &p3 = positions[v3.mIndex]; Vector &n1 = normals[v1.mIndex]; Vector &n2 = normals[v2.mIndex]; Vector &n3 = normals[v3.mIndex]; DeformVector &dv1 = dvertices[v1.mIndex]; DeformVector &dv2 = dvertices[v2.mIndex]; DeformVector &dv3 = dvertices[v3.mIndex]; getVertex(mv1,p1,v1,dv1,n1); getVertex(mv2,p2,v2,dv2,n2); getVertex(mv3,p3,v3,dv3,n3); const char *material = "default"; if ( t.mMaterialIndex >= 0 && t.mMaterialIndex < materialsHeader->mCount ) { material = materials[ t.mMaterialIndex ].mMaterialName; } #if HACK_MESH_WINDING callback->importTriangle(meshName,material, MIVF_ALL, mv1, mv3, mv2 ); #else callback->importTriangle(meshName,material, MIVF_ALL, mv1, mv2, mv3 ); #endif } delete []dvertices; MEMALLOC_FREE(data); return ret; }
NxF32 computeConcavityVolume(NxU32 vcount_hull, const NxF32 *vertices_hull, NxU32 tcount_hull, const NxU32 *indices_hull, NxU32 vcount_mesh, const NxF32 *vertices_mesh, NxU32 tcount_mesh, const NxU32 *indices_mesh) { NxF32 total_volume = 0; #if SHOW_DEBUG NVSHARE::gRenderDebug->pushRenderState(); NVSHARE::gRenderDebug->setCurrentDisplayTime(150.0f); #endif iRayCast *cast_hull = createRayCast(vertices_hull,tcount_hull,indices_hull); iRayCast *cast_mesh = createRayCast(vertices_mesh,tcount_mesh,indices_mesh); const NxU32 *indices = indices_mesh; #if 0 static NxU32 index = 0; NxU32 i = index++; indices = &indices[i*3]; #else for (NxU32 i=0; i<tcount_mesh; i++) #endif { NxU32 i1 = indices[0]; NxU32 i2 = indices[1]; NxU32 i3 = indices[2]; const NxF32 *p1 = &vertices_mesh[i1*3]; const NxF32 *p2 = &vertices_mesh[i2*3]; const NxF32 *p3 = &vertices_mesh[i3*3]; NxF32 normal[3]; NxF32 d = fm_computePlane(p3,p2,p1,normal); NxF32 vertices[6*3]; vertices[0] = p1[0]; vertices[1] = p1[1]; vertices[2] = p1[2]; vertices[3] = p2[0]; vertices[4] = p2[1]; vertices[5] = p2[2]; vertices[6] = p3[0]; vertices[7] = p3[1]; vertices[8] = p3[2]; NxF32 midPoint[3]; midPoint[0] = (p1[0]+p2[0]+p3[0])/3; midPoint[1] = (p1[1]+p2[1]+p3[1])/3; midPoint[2] = (p1[2]+p2[2]+p3[2])/3; fm_lerp(midPoint,p1,&vertices[0],0.9999f); fm_lerp(midPoint,p2,&vertices[3],0.9999f); fm_lerp(midPoint,p3,&vertices[6],0.9999f); NxF32 *_p1 = &vertices[3*3]; NxF32 *_p2 = &vertices[4*3]; NxF32 *_p3 = &vertices[5*3]; NxU32 hitCount = 0; if ( raycast(&vertices[0],normal, _p1,cast_hull,cast_mesh) ) hitCount++; if ( raycast(&vertices[3],normal, _p2,cast_hull,cast_mesh) ) hitCount++; if ( raycast(&vertices[6],normal, _p3,cast_hull,cast_mesh) ) hitCount++; // form triangle mesh! if ( hitCount == 3 ) { NxU32 tcount = 0; NxU32 tindices[8*3]; addTri(tindices,2,1,0,tcount); addTri(tindices,3,4,5,tcount); addTri(tindices,0,3,2,tcount); addTri(tindices,2,3,5,tcount); addTri(tindices,1,3,0,tcount); addTri(tindices,4,3,1,tcount); addTri(tindices,5,4,1,tcount); addTri(tindices,2,5,1,tcount); NxF32 volume = fm_computeMeshVolume(vertices,tcount,tindices); total_volume+=volume; #if SHOW_DEBUG NVSHARE::gRenderDebug->setCurrentColor(0x0000FF,0xFFFFFF); NVSHARE::gRenderDebug->addToCurrentState(NVSHARE::DebugRenderState::SolidWireShaded); for (NxU32 i=0; i<tcount; i++) { NxU32 i1 = tindices[i*3+0]; NxU32 i2 = tindices[i*3+1]; NxU32 i3 = tindices[i*3+2]; const NxF32 *p1 = &vertices[i1*3]; const NxF32 *p2 = &vertices[i2*3]; const NxF32 *p3 = &vertices[i3*3]; NVSHARE::gRenderDebug->DebugTri(p1,p2,p3); } #endif } indices+=3; } #if SHOW_DEBUG NVSHARE::gRenderDebug->popRenderState(); #endif releaseRayCast(cast_hull); releaseRayCast(cast_mesh); return total_volume; }