ObjectDB *getObjectDB( LWItemID id, GlobalFunc *global ) { LWObjectInfo *objinfo; LWMeshInfo *mesh; LWPntID ptid; ObjectDB *odb; const char *name; int npts, npols, nverts, i, j, k, ok = 0; /* get the object info global */ objinfo = global( LWOBJECTINFO_GLOBAL, GFUSE_TRANSIENT ); if ( !objinfo ) return NULL; /* get the mesh info for the object */ mesh = objinfo->meshInfo( id, 1 ); if ( !mesh ) return NULL; /* alloc the object database */ odb = calloc( 1, sizeof( ObjectDB )); if ( !odb ) goto Finish; odb->id = id; name = objinfo->filename( id ); odb->filename = malloc( strlen( name ) + 1 ); if ( !odb->filename ) goto Finish; strcpy( odb->filename, name ); /* alloc and init the points array */ npts = mesh->numPoints( mesh ); odb->pt = calloc( npts, sizeof( DBPoint )); if ( !odb->pt ) goto Finish; if ( mesh->scanPoints( mesh, pntScan, odb )) goto Finish; /* alloc and init the polygons array */ npols = mesh->numPolygons( mesh ); odb->pol = calloc( npols, sizeof( DBPolygon )); if ( !odb->pol ) goto Finish; if ( mesh->scanPolys( mesh, polScan, odb )) goto Finish; /* get the vertices of each polygon */ for ( i = 0; i < npols; i++ ) { nverts = mesh->polSize( mesh, odb->pol[ i ].id ); odb->pol[ i ].v = calloc( nverts, sizeof( DBPolVert )); if ( !odb->pol[ i ].v ) goto Finish; odb->pol[ i ].nverts = nverts; for ( j = 0; j < nverts; j++ ) { ptid = mesh->polVertex( mesh, odb->pol[ i ].id, j ); odb->pol[ i ].v[ j ].index = findVert( odb, ptid ); } } /* count the number of polygons per point */ for ( i = 0; i < npols; i++ ) for ( j = 0; j < odb->pol[ i ].nverts; j++ ) ++odb->pt[ odb->pol[ i ].v[ j ].index ].npols; /* alloc per-point polygon arrays */ for ( i = 0; i < npts; i++ ) { if ( odb->pt[ i ].npols == 0 ) continue; odb->pt[ i ].pol = calloc( odb->pt[ i ].npols, sizeof( int )); if ( !odb->pt[ i ].pol ) goto Finish; odb->pt[ i ].npols = 0; } /* fill in polygon array for each point */ for ( i = 0; i < npols; i++ ) { for ( j = 0; j < odb->pol[ i ].nverts; j++ ) { k = odb->pol[ i ].v[ j ].index; odb->pt[ k ].pol[ odb->pt[ k ].npols ] = i; ++odb->pt[ k ].npols; } } /* get the position of each point */ for ( i = 0; i < npts; i++ ) { mesh->pntBasePos( mesh, odb->pt[ i ].id, odb->pt[ i ].pos[ 0 ] ); mesh->pntOtherPos( mesh, odb->pt[ i ].id, odb->pt[ i ].pos[ 1 ] ); } /* init the point search array */ /* Ordinarily, you won't need this because you can look up points by their IDs. Uncomment this if you do need to search by point position instead. The second argument is 0 for base position and 1 for final position. if ( !initPointSearch( odb, 0 )) goto Finish; */ /* calculate the normal of each polygon */ getPolyNormals( odb, 0 ); getPolyNormals( odb, 1 ); /* get the vmaps */ if ( !getObjectVMaps( odb, mesh, global )) goto Finish; /* get the surfaces */ if ( !getObjectSurfs( odb, mesh, global )) goto Finish; /* calculate vertex normals */ getVertNormals( odb, 0 ); getVertNormals( odb, 1 ); /* done */ ok = 1; Finish: if ( mesh->destroy ) mesh->destroy( mesh ); if ( !ok ) { freeObjectDB( odb ); return NULL; } return odb; }
bool LWObject::collectWeights(const std::vector<LWBone> &bones) { LWObjectInfo *objectInfo = Manager::getSingleton()->getObjectInfo(); if(objectInfo == 0) return false; LWMeshInfo *meshInfo = objectInfo->meshInfo(lwId, TRUE); if(meshInfo == 0) return false; bool hasWeights = false; // Each bone has it's own weightmap for(unsigned int i = 0; i < bones.size(); ++i) { const std::string &weightMap = bones[i].getWeightName(); // Select vertex map to read void *map = 0; if((map = meshInfo->pntVLookup(meshInfo, LWVMAP_WGHT, weightMap.c_str())) == 0) continue; if(meshInfo->pntVSelect(meshInfo, map) != 1) { Manager::getSingleton()->getExporter()->printWarning(name + ": weightmap has more than 1 dimension"); continue; } // Try for each vertex for(unsigned int j = 0; j < vertices.size(); ++j) { float weight = 0.f; if(meshInfo->pntVGet(meshInfo, vertices[j].id, &weight)) { // 0-weight is valid //if(fabs(weight) < .001f) // continue; // Set if greater than what's already in for(int k = 0; k < LWVertex::MAX_WEIGHTS; ++k) { if(vertices[j].boneIndices[k] == -1 || fabs(vertices[j].boneWeights[k]) < fabsf(weight)) { // Store old value forward if(k + 1 < LWVertex::MAX_WEIGHTS) { vertices[j].boneIndices[k + 1] = vertices[j].boneIndices[k]; vertices[j].boneWeights[k + 1] = vertices[j].boneWeights[k]; } vertices[j].boneIndices[k] = i; vertices[j].boneWeights[k] = weight; break; } } /* // Set if has no weight bool set = false; for(int k = 0; k < LWVertex::MAX_WEIGHTS; ++k) { if(vertices[j].boneIndices[k] == -1) { vertices[j].boneIndices[k] = i; vertices[j].boneWeights[k] = weight; set = true; hasWeights = true; break; } } if(set == true) continue; // Set if greater than what's already in for(k = LWVertex::MAX_WEIGHTS - 1; k >= 0; --k) { if(fabs(vertices[j].boneWeights[k]) < fabsf(weight)) { // Store old value forward if(k + 1 < LWVertex::MAX_WEIGHTS) { vertices[j].boneIndices[k + 1] = vertices[j].boneIndices[k]; vertices[j].boneWeights[k + 1] = vertices[j].boneWeights[k]; } vertices[j].boneIndices[k] = i; vertices[j].boneWeights[k] = weight; break; } } */ } } } if(meshInfo->destroy) meshInfo->destroy(meshInfo); return hasWeights; }
void LWObject::collectTextureCoordinates(const std::vector<LWMaterial> &materials, const FBMatrix &transform) { // This part is a bit messy. // Can't help it since LW's gotta do what LW's gotta do etc. LWTextureFuncs *textureFunctions = Manager::getSingleton()->getTextureFunctions(); LWObjectInfo *objectInfo = Manager::getSingleton()->getObjectInfo(); if((textureFunctions == 0) || (objectInfo == 0)) return; LWMeshInfo *meshInfo = objectInfo->meshInfo(lwId, TRUE); if(meshInfo == 0) return; // Get them per face (looks ugly otherwise) for(unsigned int i = 0; i < faces.size(); ++i) { // If no material, no texture if(faces[i].materialId == -1) continue; // Each face have different material LWTextureID textureId = materials[faces[i].materialId].getTextureId(); if(textureId == 0) continue; LWTLayerID layerId = textureFunctions->firstLayer(textureId); if(layerId == 0) continue; int projection = 0; textureFunctions->getParam(layerId, TXTAG_PROJ, &projection); for(int j = 0; j < 3; ++j) { if(projection == TXPRJ_UVMAP) // UV-map { void *map = NULL; textureFunctions->getParam(layerId, TXTAG_VMAP, &map); if(map == 0) continue; if(meshInfo->pntVSelect(meshInfo, map) != 2) { Manager::getSingleton()->getExporter()->printWarning(name + ": UV-map isn't 2-dimensional. Discarding."); continue; } float uv[2] = { 0 }; LWPntID vertexId = vertices[faces[i].indices[j]].id; // Finally query texture coordinates if(meshInfo->pntVPGet(meshInfo, vertexId, faces[i].id, uv)) { faces[i].uvs[j].x = uv[0]; faces[i].uvs[j].y = -uv[1]; faces[i].hasUvs[j] = true; } else if(meshInfo->pntVGet(meshInfo, vertexId, uv)) { faces[i].uvs[j].x = uv[0]; faces[i].uvs[j].y = -uv[1]; faces[i].hasUvs[j] = true; } } else // Projected mapping { // Normals largest absolute value defines dominant axis (in world and object space) FBVector worldNormal = faces[i].normal; transform.RotateVector(worldNormal); int wAxis = getDominantAxis(worldNormal); //int wAxis = getDominantAxis(transform.GetTransformedVector(faces[i].normal)); int oAxis = getDominantAxis(faces[i].normal); // Position in world and object space FBVector &vO = vertices[faces[i].indices[j]].position; FBVector vW = transform.GetTransformedVector(vO); double oPosition[3] = { vO.x, vO.y, vO.z }; double wPosition[3] = { vW.x, vW.y, vW.z }; double uv[2] = { 0 }; textureFunctions->evaluateUV(layerId, wAxis, oAxis, oPosition, wPosition, uv); faces[i].uvs[j].x = static_cast<double> (uv[0]); faces[i].uvs[j].y = static_cast<double> (-uv[1]); faces[i].hasUvs[j] = true; } //faces[i].uvs2[j] = faces[i].uvs[j]; } } // In the name of holy spaghetti. Should clean this up a bit for(unsigned int i = 0; i < faces.size(); ++i) { // If no material, no texture if(faces[i].materialId == -1) continue; // Each face have different material LWTextureID textureId = materials[faces[i].materialId].getLightmapId(); if(textureId == 0) continue; /* int a = 0; if(materials[faces[i].materialId].getName() == "Lattia") a = 1; */ LWTLayerID layerId = textureFunctions->firstLayer(textureId); if(layerId == 0) { //materials[faces[i].materialId].removeLightmap(); continue; } int projection = 0; textureFunctions->getParam(layerId, TXTAG_PROJ, &projection); for(int j = 0; j < 3; ++j) { if(projection == TXPRJ_UVMAP) // UV-map { void *map = 0; textureFunctions->getParam(layerId, TXTAG_VMAP, &map); if(meshInfo->pntVSelect(meshInfo, map) != 2) { Manager::getSingleton()->getExporter()->printWarning(name + ": No actual UV-map defined. Discarding."); //materials[faces[i].materialId].removeLightmap(); continue; } if(map == 0) { //materials[faces[i].materialId].removeLightmap(); continue; } if(meshInfo->pntVSelect(meshInfo, map) != 2) { Manager::getSingleton()->getExporter()->printWarning(name + ": UV-map isn't 2-dimensional. Discarding."); //materials[faces[i].materialId].removeLightmap(); continue; } float uv[2] = { 0 }; LWPntID vertexId = vertices[faces[i].indices[j]].id; // Finally query texture coordinates if(meshInfo->pntVPGet(meshInfo, vertexId, faces[i].id, uv)) { faces[i].uvs2[j].x = uv[0]; faces[i].uvs2[j].y = -uv[1]; if(faces[i].hasUvs[j] == false) { faces[i].uvs[j].x = faces[i].uvs2[j].x; faces[i].uvs[j].y = faces[i].uvs2[j].y; } faces[i].hasUvs[j] = true; } else if(meshInfo->pntVGet(meshInfo, vertexId, uv)) { faces[i].uvs2[j].x = uv[0]; faces[i].uvs2[j].y = -uv[1]; if(faces[i].hasUvs[j] == false) { faces[i].uvs[j].x = faces[i].uvs2[j].x; faces[i].uvs[j].y = faces[i].uvs2[j].y; } faces[i].hasUvs[j] = true; } //else // materials[faces[i].materialId].removeLightmap(); } //else // materials[faces[i].materialId].removeLightmap(); /* else // Projected mapping { // Normals largest absolute value defines dominant axis (in world and object space) FBVector worldNormal = faces[i].normal; transform.RotateVector(worldNormal); int wAxis = getDominantAxis(worldNormal); int oAxis = getDominantAxis(faces[i].normal); // Position in world and object space Vector &vO = vertices[faces[i].indices[j]].position; Vector vW = transform.GetTransformedVector(vO); double oPosition[3] = { vO.x, vO.y, vO.z }; double wPosition[3] = { vW.x, vW.y, vW.z }; double uv[2] = { 0 }; textureFunctions->evaluateUV(layerId, wAxis, oAxis, oPosition, wPosition, uv); faces[i].uvs2[j].x = static_cast<double> (uv[0]); faces[i].uvs2[j].y = static_cast<double> (-uv[1]); if(faces[i].hasUvs[j] == false) { faces[i].uvs[j].x = faces[i].uvs2[j].x; faces[i].uvs[j].y = faces[i].uvs2[j].y; } faces[i].hasUvs[j] = true; } */ } } if(meshInfo->destroy) meshInfo->destroy(meshInfo); }
ObjectDB *getObjectDB( LWItemID id, GlobalFunc *global ) { LWObjectInfo *objinfo; LWMeshInfo *mesh; LWPntID ptid; ObjectDB *odb; const char *name; int npts, npols, nverts, i, j, k, ok = 0; /* get the object info global */ objinfo = (st_LWObjectInfo*)global( LWOBJECTINFO_GLOBAL, GFUSE_TRANSIENT ); if ( !objinfo ) return NULL; /* get the mesh info for the object */ mesh = objinfo->meshInfo( id, 1 ); if ( !mesh ) return NULL; /* alloc the object database */ odb = (st_ObjectDB*)calloc( 1, sizeof( ObjectDB )); if ( !odb ) goto Finish; odb->id = id; name = objinfo->filename( id ); odb->filename = (char*)malloc( xr_strlen( name ) + 1 ); if ( !odb->filename ) goto Finish; strcpy( odb->filename, name ); /* alloc and init the points array */ npts = mesh->numPoints( mesh ); odb->pt = (st_DBPoint*)calloc( npts, sizeof( DBPoint )); if ( !odb->pt ) goto Finish; if ( mesh->scanPoints( mesh, (int (__cdecl *)(void *,struct st_GCoreVertex *))pntScan, odb )) goto Finish; /* alloc and init the polygons array */ npols = mesh->numPolygons( mesh ); odb->pol = (st_DBPolygon*)calloc( npols, sizeof( DBPolygon )); if ( !odb->pol ) goto Finish; if ( mesh->scanPolys( mesh, (int (__cdecl *)(void *,struct st_GCorePolygon *))polScan, odb )) goto Finish; /* get the vertices of each polygon */ for ( i = 0; i < npols; i++ ) { nverts = mesh->polSize( mesh, odb->pol[ i ].id ); odb->pol[ i ].v = (st_DBPolVert*)calloc( nverts, sizeof( DBPolVert )); if ( !odb->pol[ i ].v ) goto Finish; odb->pol[ i ].nverts = nverts; for ( j = 0; j < nverts; j++ ) { ptid = mesh->polVertex( mesh, odb->pol[ i ].id, j ); odb->pol[ i ].v[ j ].index = findVert( odb, ptid ); } } /* count the number of polygons per point */ for ( i = 0; i < npols; i++ ) for ( j = 0; j < odb->pol[ i ].nverts; j++ ) ++odb->pt[ odb->pol[ i ].v[ j ].index ].npols; /* alloc per-point polygon arrays */ for ( i = 0; i < npts; i++ ) { if ( odb->pt[ i ].npols == 0 ) continue; odb->pt[ i ].pol = (int*)calloc( odb->pt[ i ].npols, sizeof( int )); if ( !odb->pt[ i ].pol ) goto Finish; odb->pt[ i ].npols = 0; } /* fill in polygon array for each point */ for ( i = 0; i < npols; i++ ) { for ( j = 0; j < odb->pol[ i ].nverts; j++ ) { k = odb->pol[ i ].v[ j ].index; odb->pt[ k ].pol[ odb->pt[ k ].npols ] = i; ++odb->pt[ k ].npols; } } /* get the base position of each point */ for ( i = 0; i < npts; i++ ) mesh->pntBasePos( mesh, odb->pt[ i ].id, odb->pt[ i ].pos[ 0 ] ); /* init the point search array */ /* do this here if you need to search by base pos, or later if you need to search by final pos */ // if ( !initPointSearch( odb, 0 )) // goto Finish; /* calculate the base normal of each polygon */ getPolyNormals( odb, 0 ); /* get the vmaps */ if ( !getObjectVMaps( odb, mesh, global )) goto Finish; /* get the surfaces */ if ( !getObjectSurfs( odb, mesh, global )) goto Finish; /* calculate initial vertex normals */ getVertNormals( odb, 0 ); /* done */ ok = 1; Finish: if ( mesh->destroy ) mesh->destroy( mesh ); if ( !ok ) { freeObjectDB( odb ); return NULL; } return odb; }