955ea3080b6cf1e3024838e21b63289ac4d7664b
1 typedef struct csr_frag csr_frag
;
2 typedef struct csr_target csr_target
;
3 typedef struct csr_filter csr_filter
;
7 u32 id
; // Triangle index
8 float depth
; // 'depth testing'
24 const char *visgroup
; // Limit to this visgroup only
25 const char *classname
; // Limit to this exact classname. will not draw world
27 int compute_bounds_only
;
30 void csr_create_target( csr_target
*rt
, u32 x
, u32 y
)
34 rt
->fragments
= (csr_frag
*)csr_malloc( x
*y
*sizeof(csr_frag
) );
35 v3_fill( rt
->bounds
[0], INFINITY
);
36 v3_fill( rt
->bounds
[1], -INFINITY
);
39 void csr_rt_free( csr_target
*rt
)
41 free( rt
->fragments
);
44 void csr_rt_clear( csr_target
*rt
)
46 for( u32 i
= 0; i
< rt
->x
*rt
->y
; i
++ )
48 rt
->fragments
[ i
].depth
= 0.f
;
52 void csr_auto_fit( csr_target
*rt
, float padding
)
54 // Correct aspect ratio to be square
55 float dx
, dy
, d
, l
, cx
, cy
;
56 dx
= rt
->bounds
[1][0] - rt
->bounds
[0][0];
57 dy
= rt
->bounds
[1][1] - rt
->bounds
[0][1];
60 d
= l
* ( l
/ dx
) * .5f
;
62 cx
= (rt
->bounds
[1][0] + rt
->bounds
[0][0]) * .5f
;
63 cy
= (rt
->bounds
[1][1] + rt
->bounds
[0][1]) * .5f
;
65 rt
->bounds
[0][0] = cx
- d
- padding
;
66 rt
->bounds
[1][0] = cx
+ d
+ padding
;
67 rt
->bounds
[0][1] = cy
- d
- padding
;
68 rt
->bounds
[1][1] = cy
+ d
+ padding
;
70 rt
->scale
= d
+ padding
;
73 void simple_raster( csr_target
*rt
, vmf_vert tri
[3], int id
)
75 // Very simplified tracing algorithm
76 float tqa
= 0.f
, tqb
= 0.f
;
78 v2f bmin
= { 0.f
, 0.f
};
79 v2f bmax
= { rt
->x
, rt
->y
};
81 v2_minv( tri
[0].co
, tri
[1].co
, bmin
);
82 v2_minv( tri
[2].co
, bmin
, bmin
);
84 v2_maxv( tri
[0].co
, tri
[1].co
, bmax
);
85 v2_maxv( tri
[2].co
, bmax
, bmax
);
87 float range_x
= (rt
->bounds
[1][0]-rt
->bounds
[0][0])/(float)rt
->x
;
88 float range_y
= (rt
->bounds
[1][1]-rt
->bounds
[0][1])/(float)rt
->y
;
90 int start_x
= csr_min( rt
->x
-1, csr_max( 0, floorf( (bmin
[0]-rt
->bounds
[0][0])/range_x
)));
91 int end_x
= csr_max( 0, csr_min( rt
->x
-1, floorf( (bmax
[0]-rt
->bounds
[0][0])/range_x
)));
92 int start_y
= csr_min( rt
->y
-1, csr_max( 0, ceilf( (bmin
[1]-rt
->bounds
[0][1])/range_y
)));
93 int end_y
= csr_max( 0, csr_min( rt
->y
-1, ceilf( (bmax
[1]-rt
->bounds
[0][1])/range_y
)));
95 v3f trace_dir
= { 0.f
, 0.f
, 1.f
};
96 v3f trace_origin
= { 0.f
, 0.f
, -16385.f
};
98 for( u32 py
= start_y
; py
<= end_y
; py
++ )
100 trace_origin
[1] = csr_lerpf( rt
->bounds
[0][1], rt
->bounds
[1][1], (float)py
/(float)rt
->y
);
102 for( u32 px
= start_x
; px
<= end_x
; px
++ )
104 csr_frag
*frag
= &rt
->fragments
[ py
* rt
->y
+ px
];
106 trace_origin
[0] = csr_lerpf( rt
->bounds
[0][0], rt
->bounds
[1][0], (float)px
/(float)rt
->x
);
107 float tdepth
= csr_ray_tri( trace_origin
, trace_dir
, tri
[0].co
, tri
[1].co
, tri
[2].co
, &tqa
, &tqb
);
109 if( tdepth
> frag
->depth
)
111 frag
->depth
= tdepth
;
113 v3_muls( tri
[1].co
, tqa
, frag
->co
);
114 v3_muladds( frag
->co
, tri
[2].co
, tqb
, frag
->co
);
115 v3_muladds( frag
->co
, tri
[0].co
, 1.f
- tqa
- tqb
, frag
->co
);
121 void csr_draw( csr_target
*rt
, vmf_vert
*triangles
, u32 triangle_count
, m4x3f transform
)
126 // Derive normal matrix
127 m4x3_to_3x3( transform
, normal
);
128 m3x3_inv_transpose( normal
, normal
);
130 for( u32 i
= 0; i
< triangle_count
; i
++ )
132 vmf_vert
*triangle
= triangles
+ i
*3;
134 m4x3_mulv( transform
, triangle
[0].co
, new_tri
[0].co
);
135 m4x3_mulv( transform
, triangle
[1].co
, new_tri
[1].co
);
136 m4x3_mulv( transform
, triangle
[2].co
, new_tri
[2].co
);
137 m3x3_mulv( normal
, triangle
[0].nrm
, new_tri
[0].nrm
);
138 m3x3_mulv( normal
, triangle
[1].nrm
, new_tri
[1].nrm
);
139 m3x3_mulv( normal
, triangle
[2].nrm
, new_tri
[2].nrm
);
141 simple_raster( rt
, new_tri
, 0 );
145 void draw_vmf_group( csr_target
*rt
, vmf_map
*map
, vdf_node
*root
, csr_filter
*filter
, m4x3f prev
, m4x3f inst
)
147 m4x3f transform
= M4X3_IDENTITY
;
154 int filter_visgroups
= 0, filter_classname
= 0, compute_bounds_only
= 0;
158 if( filter
->visgroup
)
160 filter_visgroups
= 1;
161 group_id
= vmf_visgroup_id( root
, filter
->visgroup
);
164 if( filter
->classname
)
166 filter_classname
= 1;
169 compute_bounds_only
= filter
->compute_bounds_only
;
172 // Multiply previous transform with instance transform to create basis
175 m4x3_mul( prev
, inst
, transform
);
178 // Gather world brushes
179 solidgen_ctx_init( &solid
);
181 if( !filter_classname
)
183 vdf_node
*world
= vdf_next( root
, "world", NULL
);
185 vdf_foreach( world
, "solid", brush
)
187 if( filter_visgroups
&& !vmf_visgroup_match( brush
, group_id
) )
190 solidgen_push( &solid
, brush
);
194 // Actual entity loop
197 vdf_foreach( root
, "entity", ent
)
199 if( filter_visgroups
&& !vmf_visgroup_match( ent
, group_id
) )
202 if( filter_classname
)
203 if( strcmp( kv_get( ent
, "classname", "" ), filter
->classname
) )
206 if( ent
->user
& VMF_FLAG_IS_PROP
)
208 // Create model transform
209 m4x3_identity( model
);
211 vmf_entity_transform( ent
, model
);
212 m4x3_mul( transform
, model
, model
);
215 mdl_mesh_t
*mdl
= &map
->models
[ ent
->user1
].mdl
;
217 if( compute_bounds_only
)
219 box_copy( mdl
->bounds
, trf_bounds
);
220 m4x3_transform_aabb( model
, trf_bounds
);
223 //box_concat( rt->bounds, trf_bounds );
227 for( int i
= 0; i
< mdl
->num_indices
/3; i
++ )
229 for( int j
= 0; j
< 3; j
++ )
231 v3_copy( &mdl
->vertices
[ mdl
->indices
[ i
*3+j
] *8 ], tri
[j
].co
);
232 v3_copy( &mdl
->vertices
[ mdl
->indices
[ i
*3+j
] *8+3 ], tri
[j
].nrm
);
237 csr_draw( rt
, tri
, 1, model
);
241 else if( ent
->user
& VMF_FLAG_IS_INSTANCE
)
243 m4x3_identity( model
);
244 vmf_entity_transform( ent
, model
);
246 draw_vmf_group( rt
, map
, map
->cache
[ ent
->user1
].root
, filter
, transform
, model
);
251 if( (ent_solid
= vdf_next( ent
, "solid", NULL
)) )
253 solidgen_push( &solid
, ent_solid
);
258 if( compute_bounds_only
)
260 solidgen_bounds( &solid
, trf_bounds
);
261 m4x3_transform_aabb( transform
, trf_bounds
);
262 box_concat( rt
->bounds
, trf_bounds
);
267 for( int i
= 0; i
< csr_sb_count( solid
.indices
)/3; i
++ )
269 u32
* base
= solid
.indices
+ i
*3;
271 tri
[0] = solid
.verts
[ base
[0] ];
272 tri
[1] = solid
.verts
[ base
[1] ];
273 tri
[2] = solid
.verts
[ base
[2] ];
275 csr_draw( rt
, tri
, 1, transform
);
279 solidgen_ctx_reset( &solid
);
280 solidgen_ctx_free( &solid
);
282 printf( "Bounds resolved to: (%.3f, %.3f, %.3f) -> (%.3f, %.3f, %.3f)\n",
283 rt
->bounds
[0][0],rt
->bounds
[0][1],rt
->bounds
[0][2],
284 rt
->bounds
[1][0],rt
->bounds
[1][1],rt
->bounds
[1][2] );