1 typedef struct csr_frag csr_frag
;
2 typedef struct csr_target csr_target
;
6 u32 id
; // Triangle index
7 float depth
; // 'depth testing'
20 void csr_rt_clear( csr_target
*rt
)
22 for( u32 i
= 0; i
< rt
->x
*rt
->y
; i
++ )
24 rt
->fragments
[ i
].depth
= 0.f
;
28 void simple_raster( csr_target
*rt
, vmf_vert tri
[3], int id
)
30 // Very simplified tracing algorithm
31 float tqa
= 0.f
, tqb
= 0.f
;
33 v2f bmin
= { 0.f
, 0.f
};
34 v2f bmax
= { rt
->x
, rt
->y
};
36 v2_minv( tri
[0].co
, tri
[1].co
, bmin
);
37 v2_minv( tri
[2].co
, bmin
, bmin
);
39 v2_maxv( tri
[0].co
, tri
[1].co
, bmax
);
40 v2_maxv( tri
[2].co
, bmax
, bmax
);
42 float range_x
= (rt
->bounds
[2]-rt
->bounds
[0])/(float)rt
->x
;
43 float range_y
= (rt
->bounds
[3]-rt
->bounds
[1])/(float)rt
->y
;
45 int start_x
= csr_min( rt
->x
-1, csr_max( 0, floorf( (bmin
[0]-rt
->bounds
[0])/range_x
)));
46 int end_x
= csr_max( 0, csr_min( rt
->x
-1, floorf( (bmax
[0]-rt
->bounds
[0])/range_x
)));
47 int start_y
= csr_min( rt
->y
-1, csr_max( 0, ceilf( (bmin
[1]-rt
->bounds
[1])/range_y
)));
48 int end_y
= csr_max( 0, csr_min( rt
->y
-1, ceilf( (bmax
[1]-rt
->bounds
[1])/range_y
)));
50 v3f trace_dir
= { 0.f
, 0.f
, 1.f
};
51 v3f trace_origin
= { 0.f
, 0.f
, -16385.f
};
53 for( u32 py
= start_y
; py
<= end_y
; py
++ )
55 trace_origin
[1] = csr_lerpf( rt
->bounds
[1], rt
->bounds
[3], (float)py
/(float)rt
->y
);
57 for( u32 px
= start_x
; px
<= end_x
; px
++ )
59 csr_frag
*frag
= &rt
->fragments
[ py
* rt
->y
+ px
];
61 trace_origin
[0] = csr_lerpf( rt
->bounds
[0], rt
->bounds
[2], (float)px
/(float)rt
->x
);
62 float tdepth
= csr_ray_tri( trace_origin
, trace_dir
, tri
[0].co
, tri
[1].co
, tri
[2].co
, &tqa
, &tqb
);
64 if( tdepth
> frag
->depth
)
68 v3_muls( tri
[1].co
, tqa
, frag
->co
);
69 v3_muladds( frag
->co
, tri
[2].co
, tqb
, frag
->co
);
70 v3_muladds( frag
->co
, tri
[0].co
, 1.f
- tqa
- tqb
, frag
->co
);
76 void csr_draw( csr_target
*rt
, vmf_vert
*triangles
, u32 triangle_count
, m4x3f transform
)
81 // Derive normal matrix
82 m4x3_to_3x3( transform
, normal
);
83 m3x3_inv_transpose( normal
, normal
);
85 for( u32 i
= 0; i
< triangle_count
; i
++ )
87 vmf_vert
*triangle
= triangles
+ i
*3;
89 m4x3_mulv( transform
, triangle
[0].co
, new_tri
[0].co
);
90 m4x3_mulv( transform
, triangle
[1].co
, new_tri
[1].co
);
91 m4x3_mulv( transform
, triangle
[2].co
, new_tri
[2].co
);
92 m3x3_mulv( normal
, triangle
[0].nrm
, new_tri
[0].nrm
);
93 m3x3_mulv( normal
, triangle
[1].nrm
, new_tri
[1].nrm
);
94 m3x3_mulv( normal
, triangle
[2].nrm
, new_tri
[2].nrm
);
96 simple_raster( rt
, new_tri
, 0 );
100 void draw_vmf_group( csr_target
*rt
, vmf_map
*map
, vdf_node
*root
, const char *group
, m4x3f prev
, m4x3f inst
)
102 m4x3f transform
= M4X3_IDENTITY
;
110 group_id
= vmf_visgroup_id( root
, group
);
113 // Multiply previous transform with instance transform to create basis
116 m4x3_mul( prev
, inst
, transform
);
120 solidgen_ctx_init( &solid
);
121 vdf_node
*world
= vdf_next( root
, "world", NULL
);
123 vdf_foreach( world
, "solid", brush
)
125 if( group
&& !vmf_visgroup_match( brush
, group_id
) )
128 solidgen_push( &solid
, brush
);
131 for( int i
= 0; i
< csr_sb_count( solid
.indices
)/3; i
++ )
133 u32
* base
= solid
.indices
+ i
*3;
135 tri
[0] = solid
.verts
[ base
[0] ];
136 tri
[1] = solid
.verts
[ base
[1] ];
137 tri
[2] = solid
.verts
[ base
[2] ];
139 csr_draw( rt
, tri
, 1, transform
);
142 solidgen_ctx_reset( &solid
);
144 // Actual entity loop
147 vdf_foreach( root
, "entity", ent
)
149 if( group
&& !vmf_visgroup_match( ent
, group_id
) )
152 if( ent
->user
& VMF_FLAG_IS_PROP
)
154 // Create model transform
155 m4x3_identity( model
);
157 vmf_entity_transform( ent
, model
);
158 m4x3_mul( transform
, model
, model
);
161 mdl_mesh_t
*mdl
= &map
->models
[ ent
->user1
].mdl
;
162 for( int i
= 0; i
< mdl
->num_indices
/3; i
++ )
164 for( int j
= 0; j
< 3; j
++ )
166 v3_copy( &mdl
->vertices
[ mdl
->indices
[ i
*3+j
] *8 ], tri
[j
].co
);
167 v3_copy( &mdl
->vertices
[ mdl
->indices
[ i
*3+j
] *8+3 ], tri
[j
].nrm
);
172 csr_draw( rt
, tri
, 1, model
);
175 else if( ent
->user
& VMF_FLAG_IS_INSTANCE
)
177 m4x3_identity( model
);
178 vmf_entity_transform( ent
, model
);
180 draw_vmf_group( rt
, map
, map
->cache
[ ent
->user1
].root
, group
, transform
, model
);
182 else if( ent
->user
& VMF_FLAG_BRUSH_ENT
)
188 solidgen_ctx_free( &solid
);