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