indexing description: "[ A mesh object, with fast save and load. There is definitely no support for glIndexPointer ]" date: "$Date$" revision: "$Revision$" class EM3D_MESH inherit EMGL_ARRAY_RENDERER export {NONE} all undefine is_equal, copy end EMGL_BASIC_RENDERER export {NONE} all undefine is_equal, copy end EMGL_SETTINGS export {NONE} all undefine is_equal, copy end EM3D_RESOURCE export {NONE} all undefine is_equal, copy end EM3D_ENTITY rename make as make_entity redefine render_opengl end create {EM3D_MESH_FACTORY} make feature {NONE} --Initialization make ( a_scene_manager: EM3D_SCENE_MANAGER; has_tex_coords: BOOLEAN ) is -- Make the mesh do make_entity( a_scene_manager ) create sub_meshes.make(1,0) create vertices.make ( 0 , vertex_dynamic) create normals.make ( 0 , vertex_dynamic) if has_tex_coords then create tex_coords.make ( 0 , vertex_dynamic) end create display_list end feature {EM3D_MESH_FACTORY} add_sub_mesh(some_vertices, some_normals: ARRAY[ EM_VECTOR3D ]; some_tex_coords: ARRAY[ EM_VECTOR2D ]; some_indices: ARRAY[ EM_VECTOR3I ]; a_material: STRING ) is -- Create the sub_mesh from where all the id's are different for all array's -- The points are just copied, no optimization -- some_indices are build up as VERTEX/NORMAL/TEX_COORD triple require valid_vertices: some_vertices /= void valid_indices: some_indices /= void valid_tex_coords: tex_coords /= void implies some_tex_coords /= void local i,j: INTEGER p: EM_VECTOR3I indices: EM3D_VBO_ELEMENT_ARRAY tmp_normals: ARRAY[ EM_VECTOR3D ] v1,v2,v3,n : EM_VECTOR3D do create tmp_normals.make ( some_indices.lower, some_indices.upper) if some_normals=void then -- TODO: This doesn't always look quite optimal -- Calculate the normals -- Flat shading create tmp_normals.make( some_vertices.lower, some_vertices.upper ) from i:=some_indices.lower until i>some_indices.upper loop p := some_indices[i] v1 := some_vertices[p[1]] p := some_indices[i+1] v2 := some_vertices[p[1]] p := some_indices[i+2] v3 := some_vertices[p[1]] v1.sub ( v3 ) v2.sub ( v3 ) n := v1.cross_product ( v2 ) n.normalize p := some_indices[i] tmp_normals.force( tmp_normals.item(p[1])+n, p[1] ) p := some_indices[i+1] tmp_normals.force( tmp_normals.item(p[1])+n, p[1] ) p := some_indices[i+2] tmp_normals.force( tmp_normals.item(p[1])+n, p[1] ) i := i + 3 end -- Smooth Shading from i:=some_indices.lower; j:=vertices.upper+1 until i>some_indices.upper loop normals.force( tmp_normals[ some_indices.item(i)[1] ].normalized, j ) j := j + 1 i := i + 1 end else from i:=some_indices.lower; j:=vertices.upper+1 until i>some_indices.upper loop normals.force( some_normals[ some_indices.item(i)[2] ], j ) j := j + 1 i := i + 1 end end create indices.make ( some_indices.count, index_dynamic) from i:=some_indices.lower; j:=vertices.upper+1 until i>some_indices.upper loop p := some_indices[i] vertices.force ( some_vertices[p[1]], j ) if tex_coords /= void then tex_coords.force( some_tex_coords[p[3]], j ) end indices[ i-some_indices.lower ] := j j := j + 1 i := i + 1 end if indices.count>0 then sub_meshes.force ( create {EM3D_SUB_MESH}.make ( scene_manager, Current, indices, a_material ), sub_meshes.upper+1 ) end end feature {NONE} -- Status vertex_dynamic: INTEGER is once result := {EM3D_VBO_ARRAY_F[ EM_VECTOR3F ]}.static end index_dynamic: INTEGER is once result := {EM3D_VBO_ARRAY_F[ EM_VECTOR3F ]}.static end display_list: EMGL_DISPLAY_LIST feature -- Access vertices: EM3D_VBO_ARRAY_F[ EM_VECTOR3F ] normals: EM3D_VBO_ARRAY_F[ EM_VECTOR3F ] tex_coords: EM3D_VBO_ARRAY_F[ EM_VECTOR2F ] sub_meshes: ARRAY[ EM3D_SUB_MESH ] feature -- Draw update is -- Update the array's local i: INTEGER do vertices.update if normals/=void then normals.update end if tex_coords/=void then tex_coords.update end from i:=sub_meshes.lower until i>sub_meshes.upper loop sub_meshes[i].update i:=i+1 end end changed: BOOLEAN is -- Has the mesh changed? local i: INTEGER do result := vertices.changed if not result and normals/=void then result := normals.changed end if not result and tex_coords/=void then result := tex_coords.changed end from i:=sub_meshes.lower until i>sub_meshes.upper or result loop result := result or sub_meshes[i].changed i:=i+1 end end render_opengl is -- Draw the array to OpenGL local i: INTEGER do if vertices.is_vbo_supported then update emgl_enable_client_state ( em_gl_vertex_array ) vertices.bind emgl_vertex_pointer (3, em_gl_float, 0, default_pointer ) -- vertices.unbind if normals /= void then emgl_enable_client_state ( em_gl_normal_array ) normals.bind emgl_normal_pointer (em_gl_float, 0, default_pointer ) -- normals.unbind end if tex_coords/=void then emgl_enable_client_state ( em_gl_texture_coord_array ) tex_coords.bind emgl_tex_coord_pointer (2, em_gl_float, 0, default_pointer ) -- tex_coords.unbind end from i:=sub_meshes.lower until i>sub_meshes.upper loop sub_meshes[i].render_opengl i := i + 1 end emgl_disable_client_state ( em_gl_vertex_array ) emgl_disable_client_state ( em_gl_normal_array ) emgl_disable_client_state ( em_gl_texture_coord_array ) else if changed then update display_list.new_list_compile_and_execute emgl_enable_client_state ( em_gl_vertex_array ) emgl_vertex_pointer (3, em_gl_float, 0, vertices ) if normals /= void then emgl_enable_client_state ( em_gl_normal_array ) emgl_normal_pointer (em_gl_float, 0, normals ) end if tex_coords /= void then emgl_enable_client_state ( em_gl_texture_coord_array ) emgl_tex_coord_pointer (2, em_gl_float, 0, tex_coords ) end from i:=sub_meshes.lower until i>sub_meshes.upper loop sub_meshes[i].render_opengl i := i + 1 end emgl_disable_client_state ( em_gl_vertex_array ) emgl_disable_client_state ( em_gl_normal_array ) emgl_disable_client_state ( em_gl_texture_coord_array ) display_list.end_list else display_list.call_list end end end feature -- File storage store_in_file( a_file: RAW_FILE ) is -- Store the VBO in a_file local i: INTEGER do vertices.store_in_file( a_file ) normals.store_in_file( a_file ) a_file.put_integer ( (tex_coords /= void).to_integer ) if tex_coords /= void then tex_coords.store_in_file( a_file ) end a_file.put_integer ( sub_meshes.count ) from i:=sub_meshes.lower until i>sub_meshes.upper loop sub_meshes[i].store_in_file( a_file ) i := i + 1 end end load_from_file( a_file: RAW_FILE ) is -- Load the VBO from a_file local i: INTEGER do vertices.load_from_file( a_file ) normals.load_from_file( a_file ) a_file.read_integer if a_file.last_integer>0 then if tex_coords=void then create tex_coords.make ( 0 , vertex_dynamic) end tex_coords.load_from_file( a_file ) end a_file.read_integer sub_meshes.resize (1, a_file.last_integer) from i:=sub_meshes.lower until i>sub_meshes.upper loop sub_meshes[i] := create {EM3D_SUB_MESH}.make ( scene_manager, current, create {EM3D_VBO_ELEMENT_ARRAY}.make (0, index_dynamic), "" ) sub_meshes[i].load_from_file( a_file ) i := i + 1 end end end