1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 
20 //
21 // rb_batch.c
22 //
23 
24 #include "rb_local.h"
25 
26 /*
27 =============
28 RB_BackendOverflow
29 =============
30 */
RB_BackendOverflow(int numVerts,int numIndexes)31 qBool RB_BackendOverflow (int numVerts, int numIndexes)
32 {
33 	return (rb.numVerts + numVerts > RB_MAX_VERTS
34 		|| rb.numIndexes + numIndexes > RB_MAX_INDEXES);
35 }
36 
37 
38 /*
39 =============
40 RB_InvalidMesh
41 =============
42 */
RB_InvalidMesh(const mesh_t * mesh)43 qBool RB_InvalidMesh (const mesh_t *mesh)
44 {
45 	return (!mesh->numVerts
46 		|| !mesh->numIndexes
47 		|| mesh->numVerts > RB_MAX_VERTS
48 		|| mesh->numIndexes > RB_MAX_INDEXES);
49 }
50 
51 
52 /*
53 =============
54 RB_PushTriangleIndexes
55 =============
56 */
57 #if SHADOW_VOLUMES
RB_PushTriangleIndexes(index_t * indexes,int * neighbors,vec3_t * trNormals,int count,meshFeatures_t meshFeatures)58 static inline void RB_PushTriangleIndexes (index_t *indexes, int *neighbors, vec3_t *trNormals, int count, meshFeatures_t meshFeatures)
59 {
60 	int		numTris;
61 #else
62 static inline void RB_PushTriangleIndexes (index_t *indexes, int count, meshFeatures_t meshFeatures)
63 {
64 #endif
65 	index_t	*currentIndex;
66 
67 	if (meshFeatures & MF_NONBATCHED) {
68 		rb.numIndexes = count;
69 		rb.inIndices = indexes;
70 
71 #ifdef SHADOW_VOLUMES
72 		if (neighbors) {
73 			rb.inNeighbors = neighbors;
74 			rb.curTrNeighbor = rb.inNeighbors + rb.numIndexes;
75 		}
76 
77 		if (meshFeatures & MF_TRNORMALS && trNormals) {
78 			numTris = rb.numIndexes / 3;
79 			rb.inTrNormals = trNormals;
80 			rb.curTrNormal = rb.inTrNormals[0] + numTris;
81 		}
82 #endif
83 	}
84 	else {
85 #ifdef SHADOW_VOLUMES
86 		numTris = rb.numIndexes / 3;
87 #endif
88 		currentIndex = rb.batch.indices + rb.numIndexes;
89 		rb.numIndexes += count;
90 		rb.inIndices = rb.batch.indices;
91 
92 		// The following code assumes that R_PushIndexes is fed with triangles
93 		for ( ; count>0 ; count-=3, indexes+=3, currentIndex+=3) {
94 			currentIndex[0] = rb.numVerts + indexes[0];
95 			currentIndex[1] = rb.numVerts + indexes[1];
96 			currentIndex[2] = rb.numVerts + indexes[2];
97 
98 #if SHADOW_VOLUMES
99 			if (neighbors) {
100 				rb.curTrNeighbor[0] = numTris + neighbors[0];
101 				rb.curTrNeighbor[1] = numTris + neighbors[1];
102 				rb.curTrNeighbor[2] = numTris + neighbors[2];
103 
104 				neighbors += 3;
105 				rb.curTrNeighbor += 3;
106 			}
107 
108 			if (meshFeatures & MF_TRNORMALS && trNormals) {
109 				Vec3Copy (*trNormals, rb.curTrNormal);
110 				trNormals++;
111 				rb.curTrNormal += 3;
112 			}
113 #endif
114 		}
115 	}
116 }
117 
118 
119 /*
120 =============
121 R_PushTrifanIndexes
122 =============
123 */
124 static inline void R_PushTrifanIndexes (int numVerts)
125 {
126 	index_t	*currentIndex;
127 	int		count;
128 
129 	currentIndex = rb.batch.indices + rb.numIndexes;
130 	rb.numIndexes += (numVerts - 2) * 3;
131 	rb.inIndices = rb.batch.indices;
132 
133 	for (count=2 ; count<numVerts ; count++, currentIndex+=3) {
134 		currentIndex[0] = rb.numVerts;
135 		currentIndex[1] = rb.numVerts + count - 1;
136 		currentIndex[2] = rb.numVerts + count;
137 	}
138 }
139 
140 
141 /*
142 =============
143 RB_PushMesh
144 =============
145 */
146 void RB_PushMesh (mesh_t *mesh, meshFeatures_t meshFeatures)
147 {
148 	int		i;
149 
150 	assert (mesh->numVerts);
151 
152 	rb.curMeshFeatures = meshFeatures;
153 
154 	// Push indexes
155 	if (meshFeatures & MF_TRIFAN)
156 		R_PushTrifanIndexes (mesh->numVerts);
157 	else
158 #if SHADOW_VOLUMES
159 		RB_PushTriangleIndexes (mesh->indexArray, mesh->trNeighborsArray, mesh->trNormalsArray, mesh->numIndexes, meshFeatures);
160 #else
161 		RB_PushTriangleIndexes (mesh->indexArray, mesh->numIndexes, meshFeatures);
162 #endif
163 
164 	// Push the rest
165 	if (meshFeatures & MF_NONBATCHED) {
166 		rb.numVerts = 0;
167 
168 		// Vertexes and normals
169 		if (meshFeatures & MF_DEFORMVS) {
170 			if (mesh->vertexArray != rb.batch.vertices) {
171 				for (i=0 ; i<mesh->numVerts ; i++) {
172 					rb.batch.vertices[rb.numVerts+i][0] = mesh->vertexArray[i][0];
173 					rb.batch.vertices[rb.numVerts+i][1] = mesh->vertexArray[i][1];
174 					rb.batch.vertices[rb.numVerts+i][2] = mesh->vertexArray[i][2];
175 				}
176 			}
177 			rb.inVertices = rb.batch.vertices;
178 
179 			if (meshFeatures & MF_NORMALS && mesh->normalsArray) {
180 				if (mesh->normalsArray != rb.batch.normals) {
181 					for (i=0 ; i<mesh->numVerts ; i++) {
182 						rb.batch.normals[rb.numVerts+i][0] = mesh->normalsArray[i][0];
183 						rb.batch.normals[rb.numVerts+i][1] = mesh->normalsArray[i][1];
184 						rb.batch.normals[rb.numVerts+i][2] = mesh->normalsArray[i][2];
185 					}
186 				}
187 				rb.inNormals = rb.batch.normals;
188 			}
189 		}
190 		else {
191 			rb.inVertices = mesh->vertexArray;
192 
193 			if (meshFeatures & MF_NORMALS && mesh->normalsArray)
194 				rb.inNormals = mesh->normalsArray;
195 		}
196 
197 		// Texture coordinates
198 		if (meshFeatures & MF_STCOORDS && mesh->coordArray)
199 			rb.inCoords = mesh->coordArray;
200 
201 		// Lightmap texture coordinates
202 		if (meshFeatures & MF_LMCOORDS && mesh->lmCoordArray)
203 			rb.inLMCoords = mesh->lmCoordArray;
204 
205 		// STVectors
206 		if (meshFeatures & MF_STVECTORS) {
207 			if (mesh->sVectorsArray)
208 				rb.inSVectors = mesh->sVectorsArray;
209 			if (mesh->tVectorsArray)
210 				rb.inTVectors = mesh->tVectorsArray;
211 		}
212 
213 		// Colors
214 		if (meshFeatures & MF_COLORS && mesh->colorArray) {
215 			for (i=0 ; i<mesh->numVerts ; i++) {
216 				rb.batch.colors[rb.numVerts+i][0] = mesh->colorArray[i][0];
217 				rb.batch.colors[rb.numVerts+i][1] = mesh->colorArray[i][1];
218 				rb.batch.colors[rb.numVerts+i][2] = mesh->colorArray[i][2];
219 				rb.batch.colors[rb.numVerts+i][3] = mesh->colorArray[i][3];
220 			}
221 			rb.inColors = rb.batch.colors;
222 		}
223 	}
224 	else {
225 		ri.pc.meshBatches++;
226 
227 		// Vertexes and colors
228 		if (meshFeatures & MF_COLORS && mesh->colorArray) {
229 			for (i=0 ; i<mesh->numVerts ; i++) {
230 				rb.batch.vertices[rb.numVerts+i][0] = mesh->vertexArray[i][0];
231 				rb.batch.vertices[rb.numVerts+i][1] = mesh->vertexArray[i][1];
232 				rb.batch.vertices[rb.numVerts+i][2] = mesh->vertexArray[i][2];
233 
234 				rb.batch.colors[rb.numVerts+i][0] = mesh->colorArray[i][0];
235 				rb.batch.colors[rb.numVerts+i][1] = mesh->colorArray[i][1];
236 				rb.batch.colors[rb.numVerts+i][2] = mesh->colorArray[i][2];
237 				rb.batch.colors[rb.numVerts+i][3] = mesh->colorArray[i][3];
238 			}
239 			rb.inColors = rb.batch.colors;
240 		}
241 		else {
242 			for (i=0 ; i<mesh->numVerts ; i++) {
243 				rb.batch.vertices[rb.numVerts+i][0] = mesh->vertexArray[i][0];
244 				rb.batch.vertices[rb.numVerts+i][1] = mesh->vertexArray[i][1];
245 				rb.batch.vertices[rb.numVerts+i][2] = mesh->vertexArray[i][2];
246 			}
247 		}
248 		rb.inVertices = rb.batch.vertices;
249 
250 		// Normals
251 		if (meshFeatures & MF_NORMALS && mesh->normalsArray) {
252 			for (i=0 ; i<mesh->numVerts ; i++) {
253 				rb.batch.normals[rb.numVerts+i][0] = mesh->normalsArray[i][0];
254 				rb.batch.normals[rb.numVerts+i][1] = mesh->normalsArray[i][1];
255 				rb.batch.normals[rb.numVerts+i][2] = mesh->normalsArray[i][2];
256 			}
257 			rb.inNormals = rb.batch.normals;
258 		}
259 
260 		// Texture coordinates
261 		if (meshFeatures & MF_STCOORDS && mesh->coordArray) {
262 			for (i=0 ; i<mesh->numVerts ; i++) {
263 				rb.batch.coords[rb.numVerts+i][0] = mesh->coordArray[i][0];
264 				rb.batch.coords[rb.numVerts+i][1] = mesh->coordArray[i][1];
265 			}
266 			rb.inCoords = rb.batch.coords;
267 		}
268 
269 		// Lightmap texture coordinates
270 		if (meshFeatures & MF_LMCOORDS && mesh->lmCoordArray) {
271 			for (i=0 ; i<mesh->numVerts ; i++) {
272 				rb.batch.lmCoords[rb.numVerts+i][0] = mesh->lmCoordArray[i][0];
273 				rb.batch.lmCoords[rb.numVerts+i][1] = mesh->lmCoordArray[i][1];
274 			}
275 			rb.inLMCoords = rb.batch.lmCoords;
276 		}
277 
278 		// STVectors
279 		if (meshFeatures & MF_STVECTORS) {
280 			if (mesh->sVectorsArray && mesh->tVectorsArray) {
281 				for (i=0 ; i<mesh->numVerts ; i++) {
282 					rb.batch.sVectors[rb.numVerts+i][0] = mesh->sVectorsArray[i][0];
283 					rb.batch.sVectors[rb.numVerts+i][1] = mesh->sVectorsArray[i][1];
284 					rb.batch.sVectors[rb.numVerts+i][2] = mesh->sVectorsArray[i][2];
285 					rb.batch.tVectors[rb.numVerts+i][0] = mesh->tVectorsArray[i][0];
286 					rb.batch.tVectors[rb.numVerts+i][1] = mesh->tVectorsArray[i][1];
287 					rb.batch.tVectors[rb.numVerts+i][2] = mesh->tVectorsArray[i][2];
288 				}
289 				rb.inSVectors = rb.batch.sVectors;
290 				rb.inTVectors = rb.batch.tVectors;
291 			}
292 			else {
293 				if (mesh->sVectorsArray) {
294 					for (i=0 ; i<mesh->numVerts ; i++) {
295 						rb.batch.sVectors[rb.numVerts+i][0] = mesh->sVectorsArray[i][0];
296 						rb.batch.sVectors[rb.numVerts+i][1] = mesh->sVectorsArray[i][1];
297 						rb.batch.sVectors[rb.numVerts+i][2] = mesh->sVectorsArray[i][2];
298 					}
299 					rb.inSVectors = rb.batch.sVectors;
300 				}
301 				if (mesh->tVectorsArray) {
302 					for (i=0 ; i<mesh->numVerts ; i++) {
303 						rb.batch.tVectors[rb.numVerts+i][0] = mesh->tVectorsArray[i][0];
304 						rb.batch.tVectors[rb.numVerts+i][1] = mesh->tVectorsArray[i][1];
305 						rb.batch.tVectors[rb.numVerts+i][2] = mesh->tVectorsArray[i][2];
306 					}
307 					rb.inTVectors = rb.batch.tVectors;
308 				}
309 			}
310 		}
311 	}
312 
313 	rb.numVerts += mesh->numVerts;
314 }
315