/* ================= R_MergeSurfaceList Only deals with vertexes and indexes, not silhouettes, planes, etc. Does NOT perform a cleanup triangles, so there may be duplicated verts in the result. ================= */ srfTriangles_t *R_MergeSurfaceList( const srfTriangles_t **surfaces, int numSurfaces ) { srfTriangles_t *newTri; const srfTriangles_t *tri; int i, j; int totalVerts; int totalIndexes; totalVerts = 0; totalIndexes = 0; for ( i = 0 ; i < numSurfaces ; i++ ) { totalVerts += surfaces[i]->numVerts; totalIndexes += surfaces[i]->numIndices; } newTri = R_AllocStaticTriSurf(); newTri->numVerts = totalVerts; newTri->numIndices = totalIndexes; R_AllocStaticTriSurfVerts( newTri, newTri->numVerts ); R_AllocStaticTriSurfIndices( newTri, newTri->numIndices ); totalVerts = 0; totalIndexes = 0; for ( i = 0 ; i < numSurfaces ; i++ ) { tri = surfaces[i]; memcpy( newTri->verts + totalVerts, tri->verts, tri->numVerts * sizeof( *tri->verts ) ); for ( j = 0 ; j < tri->numIndices ; j++ ) { newTri->indices[ totalIndexes + j ] = totalVerts + tri->indices[j]; } totalVerts += tri->numVerts; totalIndexes += tri->numIndices; } return newTri; }
void GameLocal::LoadAllModel() { StaticModel* dsmodel = new StaticModel; LoadMesh3DS("../Media/Dino.3ds", dsmodel); AddStaticModel(dsmodel); StaticModel* model = resourceSys->AddMesh("ninja.b3d"); AddStaticModel(model); drawSurf_t* drawSur = R_AllocDrawSurf(); drawSur->geo = R_AllocStaticTriSurf(); srfTriangles_t* tri = drawSur->geo; tri->numVerts = KnightModel::numVertices; tri->numIndexes = KnightModel::numIndices; drawSur->view = _camera->GetViewProj(); R_AllocStaticTriSurfVerts(tri, tri->numVerts); for (int i = 0; i < KnightModel::numVertices; i++) { memcpy(&(tri->verts[i].xyz), KnightModel::vertices[i].position, sizeof(float) * 3); memcpy(&(tri->verts[i].uv), KnightModel::vertices[i].uv, sizeof(float) * 3); memcpy(&(tri->verts[i].normal), KnightModel::vertices[i].normal, sizeof(float) * 3); } tri->indexes = new glIndex_t[KnightModel::numIndices]; memcpy(tri->indexes, KnightModel::indices, tri->numIndexes*sizeof(glIndex_t)); R_GenerateGeometryVbo(tri); renderSys->AddDrawSur(drawSur); }
/* ==================== idMD5Mesh::UpdateSurface ==================== */ void idMD5Mesh::UpdateSurface( const struct renderEntity_s *ent, const idJointMat *entJoints, const idJointMat *entJointsInverted, modelSurface_t *surf ) { tr.pc.c_deformedSurfaces++; tr.pc.c_deformedVerts += deformInfo->numOutputVerts; tr.pc.c_deformedIndexes += deformInfo->numIndexes; surf->shader = shader; if ( surf->geometry != NULL ) { // if the number of verts and indexes are the same we can re-use the triangle surface if ( surf->geometry->numVerts == deformInfo->numOutputVerts && surf->geometry->numIndexes == deformInfo->numIndexes ) { R_FreeStaticTriSurfVertexCaches( surf->geometry ); } else { R_FreeStaticTriSurf( surf->geometry ); surf->geometry = R_AllocStaticTriSurf(); } } else { surf->geometry = R_AllocStaticTriSurf(); } srfTriangles_t * tri = surf->geometry; // note that some of the data is referenced, and should not be freed tri->referencedIndexes = true; tri->numIndexes = deformInfo->numIndexes; tri->indexes = deformInfo->indexes; tri->silIndexes = deformInfo->silIndexes; tri->numMirroredVerts = deformInfo->numMirroredVerts; tri->mirroredVerts = deformInfo->mirroredVerts; tri->numDupVerts = deformInfo->numDupVerts; tri->dupVerts = deformInfo->dupVerts; tri->numSilEdges = deformInfo->numSilEdges; tri->silEdges = deformInfo->silEdges; tri->indexCache = deformInfo->staticIndexCache; tri->numVerts = deformInfo->numOutputVerts; if ( r_useGPUSkinning.GetBool() ) { if ( tri->verts != NULL && tri->verts != deformInfo->verts ) { R_FreeStaticTriSurfVerts( tri ); } tri->verts = deformInfo->verts; tri->ambientCache = deformInfo->staticAmbientCache; tri->shadowCache = deformInfo->staticShadowCache; tri->referencedVerts = true; } else { if ( tri->verts == NULL || tri->verts == deformInfo->verts ) { tri->verts = NULL; R_AllocStaticTriSurfVerts( tri, deformInfo->numOutputVerts ); assert( tri->verts != NULL ); // quiet analyze warning memcpy( tri->verts, deformInfo->verts, deformInfo->numOutputVerts * sizeof( deformInfo->verts[0] ) ); // copy over the texture coordinates } TransformVertsAndTangents( tri->verts, deformInfo->numOutputVerts, deformInfo->verts, entJointsInverted ); tri->referencedVerts = false; } tri->tangentsCalculated = true; CalculateBounds( entJoints, tri->bounds ); }
/* ==================== idRenderModelLiquid::GenerateSurface ==================== */ modelSurface_t idRenderModelLiquid::GenerateSurface( float lerp ) { srfTriangles_t *tri; int i, base; idDrawVert *vert; modelSurface_t surf; float inv_lerp; inv_lerp = 1.0f - lerp; vert = verts.Ptr(); for( i = 0; i < verts.Num(); i++, vert++ ) { vert->xyz.z = page1[ i ] * lerp + page2[ i ] * inv_lerp; } tr.pc.c_deformedSurfaces++; tr.pc.c_deformedVerts += deformInfo->numOutputVerts; tr.pc.c_deformedIndexes += deformInfo->numIndexes; tri = R_AllocStaticTriSurf(); // note that some of the data is references, and should not be freed tri->deformedSurface = true; tri->numIndexes = deformInfo->numIndexes; tri->indexes = deformInfo->indexes; tri->silIndexes = deformInfo->silIndexes; tri->numMirroredVerts = deformInfo->numMirroredVerts; tri->mirroredVerts = deformInfo->mirroredVerts; tri->numDupVerts = deformInfo->numDupVerts; tri->dupVerts = deformInfo->dupVerts; tri->numSilEdges = deformInfo->numSilEdges; tri->silEdges = deformInfo->silEdges; tri->dominantTris = deformInfo->dominantTris; tri->numVerts = deformInfo->numOutputVerts; R_AllocStaticTriSurfVerts( tri, tri->numVerts ); SIMDProcessor->Memcpy( tri->verts, verts.Ptr(), deformInfo->numSourceVerts * sizeof(tri->verts[0]) ); // replicate the mirror seam vertexes base = deformInfo->numOutputVerts - deformInfo->numMirroredVerts; for ( i = 0 ; i < deformInfo->numMirroredVerts ; i++ ) { tri->verts[base + i] = tri->verts[deformInfo->mirroredVerts[i]]; } R_BoundTriSurf( tri ); // If a surface is going to be have a lighting interaction generated, it will also have to call // R_DeriveTangents() to get normals, tangents, and face planes. If it only // needs shadows generated, it will only have to generate face planes. If it only // has ambient drawing, or is culled, no additional work will be necessary if ( !r_useDeferredTangents.GetBool() ) { // set face planes, vertex normals, tangents R_DeriveTangents( tri ); } surf.geometry = tri; surf.shader = shader; return surf; }
static int lgeo_newVert(lua_State* L) { srfTriangles_s* obj = lgeo_to(L); int num = lua_tonumber(L, -2); obj->numVerts = num; R_AllocStaticTriSurfVerts(obj, num); return 1; }
/* ===================== R_PolytopeSurface Generate vertexes and indexes for a polytope, and optionally returns the polygon windings. The positive sides of the planes will be visible. ===================== */ srfTriangles_t *R_PolytopeSurface( int numPlanes, const idPlane *planes, idWinding **windings ) { int i, j; srfTriangles_t *tri; idFixedWinding planeWindings[MAX_POLYTOPE_PLANES]; int numVerts, numIndexes; if( numPlanes > MAX_POLYTOPE_PLANES ) { common->Error( "R_PolytopeSurface: more than %d planes", MAX_POLYTOPE_PLANES ); } numVerts = 0; numIndexes = 0; for( i = 0; i < numPlanes; i++ ) { const idPlane &plane = planes[i]; idFixedWinding &w = planeWindings[i]; w.BaseForPlane( plane ); for( j = 0; j < numPlanes; j++ ) { const idPlane &plane2 = planes[j]; if( j == i ) { continue; } else if( !w.ClipInPlace( -plane2, ON_EPSILON ) ) { break; } } if( w.GetNumPoints() <= 2 ) { continue; } numVerts += w.GetNumPoints(); numIndexes += ( w.GetNumPoints() - 2 ) * 3; } // allocate the surface tri = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts( tri, numVerts ); R_AllocStaticTriSurfIndexes( tri, numIndexes ); // copy the data from the windings for( i = 0; i < numPlanes; i++ ) { idFixedWinding &w = planeWindings[i]; if( !w.GetNumPoints() ) { continue; } for( j = 0 ; j < w.GetNumPoints() ; j++ ) { tri->verts[tri->numVerts + j ].Clear(); tri->verts[tri->numVerts + j ].xyz = w[j].ToVec3(); } for( j = 1 ; j < w.GetNumPoints() - 1 ; j++ ) { tri->indexes[ tri->numIndexes + 0 ] = tri->numVerts; tri->indexes[ tri->numIndexes + 1 ] = tri->numVerts + j; tri->indexes[ tri->numIndexes + 2 ] = tri->numVerts + j + 1; tri->numIndexes += 3; } tri->numVerts += w.GetNumPoints(); // optionally save the winding if( windings ) { windings[i] = new idWinding( w.GetNumPoints() ); *windings[i] = w; } } R_BoundTriSurf( tri ); return tri; }
/* ================ CombineModelSurfaces Frees the model and returns a new model with all triangles combined into one surface ================ */ static idRenderModel *CombineModelSurfaces( idRenderModel *model ) { int totalVerts; int totalIndexes; int numIndexes; int numVerts; int i, j; totalVerts = 0; totalIndexes = 0; for ( i = 0 ; i < model->NumSurfaces() ; i++ ) { const modelSurface_t *surf = model->Surface(i); totalVerts += surf->geometry->numVerts; totalIndexes += surf->geometry->numIndexes; } srfTriangles_t *newTri = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts( newTri, totalVerts ); R_AllocStaticTriSurfIndexes( newTri, totalIndexes ); newTri->numVerts = totalVerts; newTri->numIndexes = totalIndexes; newTri->bounds.Clear(); idDrawVert *verts = newTri->verts; glIndex_t *indexes = newTri->indexes; numIndexes = 0; numVerts = 0; for ( i = 0 ; i < model->NumSurfaces() ; i++ ) { const modelSurface_t *surf = model->Surface(i); const srfTriangles_t *tri = surf->geometry; memcpy( verts + numVerts, tri->verts, tri->numVerts * sizeof( tri->verts[0] ) ); for ( j = 0 ; j < tri->numIndexes ; j++ ) { indexes[numIndexes+j] = numVerts + tri->indexes[j]; } newTri->bounds.AddBounds( tri->bounds ); numIndexes += tri->numIndexes; numVerts += tri->numVerts; } modelSurface_t surf; surf.id = 0; surf.geometry = newTri; surf.shader = tr.defaultMaterial; idRenderModel *newModel = renderModelManager->AllocModel(); newModel->AddSurface( surf ); renderModelManager->FreeModel( model ); return newModel; }
/* ==================== ShareMapTriVerts Converts independent triangles to shared vertex triangles ==================== */ srfTriangles_t *ShareMapTriVerts( const mapTri_t *tris ) { const mapTri_t *step; int count; int i, j; int numVerts; int numIndexes; srfTriangles_t *uTri; // unique the vertexes count = CountTriList( tris ); uTri = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts( uTri, count * 3 ); R_AllocStaticTriSurfIndexes( uTri, count * 3 ); numVerts = 0; numIndexes = 0; for ( step = tris ; step ; step = step->next ) { for ( i = 0 ; i < 3 ; i++ ) { const idDrawVert *dv; dv = &step->v[i]; // search for a match for ( j = 0 ; j < numVerts ; j++ ) { if ( MatchVert( &uTri->verts[j], dv ) ) { break; } } if ( j == numVerts ) { numVerts++; uTri->verts[j].xyz = dv->xyz; uTri->verts[j].normal = dv->normal; uTri->verts[j].st[0] = dv->st[0]; uTri->verts[j].st[1] = dv->st[1]; } uTri->indexes[numIndexes++] = j; } } uTri->numVerts = numVerts; uTri->numIndexes = numIndexes; return uTri; }
/* ==================== idRenderModelLiquid::GenerateSurface ==================== */ modelSurface_t idRenderModelLiquid::GenerateSurface( float lerp ) { srfTriangles_t* tri; int i, base; idDrawVert* vert; modelSurface_t surf; float inv_lerp; inv_lerp = 1.0f - lerp; vert = verts.Ptr(); for( i = 0; i < verts.Num(); i++, vert++ ) { vert->xyz.z = page1[ i ] * lerp + page2[ i ] * inv_lerp; } tr.pc.c_deformedSurfaces++; tr.pc.c_deformedVerts += deformInfo->numOutputVerts; tr.pc.c_deformedIndexes += deformInfo->numIndexes; tri = R_AllocStaticTriSurf(); // note that some of the data is references, and should not be freed tri->referencedIndexes = true; tri->numIndexes = deformInfo->numIndexes; tri->indexes = deformInfo->indexes; tri->silIndexes = deformInfo->silIndexes; tri->numMirroredVerts = deformInfo->numMirroredVerts; tri->mirroredVerts = deformInfo->mirroredVerts; tri->numDupVerts = deformInfo->numDupVerts; tri->dupVerts = deformInfo->dupVerts; tri->numSilEdges = deformInfo->numSilEdges; tri->silEdges = deformInfo->silEdges; tri->numVerts = deformInfo->numOutputVerts; R_AllocStaticTriSurfVerts( tri, tri->numVerts ); SIMDProcessor->Memcpy( tri->verts, verts.Ptr(), deformInfo->numSourceVerts * sizeof( tri->verts[0] ) ); // replicate the mirror seam vertexes base = deformInfo->numOutputVerts - deformInfo->numMirroredVerts; for( i = 0 ; i < deformInfo->numMirroredVerts ; i++ ) { tri->verts[base + i] = tri->verts[deformInfo->mirroredVerts[i]]; } R_BoundTriSurf( tri ); surf.geometry = tri; surf.shader = shader; return surf; }
/* ======================== idRenderModelMD5::LoadBinaryModel ======================== */ bool idRenderModelMD5::LoadBinaryModel( idFile* file, const ID_TIME_T sourceTimeStamp ) { if( !idRenderModelStatic::LoadBinaryModel( file, sourceTimeStamp ) ) { return false; } unsigned int magic = 0; file->ReadBig( magic ); if( magic != MD5B_MAGIC ) { return false; } int tempNum; file->ReadBig( tempNum ); joints.SetNum( tempNum ); for( int i = 0; i < joints.Num(); i++ ) { file->ReadString( joints[i].name ); int offset; file->ReadBig( offset ); if( offset >= 0 ) { joints[i].parent = joints.Ptr() + offset; } else { joints[i].parent = NULL; } } file->ReadBig( tempNum ); defaultPose.SetNum( tempNum ); for( int i = 0; i < defaultPose.Num(); i++ ) { file->ReadBig( defaultPose[i].q.x ); file->ReadBig( defaultPose[i].q.y ); file->ReadBig( defaultPose[i].q.z ); file->ReadBig( defaultPose[i].q.w ); file->ReadVec3( defaultPose[i].t ); } file->ReadBig( tempNum ); invertedDefaultPose.SetNum( tempNum ); for( int i = 0; i < invertedDefaultPose.Num(); i++ ) { file->ReadBigArray( invertedDefaultPose[ i ].ToFloatPtr(), JOINTMAT_TYPESIZE ); } SIMD_INIT_LAST_JOINT( invertedDefaultPose.Ptr(), joints.Num() ); file->ReadBig( tempNum ); meshes.SetNum( tempNum ); for( int i = 0; i < meshes.Num(); i++ ) { idStr materialName; file->ReadString( materialName ); if( materialName.IsEmpty() ) { meshes[i].shader = NULL; } else { meshes[i].shader = declManager->FindMaterial( materialName ); } file->ReadBig( meshes[i].numVerts ); file->ReadBig( meshes[i].numTris ); file->ReadBig( meshes[i].numMeshJoints ); meshes[i].meshJoints = ( byte* ) Mem_Alloc( meshes[i].numMeshJoints * sizeof( meshes[i].meshJoints[0] ), TAG_MODEL ); file->ReadBigArray( meshes[i].meshJoints, meshes[i].numMeshJoints ); file->ReadBig( meshes[i].maxJointVertDist ); meshes[i].deformInfo = ( deformInfo_t* )R_ClearedStaticAlloc( sizeof( deformInfo_t ) ); deformInfo_t& deform = *meshes[i].deformInfo; file->ReadBig( deform.numSourceVerts ); file->ReadBig( deform.numOutputVerts ); file->ReadBig( deform.numIndexes ); file->ReadBig( deform.numMirroredVerts ); file->ReadBig( deform.numDupVerts ); file->ReadBig( deform.numSilEdges ); srfTriangles_t tri; memset( &tri, 0, sizeof( srfTriangles_t ) ); if( deform.numOutputVerts > 0 ) { R_AllocStaticTriSurfVerts( &tri, deform.numOutputVerts ); deform.verts = tri.verts; file->ReadBigArray( deform.verts, deform.numOutputVerts ); } if( deform.numIndexes > 0 ) { R_AllocStaticTriSurfIndexes( &tri, deform.numIndexes ); R_AllocStaticTriSurfSilIndexes( &tri, deform.numIndexes ); deform.indexes = tri.indexes; deform.silIndexes = tri.silIndexes; file->ReadBigArray( deform.indexes, deform.numIndexes ); file->ReadBigArray( deform.silIndexes, deform.numIndexes ); } if( deform.numMirroredVerts > 0 ) { R_AllocStaticTriSurfMirroredVerts( &tri, deform.numMirroredVerts ); deform.mirroredVerts = tri.mirroredVerts; file->ReadBigArray( deform.mirroredVerts, deform.numMirroredVerts ); } if( deform.numDupVerts > 0 ) { R_AllocStaticTriSurfDupVerts( &tri, deform.numDupVerts ); deform.dupVerts = tri.dupVerts; file->ReadBigArray( deform.dupVerts, deform.numDupVerts * 2 ); } if( deform.numSilEdges > 0 ) { R_AllocStaticTriSurfSilEdges( &tri, deform.numSilEdges ); deform.silEdges = tri.silEdges; assert( deform.silEdges != NULL ); for( int j = 0; j < deform.numSilEdges; j++ ) { file->ReadBig( deform.silEdges[j].p1 ); file->ReadBig( deform.silEdges[j].p2 ); file->ReadBig( deform.silEdges[j].v1 ); file->ReadBig( deform.silEdges[j].v2 ); } } idShadowVertSkinned* shadowVerts = ( idShadowVertSkinned* ) Mem_Alloc( ALIGN( deform.numOutputVerts * 2 * sizeof( idShadowVertSkinned ), 16 ), TAG_MODEL ); idShadowVertSkinned::CreateShadowCache( shadowVerts, deform.verts, deform.numOutputVerts ); deform.staticAmbientCache = vertexCache.AllocStaticVertex( deform.verts, ALIGN( deform.numOutputVerts * sizeof( idDrawVert ), VERTEX_CACHE_ALIGN ) ); deform.staticIndexCache = vertexCache.AllocStaticIndex( deform.indexes, ALIGN( deform.numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) ); deform.staticShadowCache = vertexCache.AllocStaticVertex( shadowVerts, ALIGN( deform.numOutputVerts * 2 * sizeof( idShadowVertSkinned ), VERTEX_CACHE_ALIGN ) ); Mem_Free( shadowVerts ); file->ReadBig( meshes[i].surfaceNum ); } return true; }
/* =============== idRenderModelSprite::InstantiateDynamicModel =============== */ idRenderModel * idRenderModelSprite::InstantiateDynamicModel( const struct renderEntity_s *renderEntity, const struct viewDef_s *viewDef, idRenderModel *cachedModel ) { idRenderModelStatic *staticModel; srfTriangles_t *tri; modelSurface_t surf; if ( cachedModel && !r_useCachedDynamicModels.GetBool() ) { delete cachedModel; cachedModel = NULL; } if ( renderEntity == NULL || viewDef == NULL ) { delete cachedModel; return NULL; } if ( cachedModel != NULL ) { assert( dynamic_cast<idRenderModelStatic *>( cachedModel ) != NULL ); assert( idStr::Icmp( cachedModel->Name(), sprite_SnapshotName ) == 0 ); staticModel = static_cast<idRenderModelStatic *>( cachedModel ); surf = *staticModel->Surface( 0 ); tri = surf.geometry; } else { staticModel = new idRenderModelStatic; staticModel->InitEmpty( sprite_SnapshotName ); tri = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts( tri, 4 ); R_AllocStaticTriSurfIndexes( tri, 6 ); tri->verts[ 0 ].Clear(); tri->verts[ 0 ].normal.Set( 1.0f, 0.0f, 0.0f ); tri->verts[ 0 ].tangents[0].Set( 0.0f, 1.0f, 0.0f ); tri->verts[ 0 ].tangents[1].Set( 0.0f, 0.0f, 1.0f ); tri->verts[ 0 ].st[ 0 ] = 0.0f; tri->verts[ 0 ].st[ 1 ] = 0.0f; tri->verts[ 1 ].Clear(); tri->verts[ 1 ].normal.Set( 1.0f, 0.0f, 0.0f ); tri->verts[ 1 ].tangents[0].Set( 0.0f, 1.0f, 0.0f ); tri->verts[ 1 ].tangents[1].Set( 0.0f, 0.0f, 1.0f ); tri->verts[ 1 ].st[ 0 ] = 1.0f; tri->verts[ 1 ].st[ 1 ] = 0.0f; tri->verts[ 2 ].Clear(); tri->verts[ 2 ].normal.Set( 1.0f, 0.0f, 0.0f ); tri->verts[ 2 ].tangents[0].Set( 0.0f, 1.0f, 0.0f ); tri->verts[ 2 ].tangents[1].Set( 0.0f, 0.0f, 1.0f ); tri->verts[ 2 ].st[ 0 ] = 1.0f; tri->verts[ 2 ].st[ 1 ] = 1.0f; tri->verts[ 3 ].Clear(); tri->verts[ 3 ].normal.Set( 1.0f, 0.0f, 0.0f ); tri->verts[ 3 ].tangents[0].Set( 0.0f, 1.0f, 0.0f ); tri->verts[ 3 ].tangents[1].Set( 0.0f, 0.0f, 1.0f ); tri->verts[ 3 ].st[ 0 ] = 0.0f; tri->verts[ 3 ].st[ 1 ] = 1.0f; tri->indexes[ 0 ] = 0; tri->indexes[ 1 ] = 1; tri->indexes[ 2 ] = 3; tri->indexes[ 3 ] = 1; tri->indexes[ 4 ] = 2; tri->indexes[ 5 ] = 3; tri->numVerts = 4; tri->numIndexes = 6; surf.geometry = tri; surf.id = 0; surf.shader = tr.defaultMaterial; staticModel->AddSurface( surf ); } int red = idMath::FtoiFast( renderEntity->shaderParms[ SHADERPARM_RED ] * 255.0f ); int green = idMath::FtoiFast( renderEntity->shaderParms[ SHADERPARM_GREEN ] * 255.0f ); int blue = idMath::FtoiFast( renderEntity->shaderParms[ SHADERPARM_BLUE ] * 255.0f ); int alpha = idMath::FtoiFast( renderEntity->shaderParms[ SHADERPARM_ALPHA ] * 255.0f ); idVec3 right = idVec3( 0.0f, renderEntity->shaderParms[ SHADERPARM_SPRITE_WIDTH ] * 0.5f, 0.0f ); idVec3 up = idVec3( 0.0f, 0.0f, renderEntity->shaderParms[ SHADERPARM_SPRITE_HEIGHT ] * 0.5f ); tri->verts[ 0 ].xyz = up + right; tri->verts[ 0 ].color[ 0 ] = red; tri->verts[ 0 ].color[ 1 ] = green; tri->verts[ 0 ].color[ 2 ] = blue; tri->verts[ 0 ].color[ 3 ] = alpha; tri->verts[ 1 ].xyz = up - right; tri->verts[ 1 ].color[ 0 ] = red; tri->verts[ 1 ].color[ 1 ] = green; tri->verts[ 1 ].color[ 2 ] = blue; tri->verts[ 1 ].color[ 3 ] = alpha; tri->verts[ 2 ].xyz = - right - up; tri->verts[ 2 ].color[ 0 ] = red; tri->verts[ 2 ].color[ 1 ] = green; tri->verts[ 2 ].color[ 2 ] = blue; tri->verts[ 2 ].color[ 3 ] = alpha; tri->verts[ 3 ].xyz = right - up; tri->verts[ 3 ].color[ 0 ] = red; tri->verts[ 3 ].color[ 1 ] = green; tri->verts[ 3 ].color[ 2 ] = blue; tri->verts[ 3 ].color[ 3 ] = alpha; R_BoundTriSurf( tri ); staticModel->bounds = tri->bounds; return staticModel; }
/* ================ idRenderWorldLocal::ParseModel ================ */ idRenderModel *idRenderWorldLocal::ParseModel( idLexer *src ) { idRenderModel *model; idToken token; int i, j; srfTriangles_t *tri; modelSurface_t surf; src->ExpectTokenString( "{" ); // parse the name src->ExpectAnyToken( &token ); model = renderModelManager->AllocModel(); model->InitEmpty( token ); int numSurfaces = src->ParseInt(); if ( numSurfaces < 0 ) { src->Error( "R_ParseModel: bad numSurfaces" ); } for ( i = 0 ; i < numSurfaces ; i++ ) { src->ExpectTokenString( "{" ); src->ExpectAnyToken( &token ); surf.shader = declManager->FindMaterial( token ); ((idMaterial*)surf.shader)->AddReference(); tri = R_AllocStaticTriSurf(); surf.geometry = tri; tri->numVerts = src->ParseInt(); tri->numIndexes = src->ParseInt(); R_AllocStaticTriSurfVerts( tri, tri->numVerts ); for ( j = 0 ; j < tri->numVerts ; j++ ) { float vec[8]; src->Parse1DMatrix( 8, vec ); tri->verts[j].xyz[0] = vec[0]; tri->verts[j].xyz[1] = vec[1]; tri->verts[j].xyz[2] = vec[2]; tri->verts[j].st[0] = vec[3]; tri->verts[j].st[1] = vec[4]; tri->verts[j].normal[0] = vec[5]; tri->verts[j].normal[1] = vec[6]; tri->verts[j].normal[2] = vec[7]; } R_AllocStaticTriSurfIndexes( tri, tri->numIndexes ); for ( j = 0 ; j < tri->numIndexes ; j++ ) { tri->indexes[j] = src->ParseInt(); } src->ExpectTokenString( "}" ); // add the completed surface to the model model->AddSurface( surf ); } src->ExpectTokenString( "}" ); model->FinishSurfaces(); return model; }
/* ==================== idRenderModelPrt::InstantiateDynamicModel ==================== */ idRenderModel* idRenderModelPrt::InstantiateDynamicModel( const struct renderEntity_s* renderEntity, const viewDef_t* viewDef, idRenderModel* cachedModel ) { idRenderModelStatic* staticModel; if( cachedModel && !r_useCachedDynamicModels.GetBool() ) { delete cachedModel; cachedModel = NULL; } // this may be triggered by a model trace or other non-view related source, to which we should look like an empty model if( renderEntity == NULL || viewDef == NULL ) { delete cachedModel; return NULL; } if( r_skipParticles.GetBool() ) { delete cachedModel; return NULL; } /* // if the entire system has faded out if ( renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] && viewDef->renderView.time * 0.001f >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] ) { delete cachedModel; return NULL; } */ if( cachedModel != NULL ) { assert( dynamic_cast<idRenderModelStatic*>( cachedModel ) != NULL ); assert( idStr::Icmp( cachedModel->Name(), parametricParticle_SnapshotName ) == 0 ); staticModel = static_cast<idRenderModelStatic*>( cachedModel ); } else { staticModel = new( TAG_MODEL ) idRenderModelStatic; staticModel->InitEmpty( parametricParticle_SnapshotName ); } particleGen_t g; g.renderEnt = renderEntity; g.renderView = &viewDef->renderView; g.origin.Zero(); g.axis.Identity(); for( int stageNum = 0; stageNum < particleSystem->stages.Num(); stageNum++ ) { idParticleStage* stage = particleSystem->stages[stageNum]; if( !stage->material ) { continue; } if( !stage->cycleMsec ) { continue; } if( stage->hidden ) // just for gui particle editor use { staticModel->DeleteSurfaceWithId( stageNum ); continue; } idRandom steppingRandom, steppingRandom2; int stageAge = g.renderView->time[renderEntity->timeGroup] + renderEntity->shaderParms[SHADERPARM_TIMEOFFSET] * 1000 - stage->timeOffset * 1000; int stageCycle = stageAge / stage->cycleMsec; // some particles will be in this cycle, some will be in the previous cycle steppingRandom.SetSeed( ( ( stageCycle << 10 ) & idRandom::MAX_RAND ) ^ ( int )( renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND ) ); steppingRandom2.SetSeed( ( ( ( stageCycle - 1 ) << 10 ) & idRandom::MAX_RAND ) ^ ( int )( renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND ) ); int count = stage->totalParticles * stage->NumQuadsPerParticle(); int surfaceNum; modelSurface_t* surf; if( staticModel->FindSurfaceWithId( stageNum, surfaceNum ) ) { surf = &staticModel->surfaces[surfaceNum]; R_FreeStaticTriSurfVertexCaches( surf->geometry ); } else { surf = &staticModel->surfaces.Alloc(); surf->id = stageNum; surf->shader = stage->material; surf->geometry = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts( surf->geometry, 4 * count ); R_AllocStaticTriSurfIndexes( surf->geometry, 6 * count ); } int numVerts = 0; idDrawVert* verts = surf->geometry->verts; for( int index = 0; index < stage->totalParticles; index++ ) { g.index = index; // bump the random steppingRandom.RandomInt(); steppingRandom2.RandomInt(); // calculate local age for this index int bunchOffset = stage->particleLife * 1000 * stage->spawnBunching * index / stage->totalParticles; int particleAge = stageAge - bunchOffset; int particleCycle = particleAge / stage->cycleMsec; if( particleCycle < 0 ) { // before the particleSystem spawned continue; } if( stage->cycles && particleCycle >= stage->cycles ) { // cycled systems will only run cycle times continue; } if( particleCycle == stageCycle ) { g.random = steppingRandom; } else { g.random = steppingRandom2; } int inCycleTime = particleAge - particleCycle * stage->cycleMsec; if( renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] && g.renderView->time[renderEntity->timeGroup] - inCycleTime >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] * 1000 ) { // don't fire any more particles continue; } // supress particles before or after the age clamp g.frac = ( float )inCycleTime / ( stage->particleLife * 1000 ); if( g.frac < 0.0f ) { // yet to be spawned continue; } if( g.frac > 1.0f ) { // this particle is in the deadTime band continue; } // this is needed so aimed particles can calculate origins at different times g.originalRandom = g.random; g.age = g.frac * stage->particleLife; // if the particle doesn't get drawn because it is faded out or beyond a kill region, don't increment the verts numVerts += stage->CreateParticle( &g, verts + numVerts ); } // numVerts must be a multiple of 4 assert( ( numVerts & 3 ) == 0 && numVerts <= 4 * count ); // build the indexes int numIndexes = 0; triIndex_t* indexes = surf->geometry->indexes; for( int i = 0; i < numVerts; i += 4 ) { indexes[numIndexes + 0] = i + 0; indexes[numIndexes + 1] = i + 2; indexes[numIndexes + 2] = i + 3; indexes[numIndexes + 3] = i + 0; indexes[numIndexes + 4] = i + 3; indexes[numIndexes + 5] = i + 1; numIndexes += 6; } surf->geometry->tangentsCalculated = false; surf->geometry->numVerts = numVerts; surf->geometry->numIndexes = numIndexes; surf->geometry->bounds = stage->bounds; // just always draw the particles } return staticModel; }
bool MeshLoaderB3D::ReadVrts() { const int max_tex_coords = 3; int flags, tex_coord_sets, tex_coord_set_size; _file->ReadInt(flags); _file->ReadInt(tex_coord_sets); _file->ReadInt(tex_coord_set_size); if (tex_coord_sets >= max_tex_coords || tex_coord_set_size >= 4) // Something is wrong { Sys_Printf("tex_coord_sets or tex_coord_set_size too big"); return false; } //------ Allocate Memory, for speed -----------// int sizeOfVertex = 3; bool hasNormal = false; bool hasVertexColors = false; if (flags & 1) { hasNormal = true; sizeOfVertex += 3; } if (flags & 2) { sizeOfVertex += 4; hasVertexColors=true; } sizeOfVertex += tex_coord_sets*tex_coord_set_size; unsigned int size = _stack[_stackIndex-1] - _file->Tell(); //106407 16800 unsigned int numVertex = size / sizeof(float) ; numVertex /= sizeOfVertex; srfTriangles_t* tri = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts(tri, numVertex); tri->numVerts = numVertex; int idx = 0; while( CheckSize()) { float color[4]={1.0f, 1.0f, 1.0f, 1.0f}; _file->ReadVec3(tri->verts[idx].xyz); if (flags & 1) { _file->ReadVec3(tri->verts[idx].normal); } if (flags & 2) { _file->ReadFloat(color[0]); _file->ReadFloat(color[1]); _file->ReadFloat(color[2]); _file->ReadFloat(color[3]); } float u, v; for (int i = 0; i < tex_coord_sets; ++i) { //for (int j = 0; j < tex_coord_set_size; ++j) { _file->ReadFloat(u); _file->ReadFloat(v); //v = 1 - v; } } tri->verts[idx].st = idVec2(u, v); idx++; } modelSurface_t modelSurf; modelSurf.id = _surfaces.Size(); modelSurf.shader = declManager->FindMaterial("textures/ninja/ninja"); modelSurf.geometry = tri; _surfaces.Append(modelSurf); return true; }
/* ==================== idMD5Mesh::UpdateSurface ==================== */ void idMD5Mesh::UpdateSurface( const struct renderEntity_s *ent, const idJointMat *entJoints, modelSurface_t *surf ) { int i, base; srfTriangles_t *tri; tr.pc.c_deformedSurfaces++; tr.pc.c_deformedVerts += deformInfo->numOutputVerts; tr.pc.c_deformedIndexes += deformInfo->numIndexes; surf->shader = shader; if ( surf->geometry ) { // if the number of verts and indexes are the same we can re-use the triangle surface // the number of indexes must be the same to assure the correct amount of memory is allocated for the facePlanes if ( surf->geometry->numVerts == deformInfo->numOutputVerts && surf->geometry->numIndexes == deformInfo->numIndexes ) { R_FreeStaticTriSurfVertexCaches( surf->geometry ); } else { R_FreeStaticTriSurf( surf->geometry ); surf->geometry = R_AllocStaticTriSurf(); } } else { surf->geometry = R_AllocStaticTriSurf(); } tri = surf->geometry; // note that some of the data is references, and should not be freed tri->deformedSurface = true; tri->tangentsCalculated = false; tri->facePlanesCalculated = false; tri->numIndexes = deformInfo->numIndexes; tri->indexes = deformInfo->indexes; tri->silIndexes = deformInfo->silIndexes; tri->numMirroredVerts = deformInfo->numMirroredVerts; tri->mirroredVerts = deformInfo->mirroredVerts; tri->numDupVerts = deformInfo->numDupVerts; tri->dupVerts = deformInfo->dupVerts; tri->numSilEdges = deformInfo->numSilEdges; tri->silEdges = deformInfo->silEdges; tri->dominantTris = deformInfo->dominantTris; tri->numVerts = deformInfo->numOutputVerts; if ( tri->verts == NULL ) { R_AllocStaticTriSurfVerts( tri, tri->numVerts ); for ( i = 0; i < deformInfo->numSourceVerts; i++ ) { tri->verts[i].Clear(); tri->verts[i].st = texCoords[i]; } } if ( ent->shaderParms[ SHADERPARM_MD5_SKINSCALE ] != 0.0f ) { TransformScaledVerts( tri->verts, entJoints, ent->shaderParms[ SHADERPARM_MD5_SKINSCALE ] ); } else { TransformVerts( tri->verts, entJoints ); } // replicate the mirror seam vertexes base = deformInfo->numOutputVerts - deformInfo->numMirroredVerts; for ( i = 0; i < deformInfo->numMirroredVerts; i++ ) { tri->verts[base + i] = tri->verts[deformInfo->mirroredVerts[i]]; } R_BoundTriSurf( tri ); // If a surface is going to be have a lighting interaction generated, it will also have to call // R_DeriveTangents() to get normals, tangents, and face planes. If it only // needs shadows generated, it will only have to generate face planes. If it only // has ambient drawing, or is culled, no additional work will be necessary if ( !r_useDeferredTangents.GetBool() ) { // set face planes, vertex normals, tangents R_DeriveTangents( tri ); } }
/* ==================== idRenderModelOverlay::AddOverlaySurfacesToModel ==================== */ void idRenderModelOverlay::AddOverlaySurfacesToModel( idRenderModel *baseModel ) { int i, j, k, numVerts, numIndexes, surfaceNum; const modelSurface_t *baseSurf; idRenderModelStatic *staticModel; overlaySurface_t *surf; srfTriangles_t *newTri; modelSurface_t *newSurf; if ( baseModel == NULL || baseModel->IsDefaultModel() ) { return; } // md5 models won't have any surfaces when r_showSkel is set if ( !baseModel->NumSurfaces() ) { return; } if ( baseModel->IsDynamicModel() != DM_STATIC ) { common->Error( "idRenderModelOverlay::AddOverlaySurfacesToModel: baseModel is not a static model" ); } assert( dynamic_cast<idRenderModelStatic *>(baseModel) != NULL ); staticModel = static_cast<idRenderModelStatic *>(baseModel); staticModel->overlaysAdded = 0; if ( !materials.Num() ) { staticModel->DeleteSurfacesWithNegativeId(); return; } for ( k = 0; k < materials.Num(); k++ ) { numVerts = numIndexes = 0; for ( i = 0; i < materials[k]->surfaces.Num(); i++ ) { numVerts += materials[k]->surfaces[i]->numVerts; numIndexes += materials[k]->surfaces[i]->numIndexes; } if ( staticModel->FindSurfaceWithId( -1 - k, surfaceNum ) ) { newSurf = &staticModel->surfaces[surfaceNum]; } else { newSurf = &staticModel->surfaces.Alloc(); newSurf->geometry = NULL; newSurf->shader = materials[k]->material; newSurf->id = -1 - k; } if ( newSurf->geometry == NULL || newSurf->geometry->numVerts < numVerts || newSurf->geometry->numIndexes < numIndexes ) { R_FreeStaticTriSurf( newSurf->geometry ); newSurf->geometry = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts( newSurf->geometry, numVerts ); R_AllocStaticTriSurfIndexes( newSurf->geometry, numIndexes ); SIMDProcessor->Memset( newSurf->geometry->verts, 0, numVerts * sizeof( newTri->verts[0] ) ); } else { R_FreeStaticTriSurfVertexCaches( newSurf->geometry ); } newTri = newSurf->geometry; numVerts = numIndexes = 0; for ( i = 0; i < materials[k]->surfaces.Num(); i++ ) { surf = materials[k]->surfaces[i]; // get the model surface for this overlay surface if ( surf->surfaceNum < staticModel->NumSurfaces() ) { baseSurf = staticModel->Surface( surf->surfaceNum ); } else { baseSurf = NULL; } // if the surface ids no longer match if ( !baseSurf || baseSurf->id != surf->surfaceId ) { // find the surface with the correct id if ( staticModel->FindSurfaceWithId( surf->surfaceId, surf->surfaceNum ) ) { baseSurf = staticModel->Surface( surf->surfaceNum ); } else { // the surface with this id no longer exists FreeSurface( surf ); materials[k]->surfaces.RemoveIndex( i ); i--; continue; } } // copy indexes; for ( j = 0; j < surf->numIndexes; j++ ) { newTri->indexes[numIndexes + j] = numVerts + surf->indexes[j]; } numIndexes += surf->numIndexes; // copy vertices for ( j = 0; j < surf->numVerts; j++ ) { overlayVertex_t *overlayVert = &surf->verts[j]; newTri->verts[numVerts].st[0] = overlayVert->st[0]; newTri->verts[numVerts].st[1] = overlayVert->st[1]; if ( overlayVert->vertexNum >= baseSurf->geometry->numVerts ) { // This can happen when playing a demofile and a model has been changed since it was recorded, so just issue a warning and go on. common->Warning( "idRenderModelOverlay::AddOverlaySurfacesToModel: overlay vertex out of range. Model has probably changed since generating the overlay." ); FreeSurface( surf ); materials[k]->surfaces.RemoveIndex( i ); staticModel->DeleteSurfaceWithId( newSurf->id ); return; } newTri->verts[numVerts].xyz = baseSurf->geometry->verts[overlayVert->vertexNum].xyz; numVerts++; } } newTri->numVerts = numVerts; newTri->numIndexes = numIndexes; R_BoundTriSurf( newTri ); staticModel->overlaysAdded++; // so we don't create an overlay on an overlay surface } }
/* ============= idRenderModelMD3::InstantiateDynamicModel ============= */ idRenderModel *idRenderModelMD3::InstantiateDynamicModel( const struct renderEntity_s *ent, const struct viewDef_s *view, idRenderModel *cachedModel ) { int i, j; float backlerp; int * triangles; float * texCoords; int indexes; int numVerts; md3Surface_t * surface; int frame, oldframe; idRenderModelStatic *staticModel; if ( cachedModel ) { delete cachedModel; cachedModel = NULL; } staticModel = new idRenderModelStatic; staticModel->bounds.Clear(); surface = (md3Surface_t *) ((byte *)md3 + md3->ofsSurfaces); // TODO: these need set by an entity frame = ent->shaderParms[SHADERPARM_MD3_FRAME]; // probably want to keep frames < 1000 or so oldframe = ent->shaderParms[SHADERPARM_MD3_LASTFRAME]; backlerp = ent->shaderParms[SHADERPARM_MD3_BACKLERP]; for( i = 0; i < md3->numSurfaces; i++ ) { srfTriangles_t *tri = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts( tri, surface->numVerts ); R_AllocStaticTriSurfIndexes( tri, surface->numTriangles * 3 ); tri->bounds.Clear(); modelSurface_t surf; surf.geometry = tri; md3Shader_t* shaders = (md3Shader_t *) ((byte *)surface + surface->ofsShaders); surf.shader = shaders->shader; LerpMeshVertexes( tri, surface, backlerp, frame, oldframe ); triangles = (int *) ((byte *)surface + surface->ofsTriangles); indexes = surface->numTriangles * 3; for (j = 0 ; j < indexes ; j++) { tri->indexes[j] = triangles[j]; } tri->numIndexes += indexes; texCoords = (float *) ((byte *)surface + surface->ofsSt); numVerts = surface->numVerts; for ( j = 0; j < numVerts; j++ ) { idDrawVert *stri = &tri->verts[j]; stri->st[0] = texCoords[j*2+0]; stri->st[1] = texCoords[j*2+1]; } R_BoundTriSurf( tri ); staticModel->AddSurface( surf ); staticModel->bounds.AddPoint( surf.geometry->bounds[0] ); staticModel->bounds.AddPoint( surf.geometry->bounds[1] ); // find the next surface surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd ); } return staticModel; }
/* =============== idRenderModelBeam::InstantiateDynamicModel =============== */ idRenderModel *idRenderModelBeam::InstantiateDynamicModel(const struct renderEntity_s *renderEntity, const struct viewDef_s *viewDef, idRenderModel *cachedModel) { idRenderModelStatic *staticModel; srfTriangles_t *tri; modelSurface_t surf; if (cachedModel) { delete cachedModel; cachedModel = NULL; } if (renderEntity == NULL || viewDef == NULL) { delete cachedModel; return NULL; } if (cachedModel != NULL) { assert(dynamic_cast<idRenderModelStatic *>(cachedModel) != NULL); assert(idStr::Icmp(cachedModel->Name(), beam_SnapshotName) == 0); staticModel = static_cast<idRenderModelStatic *>(cachedModel); surf = *staticModel->Surface(0); tri = surf.geometry; } else { staticModel = new idRenderModelStatic; staticModel->InitEmpty(beam_SnapshotName); tri = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts(tri, 4); R_AllocStaticTriSurfIndexes(tri, 6); tri->verts[0].Clear(); tri->verts[0].st[0] = 0; tri->verts[0].st[1] = 0; tri->verts[1].Clear(); tri->verts[1].st[0] = 0; tri->verts[1].st[1] = 1; tri->verts[2].Clear(); tri->verts[2].st[0] = 1; tri->verts[2].st[1] = 0; tri->verts[3].Clear(); tri->verts[3].st[0] = 1; tri->verts[3].st[1] = 1; tri->indexes[0] = 0; tri->indexes[1] = 2; tri->indexes[2] = 1; tri->indexes[3] = 2; tri->indexes[4] = 3; tri->indexes[5] = 1; tri->numVerts = 4; tri->numIndexes = 6; surf.geometry = tri; surf.id = 0; surf.shader = tr.defaultMaterial; staticModel->AddSurface(surf); } idVec3 target = *reinterpret_cast<const idVec3 *>(&renderEntity->shaderParms[SHADERPARM_BEAM_END_X]); // we need the view direction to project the minor axis of the tube // as the view changes idVec3 localView, localTarget; float modelMatrix[16]; R_AxisToModelMatrix(renderEntity->axis, renderEntity->origin, modelMatrix); R_GlobalPointToLocal(modelMatrix, viewDef->renderView.vieworg, localView); R_GlobalPointToLocal(modelMatrix, target, localTarget); idVec3 major = localTarget; idVec3 minor; idVec3 mid = 0.5f * localTarget; idVec3 dir = mid - localView; minor.Cross(major, dir); minor.Normalize(); if (renderEntity->shaderParms[SHADERPARM_BEAM_WIDTH] != 0.0f) { minor *= renderEntity->shaderParms[SHADERPARM_BEAM_WIDTH] * 0.5f; } int red = idMath::FtoiFast(renderEntity->shaderParms[SHADERPARM_RED] * 255.0f); int green = idMath::FtoiFast(renderEntity->shaderParms[SHADERPARM_GREEN] * 255.0f); int blue = idMath::FtoiFast(renderEntity->shaderParms[SHADERPARM_BLUE] * 255.0f); int alpha = idMath::FtoiFast(renderEntity->shaderParms[SHADERPARM_ALPHA] * 255.0f); tri->verts[0].xyz = minor; tri->verts[0].color[0] = red; tri->verts[0].color[1] = green; tri->verts[0].color[2] = blue; tri->verts[0].color[3] = alpha; tri->verts[1].xyz = -minor; tri->verts[1].color[0] = red; tri->verts[1].color[1] = green; tri->verts[1].color[2] = blue; tri->verts[1].color[3] = alpha; tri->verts[2].xyz = localTarget + minor; tri->verts[2].color[0] = red; tri->verts[2].color[1] = green; tri->verts[2].color[2] = blue; tri->verts[2].color[3] = alpha; tri->verts[3].xyz = localTarget - minor; tri->verts[3].color[0] = red; tri->verts[3].color[1] = green; tri->verts[3].color[2] = blue; tri->verts[3].color[3] = alpha; R_BoundTriSurf(tri); staticModel->bounds = tri->bounds; return staticModel; }
/* ================ idRenderWorldLocal::ParseModel ================ */ idRenderModel* idRenderWorldLocal::ParseModel( idLexer* src, const char* mapName, ID_TIME_T mapTimeStamp, idFile* fileOut ) { idToken token; src->ExpectTokenString( "{" ); // parse the name src->ExpectAnyToken( &token ); idRenderModel* model = renderModelManager->AllocModel(); model->InitEmpty( token ); if( fileOut != NULL ) { // write out the type so the binary reader knows what to instantiate fileOut->WriteString( "shadowmodel" ); fileOut->WriteString( token ); } int numSurfaces = src->ParseInt(); if( numSurfaces < 0 ) { src->Error( "R_ParseModel: bad numSurfaces" ); } for( int i = 0; i < numSurfaces; i++ ) { src->ExpectTokenString( "{" ); src->ExpectAnyToken( &token ); modelSurface_t surf; surf.shader = declManager->FindMaterial( token ); ( ( idMaterial* )surf.shader )->AddReference(); srfTriangles_t* tri = R_AllocStaticTriSurf(); surf.geometry = tri; tri->numVerts = src->ParseInt(); tri->numIndexes = src->ParseInt(); // parse the vertices idTempArray<float> verts( tri->numVerts * 8 ); for( int j = 0; j < tri->numVerts; j++ ) { src->Parse1DMatrix( 8, &verts[j * 8] ); } // parse the indices idTempArray<triIndex_t> indexes( tri->numIndexes ); for( int j = 0; j < tri->numIndexes; j++ ) { indexes[j] = src->ParseInt(); } #if 1 // find the island that each vertex belongs to idTempArray<int> vertIslands( tri->numVerts ); idTempArray<bool> trisVisited( tri->numIndexes ); vertIslands.Zero(); trisVisited.Zero(); int numIslands = 0; for( int j = 0; j < tri->numIndexes; j += 3 ) { if( trisVisited[j] ) { continue; } int islandNum = ++numIslands; vertIslands[indexes[j + 0]] = islandNum; vertIslands[indexes[j + 1]] = islandNum; vertIslands[indexes[j + 2]] = islandNum; trisVisited[j] = true; idList<int> queue; queue.Append( j ); for( int n = 0; n < queue.Num(); n++ ) { int t = queue[n]; for( int k = 0; k < tri->numIndexes; k += 3 ) { if( trisVisited[k] ) { continue; } bool connected = indexes[t + 0] == indexes[k + 0] || indexes[t + 0] == indexes[k + 1] || indexes[t + 0] == indexes[k + 2] || indexes[t + 1] == indexes[k + 0] || indexes[t + 1] == indexes[k + 1] || indexes[t + 1] == indexes[k + 2] || indexes[t + 2] == indexes[k + 0] || indexes[t + 2] == indexes[k + 1] || indexes[t + 2] == indexes[k + 2]; if( connected ) { vertIslands[indexes[k + 0]] = islandNum; vertIslands[indexes[k + 1]] = islandNum; vertIslands[indexes[k + 2]] = islandNum; trisVisited[k] = true; queue.Append( k ); } } } } // center the texture coordinates for each island for maximum 16-bit precision for( int j = 1; j <= numIslands; j++ ) { float minS = idMath::INFINITY; float minT = idMath::INFINITY; float maxS = -idMath::INFINITY; float maxT = -idMath::INFINITY; for( int k = 0; k < tri->numVerts; k++ ) { if( vertIslands[k] == j ) { minS = Min( minS, verts[k * 8 + 3] ); maxS = Max( maxS, verts[k * 8 + 3] ); minT = Min( minT, verts[k * 8 + 4] ); maxT = Max( maxT, verts[k * 8 + 4] ); } } const float averageS = idMath::Ftoi( ( minS + maxS ) * 0.5f ); const float averageT = idMath::Ftoi( ( minT + maxT ) * 0.5f ); for( int k = 0; k < tri->numVerts; k++ ) { if( vertIslands[k] == j ) { verts[k * 8 + 3] -= averageS; verts[k * 8 + 4] -= averageT; } } } #endif R_AllocStaticTriSurfVerts( tri, tri->numVerts ); for( int j = 0; j < tri->numVerts; j++ ) { tri->verts[j].xyz[0] = verts[j * 8 + 0]; tri->verts[j].xyz[1] = verts[j * 8 + 1]; tri->verts[j].xyz[2] = verts[j * 8 + 2]; tri->verts[j].SetTexCoord( verts[j * 8 + 3], verts[j * 8 + 4] ); tri->verts[j].SetNormal( verts[j * 8 + 5], verts[j * 8 + 6], verts[j * 8 + 7] ); } R_AllocStaticTriSurfIndexes( tri, tri->numIndexes ); for( int j = 0; j < tri->numIndexes; j++ ) { tri->indexes[j] = indexes[j]; } src->ExpectTokenString( "}" ); // add the completed surface to the model model->AddSurface( surf ); } src->ExpectTokenString( "}" ); model->FinishSurfaces(); if( fileOut != NULL && model->SupportsBinaryModel() && r_binaryLoadRenderModels.GetBool() ) { model->WriteBinaryModel( fileOut, &mapTimeStamp ); } return model; }
bool MeshLoaderB3D::ReadVrts() { const int max_tex_coords = 3; int flags, tex_coord_sets, tex_coord_set_size; flags = _file->ReadInt(); tex_coord_sets = _file->ReadInt(); tex_coord_set_size = _file->ReadInt(); if (tex_coord_sets >= max_tex_coords || tex_coord_set_size >= 4) // Something is wrong { Sys_Printf("tex_coord_sets or tex_coord_set_size too big"); return false; } //------ Allocate Memory, for speed -----------// int sizeOfVertex = 3; bool hasNormal = false; bool hasVertexColors = false; if (flags & 1) { hasNormal = true; sizeOfVertex += 3; } if (flags & 2) { sizeOfVertex += 4; hasVertexColors=true; } sizeOfVertex += tex_coord_sets*tex_coord_set_size; unsigned int size = _stack[_stack.size() - 1] - _file->Tell(); //106407 16800 unsigned int numVertex = size / sizeof(float) ; numVertex /= sizeOfVertex; srfTriangles_t* tri = _mesh->AllocGeo(); tri->numVerts = numVertex; R_AllocStaticTriSurfVerts(tri, numVertex); int idx = 0; while( CheckSize()) { float color[4]={1.0f, 1.0f, 1.0f, 1.0f}; tri->verts[idx].xyz = _file->ReadVec3(); if (flags & 1) { tri->verts[idx].normal = _file->ReadVec3(); } if (flags & 2) { color[0] = _file->ReadFloat(); color[1] = _file->ReadFloat(); color[2] = _file->ReadFloat(); color[3] = _file->ReadFloat(); } float u, v; for (int i = 0; i < tex_coord_sets; ++i) { //for (int j = 0; j < tex_coord_set_size; ++j) { u = _file->ReadFloat(); v = 1.0f - _file->ReadFloat(); } } tri->verts[idx].st = Vec2(u, v); idx++; } return true; }