14c91c23fd1f1504902f5eeb1f7429239a7e84d2
1 typedef struct csr_frag csr_frag
;
2 typedef struct csr_target csr_target
;
3 typedef struct csr_filter csr_filter
;
27 const char *visgroup
; // Limit to this visgroup only
28 const char *classname
; // Limit to this exact classname. will not draw world
30 int compute_bounds_only
;
33 void csr_create_target( csr_target
*rt
, u32 x
, u32 y
)
39 rt
->fragments
= (csr_frag
*)csr_malloc( x
*y
*sizeof(csr_frag
)*rt
->num_samples
);
41 v3_fill( rt
->bounds
[0], INFINITY
);
42 v3_fill( rt
->bounds
[1], -INFINITY
);
45 void csr_update_subsamples( csr_target
*rt
)
47 float range_x
= (rt
->bounds
[1][0]-rt
->bounds
[0][0]);
48 float range_y
= (rt
->bounds
[1][1]-rt
->bounds
[0][1]);
50 v2f pixel_size
= { range_x
/(float)rt
->x
, range_y
/(float)rt
->y
};
52 rt
->subsamples
[0][0] = pixel_size
[0] * -0.25f
;
53 rt
->subsamples
[0][1] = 0.f
;
54 rt
->subsamples
[1][0] = pixel_size
[0] * 0.75f
;
55 rt
->subsamples
[1][1] = pixel_size
[1] * 0.25f
;
56 rt
->subsamples
[2][0] = 0.f
;
57 rt
->subsamples
[2][1] = pixel_size
[1] * 0.5f
;
58 rt
->subsamples
[3][0] = pixel_size
[0] * 0.5f
;
59 rt
->subsamples
[3][1] = pixel_size
[1] * 0.75f
;
62 void csr_rt_free( csr_target
*rt
)
64 free( rt
->fragments
);
67 void csr_rt_clear( csr_target
*rt
)
69 for( u32 i
= 0; i
< rt
->x
*rt
->y
*rt
->num_samples
; i
++ )
71 v3_zero( rt
->fragments
[ i
].co
);
72 v3_zero( rt
->fragments
[ i
].nrm
);
73 rt
->fragments
[i
].depth
= 0.f
;
77 void csr_auto_fit( csr_target
*rt
, float padding
)
79 // Correct aspect ratio to be square
80 float dx
, dy
, d
, l
, cx
, cy
;
81 dx
= rt
->bounds
[1][0] - rt
->bounds
[0][0];
82 dy
= rt
->bounds
[1][1] - rt
->bounds
[0][1];
84 l
= fmaxf( dx
, dy
) * .5f
;
86 cx
= (rt
->bounds
[1][0] + rt
->bounds
[0][0]) * .5f
;
87 cy
= (rt
->bounds
[1][1] + rt
->bounds
[0][1]) * .5f
;
89 rt
->bounds
[0][0] = cx
- l
- padding
;
90 rt
->bounds
[1][0] = cx
+ l
+ padding
;
91 rt
->bounds
[0][1] = cy
- l
- padding
;
92 rt
->bounds
[1][1] = cy
+ l
+ padding
;
94 rt
->scale
= l
+ padding
;
96 csr_update_subsamples( rt
);
99 void csr_write_txt( char const *path
, const char *name
, csr_target
*rt
)
103 write_ptr
= fopen( path
, "w" );
105 fprintf( write_ptr
, "\"%s\"\n\{\n", name
);
106 fprintf( write_ptr
, "\t\"material\" \"overviews/%s\"\n", name
);
107 fprintf( write_ptr
, "\t\"pos_x\" \"%.8f\"\n", rt
->bounds
[0][0] );
108 fprintf( write_ptr
, "\t\"pos_y\" \"%.8f\"\n", rt
->bounds
[0][1] );
109 fprintf( write_ptr
, "\t\"scale\" \"%.8f\"\n", rt
->scale
/ (float)rt
->x
);
110 fprintf( write_ptr
, "}\n" );
115 void simple_raster( csr_target
*rt
, vmf_vert tri
[3] )
117 // Very very simplified rasterizing algorithm
118 v2f bmin
= { 0.f
, 0.f
};
119 v2f bmax
= { rt
->x
, rt
->y
};
121 v2_minv( tri
[0].co
, tri
[1].co
, bmin
);
122 v2_minv( tri
[2].co
, bmin
, bmin
);
124 v2_maxv( tri
[0].co
, tri
[1].co
, bmax
);
125 v2_maxv( tri
[2].co
, bmax
, bmax
);
127 float range_x
= (rt
->bounds
[1][0]-rt
->bounds
[0][0])/(float)rt
->x
;
128 float range_y
= (rt
->bounds
[1][1]-rt
->bounds
[0][1])/(float)rt
->y
;
130 int start_x
= csr_min( rt
->x
-1, csr_max( 0, floorf( (bmin
[0]-rt
->bounds
[0][0])/range_x
)));
131 int end_x
= csr_max( 0, csr_min( rt
->x
-1, ceilf( (bmax
[0]-rt
->bounds
[0][0])/range_x
)));
132 int start_y
= csr_min( rt
->y
-1, csr_max( 0, floorf( (bmin
[1]-rt
->bounds
[0][1])/range_y
)));
133 int end_y
= csr_max( 0, csr_min( rt
->y
-1, ceilf( (bmax
[1]-rt
->bounds
[0][1])/range_y
)));
136 float d
, bca
= 0.f
, bcb
= 0.f
, bcc
= 0.f
;
138 v2_sub( tri
[1].co
, tri
[0].co
, v0
);
139 v2_sub( tri
[2].co
, tri
[0].co
, v1
);
140 v2_sub( tri
[1].co
, tri
[2].co
, v2
);
141 d
= 1.f
/ (v0
[0]*v1
[1] - v1
[0]*v0
[1]);
144 if( v2_cross( v0
, v1
) > 0.f
)
149 for( u32 py
= start_y
; py
<= end_y
; py
++ )
151 trace_origin
[1] = csr_lerpf( rt
->bounds
[0][1], rt
->bounds
[1][1], (float)py
/(float)rt
->y
);
153 for( u32 px
= start_x
; px
<= end_x
; px
++ )
155 csr_frag
*frag
= &rt
->fragments
[ (py
* rt
->y
+ px
) * rt
->num_samples
];
157 trace_origin
[0] = csr_lerpf( rt
->bounds
[0][0], rt
->bounds
[1][0], (float)px
/(float)rt
->x
);
159 // Determine coverage
160 for( int i
= 0; i
< rt
->num_samples
; i
++ )
164 v2_add( rt
->subsamples
[ i
], trace_origin
, sample_origin
);
165 v2_sub( sample_origin
, tri
[0].co
, vp
);
167 if( v2_cross( v0
, vp
) > 0.f
)
169 if( v2_cross( vp
, v1
) > 0.f
)
173 v2_sub( sample_origin
, tri
[2].co
, vp2
);
175 if( v2_cross( vp2
, v2
) > 0.f
)
178 bcb
= (vp
[0]*v1
[1] - v1
[0]*vp
[1]) * d
;
179 bcc
= (v0
[0]*vp
[1] - vp
[0]*v0
[1]) * d
;
180 bca
= 1.f
- bcb
- bcc
;
182 float hit
= (tri
[0].co
[2] * bca
+ tri
[1].co
[2] * bcb
+ tri
[2].co
[2] * bcc
) +16385.f
;
184 if( hit
> frag
[i
].depth
)
187 v3_muls( tri
[0].co
, bca
, frag
[i
].co
);
188 v3_muladds( frag
[i
].co
, tri
[1].co
, bcb
, frag
[i
].co
);
189 v3_muladds( frag
[i
].co
, tri
[2].co
, bcc
, frag
[i
].co
);
191 // TODO: Same for normal map
198 void csr_draw( csr_target
*rt
, vmf_vert
*triangles
, u32 triangle_count
, m4x3f transform
)
203 // Derive normal matrix
204 m4x3_to_3x3( transform
, normal
);
205 m3x3_inv_transpose( normal
, normal
);
207 for( u32 i
= 0; i
< triangle_count
; i
++ )
209 vmf_vert
*triangle
= triangles
+ i
*3;
211 m4x3_mulv( transform
, triangle
[0].co
, new_tri
[0].co
);
212 m4x3_mulv( transform
, triangle
[1].co
, new_tri
[1].co
);
213 m4x3_mulv( transform
, triangle
[2].co
, new_tri
[2].co
);
214 m3x3_mulv( normal
, triangle
[0].nrm
, new_tri
[0].nrm
);
215 m3x3_mulv( normal
, triangle
[1].nrm
, new_tri
[1].nrm
);
216 m3x3_mulv( normal
, triangle
[2].nrm
, new_tri
[2].nrm
);
218 simple_raster( rt
, new_tri
);
222 void draw_vmf_group( csr_target
*rt
, vmf_map
*map
, vdf_node
*root
, csr_filter
*filter
, m4x3f prev
, m4x3f inst
)
224 m4x3f transform
= M4X3_IDENTITY
;
230 int filter_visgroups
= 0, filter_classname
= 0, compute_bounds_only
= 0;
234 if( filter
->visgroup
)
236 filter_visgroups
= 1;
237 group_id
= vmf_visgroup_id( root
, filter
->visgroup
);
240 if( filter
->classname
)
242 filter_classname
= 1;
245 compute_bounds_only
= filter
->compute_bounds_only
;
248 // Multiply previous transform with instance transform to create basis
251 m4x3_mul( prev
, inst
, transform
);
254 // Gather world brushes
255 solidgen_ctx_init( &solid
);
257 if( !filter_classname
)
259 vdf_node
*world
= vdf_next( root
, "world", NULL
);
261 vdf_foreach( world
, "solid", brush
)
263 if( filter_visgroups
&& !vmf_visgroup_match( brush
, group_id
) )
266 solidgen_push( &solid
, brush
);
270 // Actual entity loop
273 vdf_foreach( root
, "entity", ent
)
275 if( filter_visgroups
&& !vmf_visgroup_match( ent
, group_id
) )
278 if( filter_classname
)
279 if( strcmp( kv_get( ent
, "classname", "" ), filter
->classname
) )
282 if( ent
->user
& VMF_FLAG_IS_PROP
)
284 // Create model transform
285 m4x3_identity( model
);
287 vmf_entity_transform( ent
, model
);
288 m4x3_mul( transform
, model
, model
);
291 mdl_mesh_t
*mdl
= &map
->models
[ ent
->user1
].mdl
;
293 if( compute_bounds_only
)
295 box_copy( mdl
->bounds
, trf_bounds
);
296 m4x3_transform_aabb( model
, trf_bounds
);
299 box_concat( rt
->bounds
, trf_bounds
);
303 for( int i
= 0; i
< mdl
->num_indices
/3; i
++ )
305 for( int j
= 0; j
< 3; j
++ )
307 v3_copy( &mdl
->vertices
[ mdl
->indices
[ i
*3+j
] *8 ], tri
[j
].co
);
308 v3_copy( &mdl
->vertices
[ mdl
->indices
[ i
*3+j
] *8+3 ], tri
[j
].nrm
);
313 csr_draw( rt
, tri
, 1, model
);
317 else if( ent
->user
& VMF_FLAG_IS_INSTANCE
)
319 m4x3_identity( model
);
320 vmf_entity_transform( ent
, model
);
322 draw_vmf_group( rt
, map
, map
->cache
[ ent
->user1
].root
, filter
, transform
, model
);
327 vdf_foreach( ent
, "solid", ent_solid
)
329 solidgen_push( &solid
, ent_solid
);
334 if( compute_bounds_only
)
336 solidgen_bounds( &solid
, trf_bounds
);
337 m4x3_transform_aabb( transform
, trf_bounds
);
338 box_concat( rt
->bounds
, trf_bounds
);
343 for( int i
= 0; i
< csr_sb_count( solid
.indices
)/3; i
++ )
345 u32
* base
= solid
.indices
+ i
*3;
347 tri
[0] = solid
.verts
[ base
[0] ];
348 tri
[1] = solid
.verts
[ base
[1] ];
349 tri
[2] = solid
.verts
[ base
[2] ];
351 csr_draw( rt
, tri
, 1, transform
);
355 solidgen_ctx_reset( &solid
);
356 solidgen_ctx_free( &solid
);
359 void csr_rt_save_buffers( csr_target
*rt
, const char *basename
, const char *subname
)
363 float *image
= (float *)csr_malloc( 1024*1024*sizeof(float)*3 );
365 for( int l
= 0; l
< rt
->x
; l
++ )
367 for( int x
= 0; x
< rt
->y
; x
++ )
369 float *dst
= &image
[ (l
*1024+x
)*3 ];
370 csr_frag
*src
= &rt
->fragments
[ ((1023-l
)*1024+x
)*rt
->num_samples
];
373 v3_muls( src
[0].co
, 1.f
/(float)rt
->num_samples
, dst
);
374 v3_muladds( dst
, src
[1].co
, 1.f
/(float)rt
->num_samples
, dst
);
375 v3_muladds( dst
, src
[2].co
, 1.f
/(float)rt
->num_samples
, dst
);
376 v3_muladds( dst
, src
[3].co
, 1.f
/(float)rt
->num_samples
, dst
);
380 // Save position buffer
381 strcpy( output
, basename
);
382 strcat( output
, "." );
383 strcat( output
, subname
);
384 strcat( output
, "_position.pfm" );
385 csr_32f_write( output
, rt
->x
, rt
->y
, image
);