+class CXR_INIT_FS_OPERATOR(bpy.types.Operator):
+ bl_idname="convexer.fs_init"
+ bl_label="Initialize filesystem"
+
+ def execute(_,context):
+ gameinfo = F'{bpy.context.scene.cxr_data.subdir}/gameinfo.txt'
+
+ if libcxr_fs_set_gameinfo.call( gameinfo.encode('utf-8') ) == 1:
+ print( "File system ready" )
+ else:
+ print( "File system failed to initialize" )
+
+ return {'FINISHED'}
+
+def cxr_load_texture( path, is_normal ):
+ global cxr_asset_lib
+
+ if path in cxr_asset_lib['textures']:
+ return cxr_asset_lib['textures'][path]
+
+ print( F"cxr_load_texture( '{path}' )" )
+
+ pvtf = libcxr_fs_get.call( path.encode('utf-8'), 0 )
+
+ if not pvtf:
+ print( "vtf failed to load" )
+ cxr_asset_lib['textures'][path] = None
+ return None
+
+ x = c_int32(0)
+ y = c_int32(0)
+
+ img_data = libnbvtf_read.call( pvtf, pointer(x), pointer(y), \
+ c_int32(is_normal) )
+
+ x = x.value
+ y = y.value
+
+ if not img_data:
+ print( "vtf failed to decode" )
+ libcxr_fs_free.call( pvtf )
+ cxr_asset_lib['textures'][path] = None
+ return None
+
+ img_buf = gpu.types.Buffer('FLOAT', [x*y*4], [_/255.0 for _ in img_data[:x*y*4]])
+
+ tex = cxr_asset_lib['textures'][path] = \
+ gpu.types.GPUTexture( size=(x,y), layers=0, is_cubemap=False,\
+ format='RGBA8', data=img_buf )
+
+ libnbvtf_free.call( img_data )
+ libcxr_fs_free.call( pvtf )
+ return tex
+
+def cxr_load_material( path ):
+ global cxr_asset_lib
+
+ if path in cxr_asset_lib['materials']:
+ return cxr_asset_lib['materials'][path]
+
+ print( F"cxr_load_material( '{path}' )" )
+
+ pvmt = libcxr_valve_load_material.call( path.encode( 'utf-8') )
+
+ if not pvmt:
+ cxr_asset_lib['materials'][path] = None
+ return None
+
+ vmt = pvmt[0]
+ mat = cxr_asset_lib['materials'][path] = {}
+
+ if vmt.basetexture:
+ mat['basetexture'] = cxr_load_texture( vmt.basetexture.decode('utf-8'), 0)
+
+ if vmt.bumpmap:
+ mat['bumpmap'] = cxr_load_texture( vmt.bumpmap.decode('utf-8'), 1)
+
+ libcxr_valve_free_material.call( pvmt )
+
+ return mat
+
+def cxr_load_model_full( path ):
+ global cxr_asset_lib, cxr_mdl_shader
+
+ if path in cxr_asset_lib['models']:
+ return cxr_asset_lib['models'][path]
+
+ pmdl = libcxr_valve_load_model.call( path.encode( 'utf-8' ) )
+
+ print( F"cxr_load_model_full( '{path}' )" )
+
+ if not pmdl:
+ print( "Failed to load model" )
+ cxr_asset_lib['models'][path] = None
+ return None
+
+ mdl = pmdl[0]
+
+ # Convert our lovely interleaved vertex stream into, whatever this is.
+ positions = [ (mdl.vertex_data[i*8+0], \
+ mdl.vertex_data[i*8+1], \
+ mdl.vertex_data[i*8+2]) for i in range(mdl.vertex_count) ]
+
+ normals = [ (mdl.vertex_data[i*8+3], \
+ mdl.vertex_data[i*8+4], \
+ mdl.vertex_data[i*8+5]) for i in range(mdl.vertex_count) ]
+
+ uvs = [ (mdl.vertex_data[i*8+6], \
+ mdl.vertex_data[i*8+7]) for i in range(mdl.vertex_count) ]
+
+ fmt = gpu.types.GPUVertFormat()
+ fmt.attr_add(id="aPos", comp_type='F32', len=3, fetch_mode='FLOAT')
+ fmt.attr_add(id="aNormal", comp_type='F32', len=3, fetch_mode='FLOAT')
+ fmt.attr_add(id="aUv", comp_type='F32', len=2, fetch_mode='FLOAT')
+
+ vbo = gpu.types.GPUVertBuf(len=mdl.vertex_count, format=fmt)
+ vbo.attr_fill(id="aPos", data=positions )
+ vbo.attr_fill(id="aNormal", data=normals )
+ vbo.attr_fill(id="aUv", data=uvs )
+
+ batches = cxr_asset_lib['models'][path] = []
+
+ for p in range(mdl.part_count):
+ part = mdl.parts[p]
+ indices = mdl.indices[part.ibstart:part.ibstart+part.ibcount]
+ indices = [ (indices[i*3+0],indices[i*3+1],indices[i*3+2]) \
+ for i in range(part.ibcount//3) ]
+
+ ibo = gpu.types.GPUIndexBuf( type='TRIS', seq=indices )
+
+ batch = gpu.types.GPUBatch( type='TRIS', buf=vbo, elem=ibo )
+ batch.program_set( cxr_mdl_shader )
+
+ mat_str = cast( mdl.materials[ part.material ], c_char_p )
+ batches += [( cxr_load_material( mat_str.value.decode('utf-8') ), batch )]
+
+ libcxr_valve_free_model.call( pmdl )
+
+ return batches
+
+class CXR_LOAD_MODEL_OPERATOR(bpy.types.Operator):
+ bl_idname="convexer.model_load"
+ bl_label="Load model"
+
+ def execute(_,context):
+ global cxr_test_mdl, cxr_mdl_shader, cxr_asset_lib
+
+ cxr_test_mdl = cxr_load_model_full( bpy.context.scene.cxr_data.dev_mdl )
+
+ scene_redraw()
+ return {'FINISHED'}
+