the asumptions were of course, incorrect
[convexer.git] / cxr / cxr.h
index dd7a8b83092dffc3612042b87aba4216abe6b54f..644c8ed83e39381e88ceb5c3beeb4772e29f3be3 100644 (file)
--- 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
 
 #include <stdio.h>
 #include <math.h>
-#include <stdint.h>
-#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 
-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 */
 
@@ -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; i<src->loop_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" );
 
@@ -2063,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;
@@ -2191,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;
@@ -2272,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) );
    
@@ -2746,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; i<mesh->abloops.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);
    
@@ -2948,6 +2966,8 @@ static int cxr_write_disp( cxr_mesh *mesh, cxr_world *world,
 
             if( !newvert )
             {
+               free( graph );
+               free( vertinfo );
                return 0;
             }
          }
@@ -3010,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;
@@ -3064,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 */
@@ -3113,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;
@@ -3137,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;
             }
          }
 
@@ -3183,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
@@ -3201,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, 
@@ -3227,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 );
@@ -3257,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; i<ctx->visgroup_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" );
@@ -3302,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;
       }
       
@@ -3361,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 );
@@ -3473,5 +3509,6 @@ CXR_API int cxr_lightpatch_bsp( const char *path )
 
    return 1;
 }
+
 #endif /* CXR_VALVE_MAP_FILE */
 #endif /* CXR_IMPLEMENTATION */