indexing description: "A direct X format mesh loader" date: "$Date$" revision: "$Revision$" class EM3D_MESH_X_FACTORY inherit EM3D_MESH_FACTORY EM3D_X_PARSING_SUPPORT export {NONE} all end create make feature --Initialization load_mesh_internal( a_filename: STRING ) is -- Load all meshes from a .x file local file: PLAIN_TEXT_FILE name: STRING mesh: EM3D_MESH some_meshes: ARRAY[ EM_PAIR[ STRING, EM3D_MESH ] ] some_material_files: ARRAY[ STRING ] do scene_manager.material_factory.load_material( a_filename ) create file.make_open_read( a_filename ) -- Parse all the 'Mesh' tags create some_meshes.make (1, 0 ) from file.start until file.end_of_file loop file.read_word if file.last_string.substring (1,2).is_equal ( "//") then --nothing elseif file.last_string.is_equal ( "Mesh" ) then name := file.position.out file.read_word -- Read the Mesh name if not file.last_string.is_equal( "{" ) then name := file.last_string.twin file.read_word end mesh := parse_mesh( file ) add_mesh( mesh, a_filename+"#"+name ) some_meshes.force( create {EM_PAIR[ STRING, EM3D_MESH ]}.make ( a_filename+"#"+name, mesh), some_meshes.upper+1 ) end file.read_line end create some_material_files.make( 1, 1 ) some_material_files[ 1 ] := a_filename scene_manager.mesh_factory.store_mesh ( a_filename+".mesh", some_meshes, some_material_files) file.close end feature {NONE} -- Implementation parse_material_name( a_file: PLAIN_TEXT_FILE ): STRING is -- Parse the material name from a material block local pos: INTEGER do if a_file.item='{' then -- We have a named material (no inline) result := "" from a_file.forth until a_file.item='}' loop result.append_character( a_file.item ) a_file.forth end skip( a_file, '}' ) else -- We have a inline definition pos := a_file.position a_file.read_word result := a_file.position.out if a_file.last_string.is_equal ( "Material" ) then a_file.read_word if not a_file.last_string.is_equal( "{" ) then result := a_file.last_string.twin end a_file.go (pos) skip_block( a_file ) skip( a_file, ' ' ) end end end merge_indices( vertex_faces: ARRAY[ ARRAY[ INTEGER ] ]; normal_faces: ARRAY[ ARRAY[ INTEGER ] ]; i, j: INTEGER ): EM_VECTOR3I is -- Merge the indices do result.x := vertex_faces.item ( i ).item( j ) result.z := result.x if normal_faces/=void then result.y := normal_faces.item ( i ).item( j ) end end parse_mesh( a_file: PLAIN_TEXT_FILE ):EM3D_MESH is -- Parse the mesh part local vertices: ARRAY[ EM_VECTOR3D ] normals: ARRAY[ EM_VECTOR3D ] tex_coords: ARRAY[ EM_VECTOR2D ] vertex_faces: ARRAY[ ARRAY[ INTEGER ] ] normal_faces: ARRAY[ ARRAY[ INTEGER ] ] indices: ARRAY[ EM_VECTOR3I ] i, j, k: INTEGER v: EM_VECTOR3I materials: ARRAY[STRING] material_faces: ARRAY[ INTEGER ] material_name: STRING do -- Parse the Vertices vertices := parse_vector3d_array( a_file ) -- Parse the Faces/Indices vertex_faces := parse_face_array( a_file ) -- Parse optional things from a_file.read_word until a_file.last_string.is_equal ( "}" ) loop if a_file.last_string.substring(1,2).is_equal ( "//" ) then a_file.read_line elseif a_file.last_string.is_equal ( "MeshTextureCoords" ) then skip_one ( a_file, '{' ) tex_coords := parse_vector2d_array( a_file ) skip_one ( a_file, '}' ) elseif a_file.last_string.is_equal ( "MeshNormals" ) then skip_one ( a_file, '{' ) normals := parse_vector3d_array( a_file ) normal_faces := parse_face_array( a_file ) skip_one ( a_file, '}' ) elseif a_file.last_string.is_equal ( "MeshMaterialList" ) then skip_one ( a_file, '{' ) create materials.make (0, parse_integer( a_file )-1 ) material_faces := parse_integer_array( a_file ) from i := materials.lower until i>materials.upper loop materials[ i ] := a_file.name+"#"+parse_material_name( a_file ) i := i + 1 end skip_one ( a_file, '}' ) else skip_block( a_file ) end a_file.read_word end if materials=void or else materials.count=0 then -- Merge the indices create indices.make ( 0, -1 ) from i := vertex_faces.lower until i>vertex_faces.upper loop from j := vertex_faces.item(i).lower+2 until j > vertex_faces.item(i).upper loop v := merge_indices( vertex_faces, normal_faces, i, vertex_faces.item(i).lower ) indices.force ( v, indices.upper+1 ) v := merge_indices( vertex_faces, normal_faces, i, j-1 ) indices.force ( v, indices.upper+1 ) v := merge_indices( vertex_faces, normal_faces, i, j ) indices.force ( v, indices.upper+1 ) j := j + 1 end i := i + 1 end -- Create the mesh create result.make( scene_manager, tex_coords/=void ) result.add_sub_mesh( vertices, normals, tex_coords, indices, "" ) else create result.make( scene_manager, tex_coords/=void ) from k:=materials.lower until k>materials.upper loop create indices.make ( 0, -1 ) from i:=material_faces.lower until i>material_faces.upper loop if material_faces.item ( i )=k then from j := vertex_faces.item(i).lower+2 until j > vertex_faces.item(i).upper loop v := merge_indices( vertex_faces, normal_faces, i, vertex_faces.item(i).lower ) indices.force ( v, indices.upper+1 ) v := merge_indices( vertex_faces, normal_faces, i, j-1 ) indices.force ( v, indices.upper+1 ) v := merge_indices( vertex_faces, normal_faces, i, j ) indices.force ( v, indices.upper+1 ) j := j + 1 end end i := i + 1 end -- Create the submesh with material k result.add_sub_mesh( vertices, normals, tex_coords, indices, materials[ k ] ) k := k + 1 end end end invariant invariant_clause: True -- Your invariant here end