]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/surface_foliage.c
* moved zeroradiant (1.6) into trunk
[xonotic/netradiant.git] / tools / quake3 / q3map2 / surface_foliage.c
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
21 ----------------------------------------------------------------------------------
22
23 Foliage code for Wolfenstein: Enemy Territory by ydnar@splashdamage.com
24
25 ------------------------------------------------------------------------------- */
26
27
28
29 /* marker */
30 #define SURFACE_FOLIAGE_C
31
32
33
34 /* dependencies */
35 #include "q3map2.h"
36
37
38
39 #define MAX_FOLIAGE_INSTANCES   8192
40
41 static int                                              numFoliageInstances;
42 static foliageInstance_t                foliageInstances[ MAX_FOLIAGE_INSTANCES ];
43
44
45
46 /*
47 SubdivideFoliageTriangle_r()
48 recursively subdivides a triangle until the triangle is smaller than
49 the desired density, then pseudo-randomly sets a point
50 */
51
52 static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, foliage_t *foliage, bspDrawVert_t **tri )
53 {
54         bspDrawVert_t   mid, *tri2[ 3 ];
55         int                             max;
56         
57         
58         /* limit test */
59         if( numFoliageInstances >= MAX_FOLIAGE_INSTANCES )
60                 return;
61         
62         /* plane test */
63         {
64                 vec4_t          plane;
65                 
66                 
67                 /* make a plane */
68                 if( !PlaneFromPoints( plane, tri[ 0 ]->xyz, tri[ 1 ]->xyz, tri[ 2 ]->xyz ) )
69                         return;
70                 
71                 /* if normal is too far off vertical, then don't place an instance */
72                 if( plane[ 2 ] < 0.5f )
73                         return;
74         }
75         
76         /* subdivide calc */
77         {
78                 int                                     i;
79                 float                           *a, *b, dx, dy, dz, dist, maxDist;
80                 foliageInstance_t       *fi;
81                 
82                 
83                 /* get instance */
84                 fi = &foliageInstances[ numFoliageInstances ];
85                 
86                 /* find the longest edge and split it */
87                 max = -1;
88                 maxDist = 0.0f;
89                 VectorClear( fi->xyz );
90                 VectorClear( fi->normal );
91                 for( i = 0; i < 3; i++ )
92                 {
93                         /* get verts */
94                         a = tri[ i ]->xyz;
95                         b = tri[ (i + 1) % 3 ]->xyz;
96                         
97                         /* get dists */
98                         dx = a[ 0 ] - b[ 0 ];
99                         dy = a[ 1 ] - b[ 1 ];
100                         dz = a[ 2 ] - b[ 2 ];
101                         dist = (dx * dx) + (dy * dy) + (dz * dz);
102                         
103                         /* longer? */
104                         if( dist > maxDist )
105                         {
106                                 maxDist = dist;
107                                 max = i;
108                         }
109                         
110                         /* add to centroid */
111                         VectorAdd( fi->xyz, tri[ i ]->xyz, fi->xyz );
112                         VectorAdd( fi->normal, tri[ i ]->normal, fi->normal );
113                 }
114                 
115                 /* is the triangle small enough? */
116                 if( maxDist <= (foliage->density * foliage->density) )
117                 {
118                         float   alpha, odds, r;
119                         
120                         
121                         /* get average alpha */
122                         if( foliage->inverseAlpha == 2 )
123                                 alpha = 1.0f;
124                         else
125                         {
126                                 alpha = ((float) tri[ 0 ]->color[ 0 ][ 3 ] + (float) tri[ 1 ]->color[ 0 ][ 3 ] + (float) tri[ 2 ]->color[ 0 ][ 3 ]) / 765.0f;
127                                 if( foliage->inverseAlpha == 1 )
128                                         alpha = 1.0f - alpha;
129                                 if( alpha < 0.75f )
130                                         return;
131                         }
132                         
133                         /* roll the dice */
134                         odds = foliage->odds * alpha;
135                         r = Random();
136                         if( r > odds )
137                                 return;
138                         
139                         /* scale centroid */
140                         VectorScale( fi->xyz, 0.33333333f, fi->xyz );
141                         if( VectorNormalize( fi->normal, fi->normal ) == 0.0f )
142                                 return;
143                         
144                         /* add to count and return */
145                         numFoliageInstances++;
146                         return;
147                 }
148         }
149         
150         /* split the longest edge and map it */
151         LerpDrawVert( tri[ max ], tri[ (max + 1) % 3 ], &mid );
152         
153         /* recurse to first triangle */
154         VectorCopy( tri, tri2 );
155         tri2[ max ] = &mid;
156         SubdivideFoliageTriangle_r( ds, foliage, tri2 );
157         
158         /* recurse to second triangle */
159         VectorCopy( tri, tri2 );
160         tri2[ (max + 1) % 3 ] = &mid;
161         SubdivideFoliageTriangle_r( ds, foliage, tri2 );
162 }
163
164
165
166 /*
167 GenFoliage()
168 generates a foliage file for a bsp
169 */
170
171 void Foliage( mapDrawSurface_t *src )
172 {
173         int                                     i, j, k, x, y, pw[ 5 ], r, oldNumMapDrawSurfs;
174         mapDrawSurface_t        *ds;
175         shaderInfo_t            *si;
176         foliage_t                       *foliage;
177         mesh_t                          srcMesh, *subdivided, *mesh;
178         bspDrawVert_t           *verts, *dv[ 3 ], *fi;
179         vec3_t                          scale;
180         m4x4_t                          transform;
181         
182         
183         /* get shader */
184         si = src->shaderInfo;
185         if( si == NULL || si->foliage == NULL )
186                 return;
187         
188         /* do every foliage */
189         for( foliage = si->foliage; foliage != NULL; foliage = foliage->next )
190         {
191                 /* zero out */
192                 numFoliageInstances = 0;
193                 
194                 /* map the surface onto the lightmap origin/cluster/normal buffers */
195                 switch( src->type )
196                 {
197                         case SURFACE_META:
198                         case SURFACE_FORCED_META:
199                         case SURFACE_TRIANGLES:
200                                 /* get verts */
201                                 verts = src->verts;
202                                 
203                                 /* map the triangles */
204                                 for( i = 0; i < src->numIndexes; i += 3 )
205                                 {
206                                         dv[ 0 ] = &verts[ src->indexes[ i ] ];
207                                         dv[ 1 ] = &verts[ src->indexes[ i + 1 ] ];
208                                         dv[ 2 ] = &verts[ src->indexes[ i + 2 ] ];
209                                         SubdivideFoliageTriangle_r( src, foliage, dv );
210                                 }
211                                 break;
212                         
213                         case SURFACE_PATCH:
214                                 /* make a mesh from the drawsurf */ 
215                                 srcMesh.width = src->patchWidth;
216                                 srcMesh.height = src->patchHeight;
217                                 srcMesh.verts = src->verts;
218                                 subdivided = SubdivideMesh( srcMesh, 8, 512 );
219                                 
220                                 /* fit it to the curve and remove colinear verts on rows/columns */
221                                 PutMeshOnCurve( *subdivided );
222                                 mesh = RemoveLinearMeshColumnsRows( subdivided );
223                                 FreeMesh( subdivided );
224                                 
225                                 /* get verts */
226                                 verts = mesh->verts;
227                                 
228                                 /* map the mesh quads */
229                                 for( y = 0; y < (mesh->height - 1); y++ )
230                                 {
231                                         for( x = 0; x < (mesh->width - 1); x++ )
232                                         {
233                                                 /* set indexes */
234                                                 pw[ 0 ] = x + (y * mesh->width);
235                                                 pw[ 1 ] = x + ((y + 1) * mesh->width);
236                                                 pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
237                                                 pw[ 3 ] = x + 1 + (y * mesh->width);
238                                                 pw[ 4 ] = x + (y * mesh->width);        /* same as pw[ 0 ] */
239                                                 
240                                                 /* set radix */
241                                                 r = (x + y) & 1;
242                                                 
243                                                 /* get drawverts and map first triangle */
244                                                 dv[ 0 ] = &verts[ pw[ r + 0 ] ];
245                                                 dv[ 1 ] = &verts[ pw[ r + 1 ] ];
246                                                 dv[ 2 ] = &verts[ pw[ r + 2 ] ];
247                                                 SubdivideFoliageTriangle_r( src, foliage, dv );
248                                                 
249                                                 /* get drawverts and map second triangle */
250                                                 dv[ 0 ] = &verts[ pw[ r + 0 ] ];
251                                                 dv[ 1 ] = &verts[ pw[ r + 2 ] ];
252                                                 dv[ 2 ] = &verts[ pw[ r + 3 ] ];
253                                                 SubdivideFoliageTriangle_r( src, foliage, dv );
254                                         }
255                                 }
256                                 
257                                 /* free the mesh */
258                                 FreeMesh( mesh );
259                                 break;
260                         
261                         default:
262                                 break;
263                 }
264                 
265                 /* any origins? */
266                 if( numFoliageInstances < 1 )
267                         continue;
268                 
269                 /* remember surface count */
270                 oldNumMapDrawSurfs = numMapDrawSurfs;
271                 
272                 /* set transform matrix */
273                 VectorSet( scale, foliage->scale, foliage->scale, foliage->scale );
274                 m4x4_scale_for_vec3( transform, scale );
275                 
276                 /* add the model to the bsp */
277                 InsertModel( foliage->model, 0, transform, NULL, NULL, src->entityNum, src->castShadows, src->recvShadows, 0, src->lightmapScale );
278                 
279                 /* walk each new surface */
280                 for( i = oldNumMapDrawSurfs; i < numMapDrawSurfs; i++ )
281                 {
282                         /* get surface */
283                         ds = &mapDrawSurfs[ i ];
284                         
285                         /* set up */
286                         ds->type = SURFACE_FOLIAGE;
287                         ds->numFoliageInstances = numFoliageInstances;
288                         
289                         /* a wee hack */
290                         ds->patchWidth = ds->numFoliageInstances;
291                         ds->patchHeight = ds->numVerts;
292                         
293                         /* set fog to be same as source surface */
294                         ds->fogNum = src->fogNum;
295                         
296                         /* add a drawvert for every instance */
297                         verts = safe_malloc( (ds->numVerts + ds->numFoliageInstances) * sizeof( *verts ) );
298                         memset( verts, 0, (ds->numVerts + ds->numFoliageInstances) * sizeof( *verts ) );
299                         memcpy( verts, ds->verts, ds->numVerts * sizeof( *verts ) );
300                         free( ds->verts );
301                         ds->verts = verts;
302                         
303                         /* copy the verts */
304                         for( j = 0; j < ds->numFoliageInstances; j++ )
305                         {
306                                 /* get vert (foliage instance) */
307                                 fi = &ds->verts[ ds->numVerts + j ];
308
309                                 /* copy xyz and normal */
310                                 VectorCopy( foliageInstances[ j ].xyz, fi->xyz );
311                                 VectorCopy( foliageInstances[ j ].normal, fi->normal );
312
313                                 /* ydnar: set color */
314                                 for( k = 0; k < MAX_LIGHTMAPS; k++ )
315                                 {
316                                         fi->color[ k ][ 0 ] = 255;
317                                         fi->color[ k ][ 1 ] = 255;
318                                         fi->color[ k ][ 2 ] = 255;
319                                         fi->color[ k ][ 3 ] = 255;
320                                 }
321                         }
322                         
323                         /* increment */
324                         ds->numVerts += ds->numFoliageInstances;
325                 }
326         }
327 }