indexing description: "Element array's are maily used to pass integers to OpenGL" author: "" date: "$Date$" revision: "$Revision$" class EM3D_VBO_ELEMENT_ARRAY inherit TO_SPECIAL[ INTEGER ] undefine default_create redefine make_area, put end EMGL_VERTEX_BUFFER_OBJECT export {ANY} bind, unbind, is_vbo_supported {NONE} all undefine is_equal, copy end PLATFORM export {NONE} all undefine is_equal, copy, default_create end create make convert to_c_pointer: {POINTER} feature {NONE} --Initialization make( a_size, vbo_dynamic: INTEGER ) is -- Make a new VertexbufferObject Array haybrid -- vbo_dynamic: -- 0 means static (you specify it once and use it m-times) -- 1 means dynamic (you specify it n-times and use it m-times) -- 2 means stream (you specify it n-times and use it once) require valid_dynamic: vbo_dynamic>=0 and vbo_dynamic<=2 do inspect vbo_dynamic when 0 then internal_usage := em_gl_static_draw when 1 then internal_usage := em_gl_dynamic_draw when 2 then internal_usage := em_gl_stream_draw end make_area( a_size ) end make_area( n: INTEGER ) is -- Make a new VertexBufferObject Array hybrid do Precursor( n ) if is_vbo_supported then default_create create changelog.make( n ) bind data ( n*data_size, to_c_pointer, internal_usage) unbind end count := n changed := true end feature {NONE} --Status capacity: INTEGER target: INTEGER is once result := em_gl_element_array_buffer_arb end changelog: DS_ARRAYED_LIST[ INTEGER ] list_sorter: DS_SORTER[ INTEGER ] is once create {DS_QUICK_SORTER[ INTEGER ]}result.make( create {DS_COMPARABLE_COMPARATOR[ INTEGER ]}.make) end data_size: INTEGER is once result:=integer_bits//8 end internal_usage : INTEGER internal_map: EWG_MANAGED_POINTER save_unmap is -- Unmap with a rescue require vbo_bound: is_bound do unmap rescue data( count*data_size, to_c_pointer, internal_usage) end feature --Status frozen static: INTEGER is 0 frozen dynamic: INTEGER is 1 frozen stream: INTEGER is 2 use_map: BOOLEAN set_use_map( a_value: like use_map ) is -- Shall we use OpenGL's map/unmap(or SubCopy)? do use_map := a_value end changed: BOOLEAN lower: INTEGER is 0 upper: INTEGER is -- The upper element do result := count-1 end count: INTEGER feature --Commands put (v, i: INTEGER) is -- Put an item into the VBO array do changed := true Precursor( v, i ) if is_vbo_supported then if use_map then if internal_map=void then bind create internal_map.make_shared ( map( em_gl_write_only ), size) unbind end internal_map.put_integer( v, i ) else changelog.force_last( i ) end end end force( v, i: INTEGER) is -- Replace `i'-th entry, if in index interval, by `v'. -- Resize if i is not a valid_index require i_is_positive: i>=0 do if i >= count then resize( i+1 ) end put( v, i ) end update is -- Update the VBO local i: DS_ARRAYED_LIST_CURSOR[ INTEGER ] start_pos, last_pos: INTEGER do if changed and is_vbo_supported then bind if use_map then if internal_map /= void then internal_map := void save_unmap end else changelog.sort ( list_sorter ) -- Pass it segment wise to opengl -- TODO: Improve the segment finding from i := changelog.new_cursor; i.start until i.after loop from start_pos := i.item last_pos := i.item -- Adjust this value for better results until i.after or i.item-last_pos>1 loop last_pos := i.item i.forth end sub_data ( start_pos*data_size, (last_pos-start_pos+1)*data_size, to_c_pointer ) end changelog.wipe_out end unbind end changed := false end resize( a_new_size: INTEGER ) is -- Resize the VBO as well require a_new_size_greater_than_count: a_new_size > count do if capacity < a_new_size then -- Its much faster than just always adding a certain amount! if capacity = 0 then capacity := 1 end from until capacity >= a_new_size loop capacity := capacity*2 end area := area.aliased_resized_area( capacity ) count := a_new_size end if is_vbo_supported then bind data ( a_new_size*data_size, to_c_pointer, internal_usage) unbind end end to_c: ANY is -- Convert to C do result := area end to_c_pointer: POINTER is -- Convert to c pointer do result := $area end feature -- File storage store_in_file( a_file: RAW_FILE ) is -- Store the VBO in a_file do a_file.put_integer ( count ) a_file.put_data ( to_c_pointer, count*data_size ) end load_from_file( a_file: RAW_FILE ) is -- Load the VBO from a_file do a_file.read_integer resize( a_file.last_integer ) a_file.read_data ( to_c_pointer, count*data_size ) -- Push it into the vbo if is_vbo_supported then bind data ( count*data_size, to_c_pointer, internal_usage) unbind end end end