bool FDerivedDataPhysXCooker::Build( TArray<uint8>& OutData ) { SCOPE_CYCLE_COUNTER(STAT_PhysXCooking); check(Cooker != NULL); FMemoryWriter Ar( OutData ); uint8 bLittleEndian = PLATFORM_LITTLE_ENDIAN; //TODO: We should pass the target platform into this function and write it. Then swap the endian on the writer so the reader doesn't have to do it at runtime int32 NumConvexElementsCooked = 0; int32 NumMirroredElementsCooked = 0; uint8 bTriMeshCooked = false; uint8 bMirroredTriMeshCooked = false; Ar << bLittleEndian; int64 CookedMeshInfoOffset = Ar.Tell(); Ar << NumConvexElementsCooked; Ar << NumMirroredElementsCooked; Ar << bTriMeshCooked; Ar << bMirroredTriMeshCooked; //TODO: we must save an id with convex and tri meshes for serialization. We must save this here and patch it up at runtime somehow // Cook convex meshes, but only if we are not forcing complex collision to be used as simple collision as well if( BodySetup && BodySetup->CollisionTraceFlag != CTF_UseComplexAsSimple && BodySetup->AggGeom.ConvexElems.Num() > 0 ) { if( bGenerateNormalMesh ) { NumConvexElementsCooked = BuildConvex( OutData, false ); } if ( bGenerateMirroredMesh ) { NumMirroredElementsCooked = BuildConvex( OutData, true ); } } // Cook trimeshes, but only if we do not frce simple collision to be used as complex collision as well bool bUsingAllTriData = BodySetup != NULL ? BodySetup->bMeshCollideAll : false; if( (BodySetup == NULL || BodySetup->CollisionTraceFlag != CTF_UseSimpleAsComplex) && ShouldGenerateTriMeshData(bUsingAllTriData) ) { if( bGenerateNormalMesh ) { bTriMeshCooked = (uint8)BuildTriMesh( OutData, false, bUsingAllTriData ); } if( bGenerateMirroredMesh && ShouldGenerateNegXTriMeshData() ) { bMirroredTriMeshCooked = (uint8)BuildTriMesh( OutData, true, bUsingAllTriData ); } } // Update info on what actually got cooked Ar.Seek( CookedMeshInfoOffset ); Ar << NumConvexElementsCooked; Ar << NumMirroredElementsCooked; Ar << bTriMeshCooked; Ar << bMirroredTriMeshCooked; // Whatever got cached return true. We want to cache 'failure' too. return true; }
int main( int argc, char *argv[] ) { char *in_brush_name; char *out_shape_name; char *out_glmesh_name; char *in_plane_name; char *in_texdef_name; char *in_texture_name; char *in_tm_name; char *path_name; hobj_t *brush_root; hmanager_t *plane_hm; hmanager_t *texdef_hm; hmanager_t *texture_hm; hobj_t *tm_root; hobj_t *meshtile_root; hobj_search_iterator_t brush_iter; hobj_search_iterator_t surf_iter; hobj_search_iterator_t surf2_iter; hobj_t *brush; hobj_t *surf; hobj_t *surf2; hobj_t *shape_root; hobj_t *shape; FILE *h; int num_total_tris; char tt[256]; gld = GLD_BeginSession( "xxx" ); GLD_StartRecord( gld ); GLD_BeginList( gld, "polys", "line" ); puts( "===== meshtile1 - create meshtiles from surfaces =====" ); SetCmdArgs( argc, argv ); if ( argc == 1 ) { puts( "usage:" ); puts( " -i : input bspbrush class" ); puts( " -o : output shape class" ); puts( " -obin : output glmesh binary" ); puts( " -pl : input plane class" ); puts( " -td : input texdef class" ); puts( " -tx : input texture class" ); puts( " -tm : input texture material class" ); puts( " -path : config path to ./shape_config and ./meshtiles" ); exit(-1); } in_brush_name = GetCmdOpt2( "-i" ); out_shape_name = GetCmdOpt2( "-o" ); out_glmesh_name = GetCmdOpt2( "-obin" ); in_plane_name = GetCmdOpt2( "-pl" ); in_texdef_name = GetCmdOpt2( "-td" ); in_texture_name = GetCmdOpt2( "-tx" ); in_tm_name = GetCmdOpt2( "-tm" ); path_name = GetCmdOpt2( "-path" ); if ( !in_brush_name ) Error( "no input bspbrush class\n" ); if ( !out_shape_name ) Error( "no output shape class\n" ); if ( !out_glmesh_name ) Error( "no output glmesh binary\n" ); if ( !in_plane_name ) Error( "no input plane class\n" ); if ( !in_texdef_name ) Error( "no input texdef class\n" ); if ( !in_texture_name ) Error( "no input texture class\n" ); if ( !in_tm_name ) Error( "no input texture material class\n" ); if ( !path_name ) Error( "no config path\n" ); brush_root = ReadClassFile( in_brush_name ); if ( !brush_root ) Error( "can't read bspbrush class\n" ); texdef_hm = NewHManagerLoadClass( in_texdef_name ); if ( !texdef_hm ) Error( "can't read texdef class\n" ); plane_hm = ReadPlaneClass( in_plane_name ); texture_hm = NewHManagerLoadClass( in_texture_name ); if ( !texture_hm ) Error( "can't read texture class\n" ); tm_root = ReadClassFile( in_tm_name ); if ( !tm_root ) Error( "can't read texture material class" ); sprintf( tt, "%s/shape_config/meshtile.hobj", path_name ); meshtile_root = ReadClassFile( tt ); if ( !meshtile_root ) Error( "can't read meshtile class ( %s )\n", tt ); shape_root = NewClass( "shapes", "meshtiles0" ); // // for all c5 brushes // num_total_tris = 0; InitClassSearchIterator( &brush_iter, brush_root, "bspbrush" ); for ( ; ( brush = SearchGetNextClass( &brush_iter ) ) ; ) { int b_contents; int num_surf; vec3d_t v; hobj_t *surf_poly_obj; polygon_t *surf_poly; EasyFindInt( &b_contents, brush, "content" ); if ( b_contents != 5 ) { continue; } // // for all surfaces // InitClassSearchIterator( &surf_iter, brush, "surface" ); for ( num_surf = 0; ( surf = SearchGetNextClass( &surf_iter ) ) ; num_surf++ ) { int s_contents; hobj_t *plane; hobj_t *texdef; hobj_t *texture; hobj_t *meshtile; hpair_t *pair; hpair_t *mat_pair; #if 1 EasyFindInt( &s_contents, surf, "content" ); if ( !(s_contents & 32) ) { // no substructur flag continue; } #endif // GenerateMeshtile( surf, plane_hm, texdef_hm, plane = EasyLookupClsref( surf, "plane", plane_hm ); texdef = EasyLookupClsref( surf, "texdef", texdef_hm ); texture = EasyLookupClsref( texdef, "texture", texture_hm ); pair = FindHPair( texture, "ident" ); if ( !pair ) Error( "missing key 'ident'\n" ); meshtile = FindClass( meshtile_root, pair->value ); if ( !meshtile ) { Error( "no meshtile defs for ident '%s'\n", pair->value ); } mat_pair = FindHPair( tm_root, pair->value ); { int i, j; vec3d_t norm; fp_t dist; hobj_t *plane2; vec3d_t norm2; fp_t dist2; fp_t rotate; vec2d_t shift; vec2d_t scale; vec2d_t vec0, vec1; fp_t u_size, v_size, height; u_list_t *raw_poly_list; u_list_t *base_tile_mesh; surf_poly_obj = FindClassType( surf, "polygon" ); surf_poly = CreatePolygonFromClass( surf_poly_obj ); EasyFindVec3d( norm, plane, "norm" ); EasyFindFloat( &dist, plane, "dist" ); EasyFindVec2d( shift, texdef, "shift" ); EasyFindVec2d( vec0, texdef, "vec0" ); EasyFindVec2d( vec1, texdef, "vec1" ); if ( vec0[0] == 0.0 && vec0[1] == 0.0 ) { vec0[0] = 1.0; } if ( vec1[0] == 0.0 && vec1[1] == 0.0 ) { vec1[1] = 1.0; } EasyFindVec2d( scale, texdef, "scale" ); EasyFindFloat( &rotate, texdef, "rotate" ); EasyFindFloat( &u_size, meshtile, "u_size" ); EasyFindFloat( &v_size, meshtile, "v_size" ); EasyFindFloat( &height, meshtile, "height" ); pair = FindHPair( meshtile, "raw_path" ); if ( !pair ) Error( "missing key 'raw_path'\n" ); sprintf( tt, "%s/%s", path_name, pair->value ); raw_poly_list = ReadPolygonList( tt ); if ( !raw_poly_list ) Error( "can't load raw polygons\n" ); printf( "%s: %d raw polygons/tile \n", pair->value, U_ListLength( raw_poly_list ) ); NormalizePolygonList( raw_poly_list ); { vec3d_t scl; scl[0] = u_size; scl[1] = v_size; scl[2] = height; ScalePolygonList( raw_poly_list, scl ); } { vec3d_t shf; shf[0] = 0.0; shf[1] = 0.0; shf[2] = -height; ShiftPolygonList( raw_poly_list, shf ); } base_tile_mesh = GenBaseTileMesh( surf_poly, norm, dist, vec0, vec1, shift, raw_poly_list, u_size, v_size, rotate, scale ); // // clip base by all surface planes // InitClassSearchIterator( &surf2_iter, brush, "surface" ); for ( ; ( surf2 = SearchGetNextClass( &surf2_iter ) ) ; ) { if ( surf2 == surf ) continue; EasyFindInt( &s_contents, surf2, "content" ); if ( !(s_contents & 32) ) { // no substructur flag continue; } plane2 = EasyLookupClsref( surf2, "plane", plane_hm ); EasyFindVec3d( norm2, plane2, "norm" ); EasyFindFloat( &dist2, plane2, "dist" ); ClipPolygonList( base_tile_mesh, norm2, dist2 ); } for ( i = 0; i < surf_poly->pointnum; i++ ) { j = (i+1==surf_poly->pointnum)?0:(i+1); // search surf, which the edge is on InitClassSearchIterator( &surf2_iter, brush, "surface" ); for ( ; ( surf2 = SearchGetNextClass( &surf2_iter ) ) ; ) { if ( surf2 == surf ) continue; plane2 = EasyLookupClsref( surf2, "plane", plane_hm ); EasyFindVec3d( norm2, plane2, "norm" ); EasyFindFloat( &dist2, plane2, "dist" ); if ( fabs(Vec3dDotProduct( surf_poly->p[i], norm2 )-dist2 ) < 0.1 && fabs(Vec3dDotProduct( surf_poly->p[j], norm2 )-dist2 ) < 0.1 ) { // that's the surf vec3d_t delta1, delta2; vec3d_t cross; Vec3dSub( delta1, surf_poly->p[j], surf_poly->p[i] ); Vec3dAdd( delta2, norm, norm2 ); Vec3dUnify( delta1 ); Vec3dUnify( delta2 ); Vec3dCrossProduct( cross, delta1, delta2 ); Vec3dUnify( cross ); dist2 = Vec3dInitPlane2( cross, surf_poly->p[i] ); ClipPolygonList( base_tile_mesh, cross, dist2 ); break; } } } // DrawPolygonList( base_tile_mesh ); // // build meshtile shape // plane = EasyLookupClsref( surf, "plane", plane_hm ); shape = BuildMeshTileShape( surf_poly_obj, plane, texdef, mat_pair, base_tile_mesh ); BuildTriMesh( shape, base_tile_mesh ); InsertClass( shape_root, shape ); num_total_tris += U_ListLength( base_tile_mesh ); } } } printf( " generated %d triangles\n", num_total_tris ); GLD_EndList( gld ); GLD_Update( gld ); GLD_Pause( gld ); GLD_EndSession( gld ); h = fopen( out_shape_name, "w" ); if ( !h ) Error( "can't write shape class\n" ); WriteClass( shape_root, h ); fclose( h ); h = fopen( out_glmesh_name, "w" ); if ( !h ) Error( "can't write glmesh binary\n" ); fwrite( glmesh_base, glmesh_ofs, 1, h ); fclose( h ); HManagerSaveID(); exit(0); }