/*
- CONVEXER v0.91
+ 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
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;
i32 index,
edge_index;
v2f uv;
+ double alpha;
}
*loops;
edge_index,
index;
v2f uv;
+ float alpha;
};
struct cxr_solid
/* 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;
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)
{
#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 )
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" );
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;
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;
free( mesh->colours );
free( mesh->indices );
free( mesh->vertices );
+ free( mesh->normals );
+ free( mesh->uvs );
free( mesh );
}
}
}
+ /* 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);
if( !newvert )
{
+ free( graph );
+ free( vertinfo );
return 0;
}
}
}
}
-#ifdef CXR_DEBUG
- cxr_log( "Broken displacement!\n" );
-#endif
free( graph );
free( vertinfo );
return 0;
v3f normals[25];
double distances[25];
+ double alphas[25];
v3f lside0, lside1, lref, vdelta, vworld;
double tx, ty;
v3_copy( vdelta, normals[index] );
v3_normalize( normals[index] );
distances[index] = v3_dot( vdelta, normals[index] );
+
+ alphas[index] = vertinfo[grid[index]].alpha;
}
}
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
"\"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,
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;
}
return 1;
}
+
+#ifdef CXR_VALVE_BIN
+
+CXR_API cxr_tri_mesh *cxr_load_mdl( const char *mdlname )
+{
+ char path[1024];
+ strcpy( path, mdlname );
+ cxr_stripext( path );
+ strcat( path, ".dx90.vtx" );
+ VTXFileHeader_t *pVtxHdr = (VTXFileHeader_t *)cxr_fs_get( path );
+
+ if( !pVtxHdr )
+ return NULL;
+
+ /* .VVD */
+ strcpy( path, mdlname );
+ cxr_stripext( path );
+ strcat( path, ".vvd" );
+ vertexFileHeader_t *pVvdHdr = (vertexFileHeader_t *)cxr_fs_get( path );
+
+ if( !pVvdHdr )
+ {
+ free( pVtxHdr );
+ return 0;
+ }
+
+ /* .MDL */
+ strcpy( path, mdlname );
+ cxr_stripext( path );
+ strcat( path, ".mdl" );
+ studiohdr_t *pMdl = (studiohdr_t *)cxr_fs_get( path );
+
+ if( !pMdl )
+ {
+ free( pVtxHdr );
+ free( pVvdHdr );
+ return 0;
+ }
+
+ cxr_tri_mesh *mesh = malloc( sizeof(cxr_tri_mesh) );
+ mesh->colours = NULL;
+
+ mesh->indices_count = vtx_count_indices( pVtxHdr, pMdl );
+ mesh->indices = malloc( mesh->indices_count * sizeof( u32 ) );
+
+ mesh->vertex_count = pVvdHdr->numLodVertexes[0];
+ mesh->vertices = malloc( mesh->vertex_count * sizeof(v3f) );
+ mesh->uvs = malloc( mesh->vertex_count * sizeof(v2f) );
+ mesh->normals = malloc( mesh->vertex_count * sizeof(v3f) );
+
+#if 0
+ mesh->bounds[0][0] = pMdl->hull_min[0];
+ mesh->bounds[0][1] = pMdl->hull_min[1];
+ mesh->bounds[0][2] = pMdl->hull_min[2];
+ mesh->bounds[0][0] = pMdl->hull_max[0];
+ mesh->bounds[0][1] = pMdl->hull_max[1];
+ mesh->bounds[0][2] = pMdl->hull_max[2];
+#endif
+
+ mesh->indices_count = 0;
+
+ for( int bodyID = 0; bodyID < pVtxHdr->numBodyParts; ++bodyID )
+ {
+ /* Body parts */
+ VTXBodyPartHeader_t* pVtxBodyPart = pBodyPartVTX( pVtxHdr, bodyID );
+ mstudiobodyparts_t *pBodyPart = studiohdr_pBodypart( pMdl, bodyID );
+
+ for( int modelID = 0; modelID < pBodyPart->nummodels; ++modelID )
+ {
+ /* models */
+ VTXModelHeader_t* pVtxModel = pModelVTX( pVtxBodyPart, modelID );
+ mstudiomodel_t *pStudioModel =
+ mstudiobodyparts_pModel( pBodyPart, modelID );
+
+ int nLod = 0;
+ VTXModelLODHeader_t *pVtxLOD = pLODVTX( pVtxModel, nLod );
+
+ for( int nMesh = 0; nMesh < pStudioModel->nummeshes; ++nMesh )
+ {
+ /* meshes */
+ VTXMeshHeader_t* pVtxMesh = pMeshVTX( pVtxLOD, nMesh );
+ mstudiomesh_t* pMesh = studiomodel_pMesh( pStudioModel, nMesh );
+
+ for ( int nGroup = 0; nGroup < pVtxMesh->numStripGroups; ++nGroup )
+ {
+ /* groups */
+ VTXStripGroupHeader_t* pStripGroup =
+ pStripGroupVTX( pVtxMesh, nGroup );
+
+ for ( int nStrip = 0; nStrip < pStripGroup->numStrips; nStrip++ )
+ {
+ /* strips */
+ VTXStripHeader_t *pStrip = pStripVTX( pStripGroup, nStrip );
+
+ if ( pStrip->flags & STRIP_IS_TRILIST )
+ {
+ /* indices */
+ for ( int i = 0; i < pStrip->numIndices; i ++ )
+ {
+ u16 i1 = *pIndexVTX( pStripGroup,
+ pStrip->indexOffset + i );
+
+ mesh->indices[ mesh->indices_count ++ ] =
+ pVertexVTX( pStripGroup, i1 )->origMeshVertID +
+ pMesh->vertexoffset;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ mstudiovertex_t *vertexData = GetVertexData( pVvdHdr );
+
+ for( int i = 0; i < mesh->vertex_count; i ++ )
+ {
+ mstudiovertex_t *vert = vertexData + i;
+
+ mesh->vertices[i][0] = vert->pos[0];
+ mesh->vertices[i][1] = vert->pos[1];
+ mesh->vertices[i][2] = vert->pos[2];
+
+ mesh->normals[i][0] = vert->norm[0];
+ mesh->normals[i][1] = vert->norm[1];
+ mesh->normals[i][2] = vert->norm[2];
+
+ mesh->uvs[i][0] = vert->uv[0];
+ mesh->uvs[i][1] = vert->uv[1];
+ }
+
+ free( pVtxHdr );
+ free( pVvdHdr );
+ free( pMdl );
+
+ return mesh;
+}
+#endif /* CXR_VALVE_BIN */
+
#endif /* CXR_VALVE_MAP_FILE */
#endif /* CXR_IMPLEMENTATION */