@ -172,42 +172,94 @@ static unsigned char sample_lightmap(const world_t* world, const face_t *face, c
const unsigned char * lightmap = & world - > lightmap [ face - > lightmap ] ;
const plane_t * plane = & world - > planes [ face - > plane_id ] ;
float w , h , u , v ;
int width , height ;
float u , v ;
switch ( plane - > type )
{
case 0 :
case 3 :
// Towards X
w = bounds . max . y - bounds . min . y ;
h = bounds . max . z - bounds . min . z ;
u = ( point . y - bounds . min . y ) / w ;
v = ( point . z - bounds . min . z ) / h ;
width = ( int ) ( ceil ( bounds . max . y / 16 ) - floor ( bounds . min . y / 16 ) ) * 16 ;
height = ( int ) ( ceil ( bounds . max . z / 16 ) - floor ( bounds . min . z / 16 ) ) * 16 ;
u = ( point . y - bounds . min . y ) / width ;
v = ( point . z - bounds . min . z ) / height ;
break ;
case 1 :
case 4 :
// Towards Y
w = bounds . max . x - bounds . min . x ;
h = bounds . max . z - bounds . min . z ;
u = ( point . x - bounds . min . x ) / w ;
v = ( point . z - bounds . min . z ) / h ;
width = ( int ) ( ceil ( bounds . max . x / 16 ) - floor ( bounds . min . x / 16 ) ) * 16 ;
height = ( int ) ( ceil ( bounds . max . z / 16 ) - floor ( bounds . min . z / 16 ) ) * 16 ;
u = ( point . x - bounds . min . x ) / width ;
v = ( point . z - bounds . min . z ) / height ;
break ;
case 2 :
case 5 :
// Towards Z
w = bounds . max . x - bounds . min . x ;
h = bounds . max . y - bounds . min . y ;
u = ( point . x - bounds . min . x ) / w ;
v = ( point . y - bounds . min . y ) / h ;
width = ( int ) ( ceil ( bounds . max . x / 16 ) - floor ( bounds . min . x / 16 ) ) * 16 ;
height = ( int ) ( ceil ( bounds . max . y / 16 ) - floor ( bounds . min . y / 16 ) ) * 16 ;
u = ( point . x - bounds . min . x ) / width ;
v = ( point . y - bounds . min . y ) / height ;
break ;
default :
printf ( " Error: unknown plane type %d \n " , plane - > type ) ;
return 0 ;
}
int width = ( int ) ( w / 16 ) ;
int height = ( int ) ( h / 16 ) ;
height > > = 4 ;
width > > = 4 ;
return lightmap [ ( int ) ( ( height * v + u ) * width ) ] ;
return lightmap [ ( int ) ( v * ( width + 1 ) + u ) ] ;
}
static void export_lightmap ( const world_t * world , const face_t * face , const BoundBox & bounds , int faceIdx )
{
if ( face - > lightmap < 0 )
return ;
const unsigned char * lightmap = & world - > lightmap [ face - > lightmap ] ;
const plane_t * plane = & world - > planes [ face - > plane_id ] ;
int width , height ;
switch ( plane - > type )
{
case 0 :
case 3 :
// Towards X
width = ceil ( bounds . max . y / 16 ) - floor ( bounds . min . y / 16 ) ;
height = ceil ( bounds . max . z / 16 ) - floor ( bounds . min . z / 16 ) ;
break ;
case 1 :
case 4 :
// Towards Y
width = ceil ( bounds . max . x / 16 ) - floor ( bounds . min . x / 16 ) ;
height = ceil ( bounds . max . z / 16 ) - floor ( bounds . min . z / 16 ) ;
break ;
case 2 :
case 5 :
// Towards Z
width = ceil ( bounds . max . x / 16 ) - floor ( bounds . min . x / 16 ) ;
height = ceil ( bounds . max . y / 16 ) - floor ( bounds . min . y / 16 ) ;
break ;
default :
printf ( " Error: unknown plane type %d \n " , plane - > type ) ;
return ;
}
width + = 1 ;
char path [ _MAX_PATH ] ;
sprintf_s ( path , _MAX_PATH , " lightmap_face%d_e%d_PT%d_%dx%d.raw " , faceIdx , face - > ledge_num , plane - > type , width , height ) ;
FILE * flm ;
fopen_s ( & flm , path , " wb " ) ;
if ( ! flm )
return ;
for ( int y = 0 ; y < height ; + + y )
{
fwrite ( & lightmap [ y * width ] , sizeof ( unsigned char ) , width , flm ) ;
}
fclose ( flm ) ;
}
int process_faces ( const world_t * world )
@ -231,17 +283,11 @@ int process_faces(const world_t* world)
}
// Write vertex data to a file (no vertex splitting yet)
BoundBox bounds ;
std : : vector < ps1bsp_vertex_t > outVertices ;
for ( unsigned short i = 0 ; i < world - > numVertices ; + + i )
{
// TODO: we should respect the ordering from vertexRef->index here but meh, problem for later
vertex_t * inVertex = & world - > vertices [ i ] ;
if ( i = = 0 )
bounds . init ( inVertex - > toVec ( ) ) ;
else
bounds . includePoint ( inVertex - > toVec ( ) ) ;
ps1bsp_vertex_t outVertex = { 0 } ;
// Ensure we don't overflow 16-bit short values. Most Quake maps will stay within these bounds so it *should* be fine (for now).
@ -270,6 +316,7 @@ int process_faces(const world_t* world)
outFace . firstVertexIndex = faceVertIndices . size ( ) ;
// Traverse the list of face edges to collect all of the face's vertices
BoundBox bounds ;
for ( int edgeListIdx = 0 ; edgeListIdx < face - > ledge_num ; + + edgeListIdx )
{
int edgeIdx = world - > edgeList [ face - > ledge_id + edgeListIdx ] ;
@ -280,14 +327,30 @@ int process_faces(const world_t* world)
faceVertIndices . push_back ( vertIndex ) ;
unsigned char light = sample_lightmap ( world , face , bounds , world - > vertices [ vertIndex ] . toVec ( ) ) ;
if ( light > 0 )
// Calculate bounding box of this face
const vertex_t * vertex = & world - > vertices [ vertIndex ] ;
if ( edgeListIdx = = 0 )
bounds . init ( vertex - > toVec ( ) ) ;
else
bounds . includePoint ( vertex - > toVec ( ) ) ;
}
// Accumulate lightmap contribution of this face on each vertex
if ( face - > lightmap > = 0 )
{
for ( int indexIdx = outFace . firstVertexIndex ; indexIdx < faceVertIndices . size ( ) ; + + indexIdx )
{
* ( unsigned short * ) ( & outVertices [ vertIndex ] . baseLight ) + = light ;
int vertIndex = faceVertIndices [ indexIdx ] ;
unsigned char light = sample_lightmap ( world , face , bounds , world - > vertices [ vertIndex ] . toVec ( ) ) ;
* ( unsigned short * ) ( & outVertices [ vertIndex ] . baseLight ) + = light + ( 0xFF - face - > baselight ) ;
outVertices [ vertIndex ] . r + + ;
}
}
// For visualizing and debugging lightmaps
//if (face->ledge_num >= 10)
// export_lightmap(world, face, bounds, faceIdx);
outFace . numVertices = faceVertIndices . size ( ) - outFace . firstVertexIndex ;
outFaces . push_back ( outFace ) ;
}