X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=cxr%2Fcxr.h;h=644c8ed83e39381e88ceb5c3beeb4772e29f3be3;hb=0d0b6bf37c8a9c4494071973103a89b4aa82574a;hp=0af9b8c780fa68fd0b72755e5223b9ca7710c192;hpb=45f7d303989810f9bcedfd4a4fd6db49a5baba4e;p=convexer.git diff --git a/cxr/cxr.h b/cxr/cxr.h index 0af9b8c..644c8ed 100644 --- a/cxr/cxr.h +++ b/cxr/cxr.h @@ -1,11 +1,13 @@ /* - CONVEXER v0.9 + CONVEXER v0.95 A GNU/Linux-first Source1 Hammer replacement built with Blender, for mapmakers Copyright (C) 2022 Harry Godden (hgn) +LICENSE: GPLv3.0, please see COPYING and LICENSE for more information + Features: - Brush decomposition into convex pieces for well defined geometry - Freely form displacements without limits @@ -13,7 +15,8 @@ - Compile models and model groups easily - It runs at an ok speed! - Light patch BSP files; remove unwanted realtime effects - - Fastest VTF compressor (thanks to Richgel999 and stb) + - Bestest VTF compressor (thanks to Richgel999 and stb) + - Pack content automatically Program structure: @@ -45,7 +48,6 @@ IMPLEMENTATION */ -#define CXR_API #define CXR_EPSILON 0.001 #define CXR_PLANE_SIMILARITY_MAX 0.998 #define CXR_BIG_NUMBER 1e300 @@ -57,31 +59,17 @@ #include #include -#include -#include #include #include -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef int64_t i64; - -typedef unsigned int uint; - -typedef double v2f[2]; -typedef double v3f[3]; -typedef double v4f[4]; -typedef v3f m3x3f[3]; -typedef v3f m4x3f[4]; -typedef v3f boxf[2]; - +#include "cxr_types.h" #include "cxr_math.h" #include "cxr_mem.h" +#include "cxr_log.h" + +#ifdef CXR_VALVE_BIN + #include "cxr_valve_bin.h" +#endif typedef struct cxr_world cxr_world; typedef struct cxr_solid cxr_solid; @@ -98,6 +86,7 @@ typedef struct cxr_tri_mesh cxr_tri_mesh; #ifdef CXR_VALVE_MAP_FILE typedef struct cxr_vdf cxr_vdf; typedef struct cxr_texinfo cxr_texinfo; + typedef struct cxr_visgroup cxr_visgroup; typedef struct cxr_vmf_context cxr_vmf_context; #endif /* CXR_VALVE_MAP_FILE */ @@ -146,7 +135,7 @@ struct cxr_static_mesh struct cxr_edge { i32 i0, i1; - i32 freestyle; + i32 freestyle, sharp; } *edges; @@ -155,6 +144,7 @@ struct cxr_static_mesh i32 index, edge_index; v2f uv; + double alpha; } *loops; @@ -188,6 +178,7 @@ struct cxr_loop edge_index, index; v2f uv; + float alpha; }; struct cxr_solid @@ -226,8 +217,11 @@ struct cxr_mesh /* Simple mesh type mainly for debugging */ struct cxr_tri_mesh { - v3f *vertices; + v3f *vertices, + *normals; + v2f *uvs; v4f *colours; + i32 *indices, indices_count, vertex_count; @@ -241,6 +235,11 @@ struct cxr_texinfo double winding; }; +struct cxr_visgroup +{ + const char *name; +}; + /* * Simplified VDF writing interface. No allocations or nodes, just write to file */ @@ -258,10 +257,14 @@ struct cxr_vmf_context *detailvbsp, *detailmaterial; + cxr_visgroup *visgroups; + i32 visgroup_count; + /* Transform settings */ double scale; v3f offset; - i32 lightmap_scale; + i32 lightmap_scale, + visgroupid; /* Current stats */ i32 brush_count, @@ -279,7 +282,8 @@ enum cxr_soliderr k_soliderr_degenerate_implicit, k_soliderr_non_coplanar_vertices, k_soliderr_non_convex_poly, - k_soliderr_bad_result + k_soliderr_bad_result, + k_soliderr_invalid_input }; /* @@ -291,8 +295,12 @@ enum cxr_soliderr const char *cxr_build_time = __DATE__ " @" __TIME__; #endif -static void (*cxr_log_func)(const char *str); -static void (*cxr_line_func)( v3f p0, v3f p1, v4f colour ); +#if _WIN32 || _WIN64 +#if _WIN64 +#else +#warning 32 bit is not supported in blender 3.0 +#endif +#endif static int cxr_range(int x, int bound) { @@ -368,21 +376,6 @@ static void colour_random_brush(int n, v4f colour) #ifdef CXR_DEBUG -static void cxr_log( const char *fmt, ... ) -{ - char buf[512]; - - va_list args; - va_start( args, fmt ); - vsnprintf( buf, sizeof(buf)-1, fmt, args ); - va_end(args); - - if( cxr_log_func ) - cxr_log_func( buf ); - - fputs(buf,stdout); -} - static void cxr_debug_line( v3f p0, v3f p1, v4f colour ) { if( cxr_line_func ) @@ -493,9 +486,12 @@ CXR_API void cxr_write_test_data( cxr_static_mesh *src ) fprintf( fp, "cxr_static_loop test_loops[] = {\n" ); for( int i=0; iloop_count; i ++ ) { - fprintf( fp, " {%d, %d},\n", + fprintf( fp, " {%d, %d, {%f, %f}, %f},\n", src->loops[i].index, - src->loops[i].edge_index); + src->loops[i].edge_index, + src->loops[i].uv[0], + src->loops[i].uv[1], + src->loops[i].alpha ); } fprintf( fp, "};\n" ); @@ -517,10 +513,11 @@ CXR_API void cxr_write_test_data( cxr_static_mesh *src ) fprintf( fp, "cxr_edge test_edges[] = {\n" ); for( int i=0; iedge_count; i++ ) { - fprintf( fp, " {%d, %d, %d},\n", + fprintf( fp, " {%d, %d, %d, %d},\n", src->edges[i].i0, src->edges[i].i1, - src->edges[i].freestyle + src->edges[i].freestyle, + src->edges[i].sharp ); } fprintf( fp, "};\n" ); @@ -622,10 +619,12 @@ static void cxr_mesh_clean_edges( cxr_mesh *mesh ) { cxr_edge *orig_edge = &mesh->edges[ orig_edge_id ]; edge.freestyle = orig_edge->freestyle; + edge.sharp = orig_edge->sharp; } else { edge.freestyle = 0; + edge.sharp = 0; } cxr_ab_push( &new_edges, &edge ); @@ -1008,7 +1007,7 @@ static int *cxr_mesh_reflex_edges( cxr_mesh *mesh ) edge_tagged[lp->edge_index] = 0; cxr_polygon *polya = &mesh->polys[ lp->poly_left ], - *polyb = &mesh->polys[ lp->poly_right ]; + *polyb = &mesh->polys[ lp->poly_right ]; v4f planeb; normal_to_plane(polyb->normal, polyb->center, planeb); @@ -1327,16 +1326,66 @@ static void cxr_link_manifold( struct temp_manifold *manifold ){ cxr_loop **edge_list = malloc( sizeof(*edge_list) * solid->edge_count ); + int *temp_solid = malloc( solid->count *sizeof(int) ); + int temp_solid_len = 0; int init_reverse = 0; int unique_edge_count = 0; + + /* Try remove splitting faces first */ + { + int split_total = 0; + for( int j=0; jcount; j++ ) + { + cxr_polygon *poly = &mesh->polys[ solid_buffer[solid->start+j] ]; + int interior_count = 0; + + for( int k=0; kloop_total; k++ ) + { + cxr_loop *loop = &mesh->loops[ poly->loop_start+k ]; + + for( int l=0; lcount; l++ ) + if( loop->poly_right == solid_buffer[solid->start+l] ) + { + interior_count ++; + goto next; + } - /* Gather list of unique edges */ + next:; + } + + if( interior_count < poly->loop_total-1 ) + { + split_total ++; + continue; + } + + temp_solid[ temp_solid_len ++ ] = solid_buffer[solid->start+j]; + } + + if( temp_solid_len < 3 || (split_total & 0x2) /* unkown reasons */ ) + { + } + else + { + /* Overwrite original solid */ + for( int j=0; jstart+j ] = temp_solid[ j ]; + + solid->count = temp_solid_len; + } + + free( temp_solid ); + } for( int j=0; jcount; j++ ) { cxr_polygon *poly = &mesh->polys[ solid_buffer[solid->start+j] ]; + /* when discarding, if a face has only one loop that points outwards, + * we keep it */ + + for( int k=0; kloop_total; k++ ) { cxr_loop *loop = &mesh->loops[ poly->loop_start+k ]; @@ -1579,10 +1628,11 @@ static int cxr_non_manifold_err( cxr_mesh *mesh ) for( int i=0; iabloops.count; i++ ) { cxr_loop *lp = &mesh->loops[i]; + cxr_edge *edge = &mesh->edges[lp->edge_index]; + cxr_debug_line( verts[edge->i0], verts[edge->i1], colours_random[1] ); if( lp->poly_left == -1 || lp->poly_right == -1 ) { - cxr_edge *edge = &mesh->edges[lp->edge_index]; cxr_debug_line( verts[edge->i0], verts[edge->i1], colour_error ); } } @@ -1728,7 +1778,7 @@ static cxr_mesh *cxr_pull_best_solid( struct temp_manifold manifold; cxr_link_manifold( mesh, solid, solid_buffer, &manifold); - + if( manifold.status == k_manifold_err ) { *err = k_soliderr_bad_manifold; @@ -2009,6 +2059,7 @@ static cxr_mesh *cxr_to_internal_format( lp->index = src->loops[i].index; lp->edge_index = src->loops[i].edge_index; v2_copy( src->loops[i].uv, lp->uv ); + lp->alpha = src->loops[i].alpha; } abverts->count = src->vertex_count; @@ -2137,6 +2188,8 @@ CXR_API cxr_tri_mesh *cxr_world_preview( cxr_world *world ) out->colours = malloc( sizeof(v4f)*out->vertex_count ); out->vertices = malloc( sizeof(v3f)*out->vertex_count ); out->indices = malloc( sizeof(i32)*out->indices_count ); + out->uvs = NULL; + out->normals = NULL; v3f *overts = out->vertices; v4f *colours = out->colours; @@ -2218,11 +2271,23 @@ CXR_API void cxr_free_tri_mesh( cxr_tri_mesh *mesh ) free( mesh->colours ); free( mesh->indices ); free( mesh->vertices ); + free( mesh->normals ); + free( mesh->uvs ); free( mesh ); } CXR_API cxr_world *cxr_decompose( cxr_static_mesh *src, i32 *perrcode ) { + /* Make sure data is in the mesh and isn't empty */ + if( !src->edge_count || !src->loop_count || !src->poly_count ) + { + cxr_log( "Error %d\n", k_soliderr_invalid_input ); + if( perrcode ) + *perrcode = k_soliderr_invalid_input; + + return NULL; + } + u32 error = 0x00; cxr_world *world = malloc( sizeof(*world) ); @@ -2692,6 +2757,13 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world, } } + /* Collect alphas from loops. This discards hard blend information */ + for( int i=0; iabloops.count; i++ ) + { + cxr_loop *loop = &mesh->loops[i]; + vertinfo[loop->index].alpha = loop->alpha * 255.0; + } + v3f refv, refu, refn; v3_zero(refv); v3_zero(refu); v3_zero(refn); @@ -2894,6 +2966,8 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world, if( !newvert ) { + free( graph ); + free( vertinfo ); return 0; } } @@ -2956,9 +3030,6 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world, } } -#ifdef CXR_DEBUG - cxr_log( "Broken displacement!\n" ); -#endif free( graph ); free( vertinfo ); return 0; @@ -3010,6 +3081,8 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world, v3_muladds( face_center, refn, 1.5, pn ); v3_muladds( face_center, refv, 1.5, pv ); v3_muladds( face_center, refu, 1.5, pu ); + + v3_muladds( face_center, refn, 2.0, face_center ); } /* Create world coordinates */ @@ -3059,6 +3132,7 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world, v3f normals[25]; double distances[25]; + double alphas[25]; v3f lside0, lside1, lref, vdelta, vworld; double tx, ty; @@ -3083,6 +3157,8 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world, v3_copy( vdelta, normals[index] ); v3_normalize( normals[index] ); distances[index] = v3_dot( vdelta, normals[index] ); + + alphas[index] = vertinfo[grid[index]].alpha; } } @@ -3129,6 +3205,11 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world, cxr_vdf_karrdouble( output, "row", k, &distances[k*5], 5 ); cxr_vdf_edon( output ); + cxr_vdf_node( output, "alphas" ); + for( int k=0; k<5; k++ ) + cxr_vdf_karrdouble( output, "row", k, &alphas[k*5], 5 ); + cxr_vdf_edon( output ); + /* * TODO: This might be needed for the compilers. Opens fine in * hammer @@ -3147,11 +3228,6 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world, "\"row%d\" \"0 0 1 0 0 1 0 0 1 0 0 1 0 0 1\"\n", k ); cxr_vdf_edon( output ); - cxr_vdf_node( output, "alphas" ); - for( int k=0; k<5; k++ ) - cxr_vdf_printf( output, "\"row%d\" \"0 0 0 0 0\"\n", k ); - cxr_vdf_edon( output ); - cxr_vdf_node( output, "triangle_tags" ); for( int k=0; k<5-1; k++ ) cxr_vdf_printf( output, @@ -3173,7 +3249,8 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world, cxr_vdf_node( output, "editor"); cxr_vdf_colour255( output, "color", colours_random[cxr_range(ctx->brush_count,8)]); - + + cxr_vdf_ki32( output, "visgroupid", ctx->visgroupid ); cxr_vdf_ki32( output, "visgroupshown",1); cxr_vdf_ki32( output, "visgroupautoshown",1); cxr_vdf_edon( output ); @@ -3203,6 +3280,15 @@ CXR_API void cxr_begin_vmf( cxr_vmf_context *ctx, cxr_vdf *output ) cxr_vdf_edon( output ); cxr_vdf_node( output, "visgroups" ); + + for( int i=0; ivisgroup_count; i++ ) + { + cxr_vdf_node( output, "visgroup" ); + cxr_vdf_kv( output, "name", ctx->visgroups[i].name ); + cxr_vdf_ki32( output, "visgroupid", i+1 ); + cxr_vdf_edon( output ); + } + cxr_vdf_edon( output ); cxr_vdf_node( output, "viewsettings" ); @@ -3248,7 +3334,10 @@ CXR_API void cxr_push_world_vmf( cxr_world *world, cxr_vmf_context *ctx, if( solid->displacement ) { - cxr_write_disp( solid->pmesh, world, ctx, output ); + if( !cxr_write_disp( solid->pmesh, world, ctx, output ) ) + { + cxr_log( "Warning: Invalid displacement\n" ); + } continue; } @@ -3307,6 +3396,7 @@ CXR_API void cxr_push_world_vmf( cxr_world *world, cxr_vmf_context *ctx, cxr_vdf_colour255( output, "color", colours_random[cxr_range(ctx->brush_count,8)]); + cxr_vdf_ki32( output, "visgroupid", ctx->visgroupid ); cxr_vdf_ki32( output, "visgroupshown", 1 ); cxr_vdf_ki32( output, "visgroupautoshown", 1 ); cxr_vdf_edon( output ); @@ -3419,5 +3509,6 @@ CXR_API int cxr_lightpatch_bsp( const char *path ) return 1; } + #endif /* CXR_VALVE_MAP_FILE */ #endif /* CXR_IMPLEMENTATION */