# Batches
cxr_view_lines = None
cxr_view_mesh = None
+cxr_mdl_mesh = None
cxr_jobs_batch = None
cxr_jobs_inf = []
cxr_error_inf = None
# Shaders
cxr_view_shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR')
+
cxr_ui_shader = gpu.types.GPUShader("""
uniform mat4 ModelViewProjectionMatrix;
uniform float scale;
}
""")
+cxr_mdl_shader = gpu.types.GPUShader("""
+uniform mat4 modelMatrix;
+uniform mat4 viewProjectionMatrix;
+
+in vec3 aPos;
+in vec3 aNormal;
+
+out vec3 lPos;
+out vec3 lNormal;
+
+void main()
+{
+ vec4 pWorldPos = modelMatrix * vec4(aPos, 1.0);
+ vec3 worldPos = pWorldPos.xyz;
+
+ gl_Position = viewProjectionMatrix * pWorldPos;
+ lNormal = aNormal; //mat3(transpose(inverse(modelMatrix))) * aNormal;
+ lPos = worldPos;
+}
+""","""
+
+uniform vec4 colour;
+uniform vec3 testLightDir;
+
+in vec3 lNormal;
+in vec3 lPos;
+
+out vec4 FragColor;
+
+float SoftenCosineTerm( float flDot )
+{
+ return ( flDot + ( flDot * flDot ) ) * 0.5;
+}
+
+vec3 DiffuseTerm( vec3 worldNormal, vec3 lightDir )
+{
+ float fResult = 0.0;
+ float NDotL = dot( worldNormal, lightDir );
+
+ fResult = clamp( NDotL, 0.0, 1.0 );
+ fResult = SoftenCosineTerm( fResult );
+
+ vec3 fOut = vec3( fResult, fResult, fResult );
+ return fOut;
+}
+
+vec3 PixelShaderDoLightingLinear( vec3 worldPos, vec3 worldNormal )
+{
+ vec3 linearColor = vec3(0.0,0.0,0.0);
+ linearColor += DiffuseTerm( worldNormal, testLightDir );
+
+ return linearColor;
+}
+
+vec3 LinearToGamma( vec3 f3linear )
+{
+ return pow( f3linear, vec3(1.0 / 2.2) );
+}
+
+void main()
+{
+ vec3 tangentSpaceNormal = vec3( 0.0, 0.0, 1.0 );
+ vec4 normalTexel = vec4(1.0,1.0,1.0,1.0);
+ vec4 baseColor = colour;
+
+ //normalTexel = tex2D( BumpmapSampler, i.detailOrBumpTexCoord );
+ //tangentSpaceNormal = 2.0 * normalTexel - 1.0;
+
+ vec3 diffuseLighting = vec3( 1.0, 1.0, 1.0 );
+
+ vec3 staticLightingColor = vec3( 0.0, 0.0, 0.0 );
+ diffuseLighting = PixelShaderDoLightingLinear( lPos, lNormal );
+
+ // multiply by .5 since we want a 50% (in gamma space) reflective surface)
+ diffuseLighting *= pow( 0.5, 2.2 );
+
+ vec3 result = diffuseLighting * baseColor.xyz;
+
+ FragColor = vec4( LinearToGamma(result), 1.0 );
+}
+""")
+
# Render functions
#
def cxr_ui(_,context):
CXR_COMPILER_CHAIN.WAIT_REDRAW = False
def cxr_draw():
- global cxr_view_shader, cxr_view_mesh, cxr_view_lines
+ global cxr_view_shader, cxr_view_mesh, cxr_view_lines, cxr_mdl_shader,\
+ cxr_mdl_mesh
cxr_view_shader.bind()
if cxr_view_lines != None:
cxr_view_lines.draw( cxr_view_shader )
- gpu.state.depth_test_set('LESS_EQUAL')
- gpu.state.blend_set('ADDITIVE')
if cxr_view_mesh != None:
+ gpu.state.depth_test_set('LESS_EQUAL')
+ gpu.state.blend_set('ADDITIVE')
+
cxr_view_mesh.draw( cxr_view_shader )
+ if cxr_mdl_mesh != None:
+ gpu.state.depth_mask_set(True)
+ gpu.state.depth_test_set('LESS_EQUAL')
+ gpu.state.face_culling_set('FRONT')
+ gpu.state.blend_set('NONE')
+ cxr_mdl_shader.bind()
+ cxr_mdl_shader.uniform_float('colour',(0.5,0.5,0.5,1.0))
+ cxr_mdl_shader.uniform_float("viewProjectionMatrix", \
+ bpy.context.region_data.perspective_matrix)
+
+ testmdl = bpy.context.scene.objects['target']
+ light = bpy.context.scene.objects['point']
+ relative = light.location - testmdl.location
+ relative.normalize()
+
+ cxr_mdl_shader.uniform_float("modelMatrix", testmdl.matrix_world)
+ cxr_mdl_shader.uniform_float("testLightDir", relative)
+
+
+ cxr_mdl_mesh.draw( cxr_mdl_shader )
+
def cxr_jobs_update_graph(jobs):
global cxr_jobs_batch, cxr_ui_shader, cxr_jobs_inf
class cxr_tri_mesh(Structure):
_fields_ = [("vertices",POINTER(c_double *3)),
+ ("normals",POINTER(c_double *3)),
+ ("uvs",POINTER(c_double *2)),
("colours",POINTER(c_double *4)),
("indices",POINTER(c_int32)),
("indices_count",c_int32),
# Other
libcxr_lightpatch_bsp = extern( "cxr_lightpatch_bsp", [c_char_p], None )
+# Binary file formats and FS
+libcxr_fs_set_gameinfo = extern( "cxr_fs_set_gameinfo", [c_char_p], c_int32 )
+libcxr_fs_exit = extern( "cxr_fs_exit", [], None )
+libcxr_fs_get = extern( "cxr_fs_get", [c_char_p], c_char_p )
+libcxr_load_mdl = extern( "cxr_load_mdl", [c_char_p], POINTER(cxr_tri_mesh) )
+
libcxr_funcs = [ libcxr_decompose, libcxr_free_world, libcxr_begin_vmf, \
libcxr_vmf_begin_entities, libcxr_push_world_vmf, \
libcxr_end_vmf, libcxr_vdf_open, libcxr_vdf_close, \
libcxr_vdf_put, libcxr_vdf_node, libcxr_vdf_edon,
libcxr_vdf_kv, libcxr_lightpatch_bsp, libcxr_write_test_data,\
- libcxr_world_preview, libcxr_free_tri_mesh ]
+ libcxr_world_preview, libcxr_free_tri_mesh, \
+ libcxr_fs_set_gameinfo, libcxr_fs_exit, libcxr_fs_get, \
+ libcxr_load_mdl ]
# Callbacks
-
def libcxr_log_callback(logStr):
print( F"{logStr.decode('utf-8')}",end='' )
err = c_int32(0)
world = libcxr_decompose.call( mesh_src, pointer(err) )
- if world == None:
+ if not world:
cxr_view_mesh = None
cxr_batch_lines()
libcxr_write_test_data.call( pointer(mesh_src) )
return {'FINISHED'}
+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'}
+
+class CXR_LOAD_MODEL_OPERATOR(bpy.types.Operator):
+ bl_idname="convexer.model_load"
+ bl_label="Load model"
+
+ def execute(_,context):
+ global cxr_mdl_mesh, cxr_mdl_shader
+
+ mdlpath = bpy.context.scene.cxr_data.dev_mdl.encode('utf-8')
+ pmesh = libcxr_load_mdl.call( mdlpath )
+
+ if not pmesh:
+ print( "Failed to load model" )
+ return {'FINISHED'}
+
+ mesh = pmesh[0]
+
+ #TODO: remove code dupe
+ vertices = mesh.vertices[:mesh.vertex_count]
+ vertices = [(_[0],_[1],_[2]) for _ in vertices]
+
+ normals = mesh.normals[:mesh.vertex_count]
+ normals = [(_[0],_[1],_[2]) for _ in normals]
+
+ indices = mesh.indices[:mesh.indices_count]
+ indices = [ (indices[i*3+0],indices[i*3+1],indices[i*3+2]) \
+ for i in range(int(mesh.indices_count/3)) ]
+
+ cxr_mdl_mesh = batch_for_shader(
+ cxr_mdl_shader, 'TRIS',
+ { "aPos": vertices, "aNormal": normals },
+ indices = indices,
+ )
+
+ libcxr_free_tri_mesh.call( pmesh )
+
+ scene_redraw()
+ return {'FINISHED'}
+
# UI: Preview how the brushes will looks in 3D view
#
class CXR_PREVIEW_OPERATOR(bpy.types.Operator):
row.scale_y = 2
row.operator("convexer.reset")
+ layout.prop( bpy.context.scene.cxr_data, "dev_mdl" )
+ layout.operator( "convexer.model_load" )
+
# Main scene properties interface, where all the settings go
#
class CXR_INTERFACE(bpy.types.Panel):
if CXR_GNU_LINUX==1:
_.layout.operator("convexer.reload")
_.layout.operator("convexer.dev_test")
+ _.layout.operator("convexer.fs_init")
_.layout.operator("convexer.hash_reset")
settings = context.scene.cxr_data
comp_compile: bpy.props.BoolProperty(name="Compile",default=True)
comp_pack: bpy.props.BoolProperty(name="Pack",default=False)
+ dev_mdl: bpy.props.StringProperty(name="Model",default="")
+
classes = [ CXR_RELOAD, CXR_DEV_OPERATOR, CXR_INTERFACE, \
CXR_MATERIAL_PANEL, CXR_IMAGE_SETTINGS,\
CXR_MODEL_SETTINGS, CXR_ENTITY_SETTINGS, CXR_CUBEMAP_SETTINGS,\
CXR_LIGHT_SETTINGS, CXR_SCENE_SETTINGS, CXR_DETECT_COMPILERS,\
CXR_ENTITY_PANEL, CXR_LIGHT_PANEL, CXR_PREVIEW_OPERATOR,\
CXR_VIEW3D, CXR_COMPILER_CHAIN, CXR_RESET_HASHES,\
- CXR_COMPILE_MATERIAL, CXR_COLLECTION_PANEL, CXR_RESET ]
+ CXR_COMPILE_MATERIAL, CXR_COLLECTION_PANEL, CXR_RESET, \
+ CXR_INIT_FS_OPERATOR, CXR_LOAD_MODEL_OPERATOR ]
vmt_param_dynamic_class = None