Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / RSP / RSPVertexManager.cpp
CommitLineData
22726e4d 1/******************************************************************************
2 * Arachnoid Graphics Plugin for Mupen64Plus
3 * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
4 *
5 * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program 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 this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *****************************************************************************/
21
22#include "RSPVertexManager.h"
23#include "OpenGLManager.h"
24#include "Memory.h"
25#include "RSPMatrixManager.h"
26#include "RSPLightManager.h"
27#include "OpenGLRenderer.h"
28#include "GBIDefs.h" //hmm
29#include "MathLib.h" //Transform, Vec3Normalize
30#include <cmath> //sqrt
31#include "Logger.h"
32
33//Vertex
34struct Vertex
35{
36 //Position (x,y,z)
37 short y;
38 short x;
39 unsigned short flag; //Special Flags
40 short z;
41
42 //TexCoords
43 short t;
44 short s;
45
46 //Color or Normal
47 union
48 {
49 struct { unsigned char a; unsigned char b; unsigned char g; unsigned char r; } color;
50 struct { signed char a; signed char z; signed char y; signed char x; } normal;
51 };
52};
53
54//Perfect Dark Vertex
55struct PerfectDarkVertex
56{
57 short y;
58 short x;
59 unsigned short ci; //Color Index
60 short z;
61 short t;
62 short s;
63};
64
65struct DKRTriangle
66{
67 unsigned char v2, v1, v0, flag;
68 short t0, s0;
69 short t1, s1;
70 short t2, s2;
71};
72
73//-----------------------------------------------------------------------------
74//! Constructor
75//-----------------------------------------------------------------------------
76RSPVertexManager::RSPVertexManager()
77{
78 m_openGLMgr = 0;
79 m_memory = 0;
80 m_matrixMgr = 0;
81}
82
83//-----------------------------------------------------------------------------
84//! Destructor
85//-----------------------------------------------------------------------------
86RSPVertexManager::~RSPVertexManager()
87{
88
89}
90
91//-----------------------------------------------------------------------------
92//* Initialize
93//-----------------------------------------------------------------------------
94bool RSPVertexManager::initialize(OpenGLManager* openGLMgr, Memory* memory, RSPMatrixManager* matrixMgr, RSPLightManager* lightMgr)
95{
96 m_openGLMgr = openGLMgr;
97 m_memory = memory;
98 m_matrixMgr = matrixMgr;
99 m_lightMgr = lightMgr;
100 m_texCoordGenType = TCGT_NONE;
101 m_rdramOffset = 0;
102 m_billboard = false;
103 return true;
104}
105
106//-----------------------------------------------------------------------------
107// Set Vertices
108//-----------------------------------------------------------------------------
109void RSPVertexManager::setVertices( unsigned int address, unsigned int numVertices, unsigned int firstVertexIndex)
110{
111 //Make sure address is valid
112 if ((address + sizeof( Vertex ) * numVertices) > m_memory->getRDRAMSize()) {
113 return;
114 }
115
116 //Get vertex from rdram
117 Vertex *vertex = (Vertex*) m_memory->getRDRAM(address);
118
119 //Avoid overflow. There can only be MAX_VERTICES in size.
120 if ( numVertices+firstVertexIndex >= MAX_VERTICES)
121 {
122 return;
123 }
124
125 //For each vertex
126 for (unsigned int i=firstVertexIndex; i <numVertices+firstVertexIndex; ++i)
127 {
128 m_vertices[i].x = vertex->x;
129 m_vertices[i].y = vertex->y;
130 m_vertices[i].z = vertex->z;
131 m_vertices[i].flag = vertex->flag;
132 m_vertices[i].s = _FIXED2FLOAT( vertex->s, 5 );
133 m_vertices[i].t = _FIXED2FLOAT( vertex->t, 5 );
134
135 if ( m_lightMgr->getLightEnabled() )
136 {
137 m_vertices[i].nx = vertex->normal.x;
138 m_vertices[i].ny = vertex->normal.y;
139 m_vertices[i].nz = vertex->normal.z;
140 m_vertices[i].a = vertex->color.a * 0.0039215689f;
141 }
142 else
143 {
144 m_vertices[i].r = vertex->color.r * 0.0039215689f;
145 m_vertices[i].g = vertex->color.g * 0.0039215689f;
146 m_vertices[i].b = vertex->color.b * 0.0039215689f;
147 m_vertices[i].a = vertex->color.a * 0.0039215689f;
148 }
149
150 _processVertex(i);
151 vertex++;
152 }
153}
154
155//-----------------------------------------------------------------------------
156// Modify Vertex
157//-----------------------------------------------------------------------------
158void RSPVertexManager::modifyVertex( unsigned int vtx, unsigned int where, unsigned int val )
159{
160 switch (where)
161 {
162 case G_MWO_POINT_RGBA:
163 m_vertices[vtx].r = _SHIFTR( val, 24, 8 ) * 0.0039215689f;
164 m_vertices[vtx].g = _SHIFTR( val, 16, 8 ) * 0.0039215689f;
165 m_vertices[vtx].b = _SHIFTR( val, 8, 8 ) * 0.0039215689f;
166 m_vertices[vtx].a = _SHIFTR( val, 0, 8 ) * 0.0039215689f;
167 break;
168 case G_MWO_POINT_ST:
169 m_vertices[vtx].s = _FIXED2FLOAT( (short)_SHIFTR( val, 16, 16 ), 5 );
170 m_vertices[vtx].t = _FIXED2FLOAT( (short)_SHIFTR( val, 0, 16 ), 5 );
171 break;
172 case G_MWO_POINT_XYSCREEN:
173 break;
174 case G_MWO_POINT_ZSCREEN:
175 break;
176 }
177}
178
179void RSPVertexManager::setVertexColor(unsigned int vertexIndex, float r, float g, float b, float a)
180{
181 m_vertices[vertexIndex].r = r;
182 m_vertices[vertexIndex].g = g;
183 m_vertices[vertexIndex].b = b;
184 m_vertices[vertexIndex].a = a;
185}
186
187void RSPVertexManager::setVertexTextureCoord(unsigned int vertexIndex, float s, float t)
188{
189 m_vertices[vertexIndex].s = s;
190 m_vertices[vertexIndex].t = t;
191}
192
193
194//-----------------------------------------------------------------------------
195// ?
196//-----------------------------------------------------------------------------
197void RSPVertexManager::ciVertex(unsigned int segmentAddress, unsigned int numVertices, unsigned int firstVertexIndex)
198{
199 unsigned int rdramAddress = m_memory->getRDRAMAddress(segmentAddress);
200
201 if ((rdramAddress + sizeof(PerfectDarkVertex) * numVertices) > m_memory->getRDRAMSize())
202 {
203 return;
204 }
205
206 PerfectDarkVertex* vertex = (PerfectDarkVertex*)m_memory->getRDRAM(rdramAddress);
207
208 //Avoid overflow. There can only be MAX_VERTICES in size.
209 if ( numVertices+firstVertexIndex >= MAX_VERTICES)
210 {
211 return;
212 }
213
214 //For each vertex
215 for (unsigned int i=firstVertexIndex; i <numVertices+firstVertexIndex; ++i)
216 {
217 m_vertices[i].x = vertex->x;
218 m_vertices[i].y = vertex->y;
219 m_vertices[i].z = vertex->z;
220 m_vertices[i].flag = 0;
221 m_vertices[i].s = _FIXED2FLOAT( vertex->s, 5 );
222 m_vertices[i].t = _FIXED2FLOAT( vertex->t, 5 );
223
224 //Get color
225 unsigned char* color = m_memory->getRDRAM(m_colorBaseRDRAMAddress + (vertex->ci & 0xff));
226
227 //Assign color
228 if ( m_lightMgr->getLightEnabled() )
229 {
230 m_vertices[i].nx = (short)color[3];
231 m_vertices[i].ny = (short)color[2];
232 m_vertices[i].nz = (short)color[1];
233 m_vertices[i].a = color[0] * 0.0039215689f;
234 }
235 else
236 {
237 m_vertices[i].r = color[3] * 0.0039215689f;
238 m_vertices[i].g = color[2] * 0.0039215689f;
239 m_vertices[i].b = color[1] * 0.0039215689f;
240 m_vertices[i].a = color[0] * 0.0039215689f;
241 }
242
243 _processVertex( i );
244 vertex++;
245 }
246}
247
248//-----------------------------------------------------------------------------
249// ?
250//-----------------------------------------------------------------------------
251void RSPVertexManager::DMAVertex( unsigned int v, unsigned int numVertices, unsigned int firstVertexIndex)
252{
253 unsigned int address = m_rdramOffset + m_memory->getRDRAMAddress( v );
254
255 if ((address + 10 * numVertices) > m_memory->getRDRAMSize())
256 {
257 return;
258 }
259
260 unsigned char* RDRAM = m_memory->getRDRAM();
261
262 if ((numVertices + firstVertexIndex) < (80))
263 {
264 for (unsigned int i = firstVertexIndex; i < numVertices + firstVertexIndex; i++)
265 {
266 m_vertices[i].x = *(short*)&RDRAM[address ^ 2];
267 m_vertices[i].y = *(short*)&RDRAM[(address + 2) ^ 2];
268 m_vertices[i].z = *(short*)&RDRAM[(address + 4) ^ 2];
269
270 if ( m_lightMgr->getLightEnabled() )
271 {
272 m_vertices[i].nx = *(char*)&RDRAM[(address + 6) ^ 3];
273 m_vertices[i].ny = *(char*)&RDRAM[(address + 7) ^ 3];
274 m_vertices[i].nz = *(char*)&RDRAM[(address + 8) ^ 3];
275 m_vertices[i].a = *(unsigned char*)&RDRAM[(address + 9) ^ 3] * 0.0039215689f;
276 }
277 else
278 {
279 m_vertices[i].r = *(unsigned char*)&RDRAM[(address + 6) ^ 3] * 0.0039215689f;
280 m_vertices[i].g = *(unsigned char*)&RDRAM[(address + 7) ^ 3] * 0.0039215689f;
281 m_vertices[i].b = *(unsigned char*)&RDRAM[(address + 8) ^ 3] * 0.0039215689f;
282 m_vertices[i].a = *(unsigned char*)&RDRAM[(address + 9) ^ 3] * 0.0039215689f;
283 }
284
285 _processVertex( i );
286
287 address += 10;
288 }
289 }
290}
291
292//-----------------------------------------------------------------------------
293// ?
294//-----------------------------------------------------------------------------
295void RSPVertexManager::DMAOffsets( unsigned int mtxoffset, unsigned int vtxoffset )
296{
297 static bool warned = false;
298 if ( !warned ) {
299 Logger::getSingleton().printMsg("VertexManager - DMAOffsets - Unimplemented", M64MSG_WARNING);
300 warned = true;
301 }
302}
303
304//-----------------------------------------------------------------------------
305//! @param v0 Index of first vertex in triangle
306//! @param v1 Index of second vertex in triangle
307//! @param v2 Index of third vertex in triangle
308//-----------------------------------------------------------------------------
309bool RSPVertexManager::add1Triangle(unsigned int v0, unsigned int v1, unsigned int v2 )
310{
311 bool triangleAdded = false;
312
313 if (true)//IsTriangleVisible(dwV0, dwV1, dwV2))
314 {
315 if ( !((v0 < MAX_VERTICES) && (v1 < MAX_VERTICES) && (v2 < MAX_VERTICES)) )
316 {
317 return false;
318 }
319
320 // Don't bother with triangles completely outside clipping frustrum
321 if (((m_vertices[v0].xClip < 0.0f) && (m_vertices[v1].xClip < 0.0f) && (m_vertices[v2].xClip < 0.0f)) ||
322 ((m_vertices[v0].xClip > 0.0f) && (m_vertices[v1].xClip > 0.0f) && (m_vertices[v2].xClip > 0.0f)) ||
323 ((m_vertices[v0].yClip < 0.0f) && (m_vertices[v1].yClip < 0.0f) && (m_vertices[v2].yClip < 0.0f)) ||
324 ((m_vertices[v0].yClip > 0.0f) && (m_vertices[v1].yClip > 0.0f) && (m_vertices[v2].yClip > 0.0f)) ||
325 ((m_vertices[v0].zClip > 0.1f) && (m_vertices[v1].zClip > 0.1f) && (m_vertices[v2].zClip > 0.1f)) ||
326 ((m_vertices[v0].zClip < -0.1f) && (m_vertices[v1].zClip < -0.1f) && (m_vertices[v2].zClip < -0.1f)) )
327 {
328 return false;
329 }
330 triangleAdded = true;
331
332 //Add vertex to vertex buffer
333 OpenGLRenderer::getSingleton().addTriangle( m_vertices, v0, v1, v2 );
334 }
335
336 return triangleAdded;
337}
338
339void RSPVertexManager::add2Triangles( int v00, int v01, int v02, int flag0,
340 int v10, int v11, int v12, int flag1 )
341{
342 //implemented by calling add1Triangle multiple times
343
344 static bool warned = false;
345 if ( !warned ) {
346 Logger::getSingleton().printMsg("VertexManager - add2Triangles - Unimplemented", M64MSG_WARNING);
347 warned = true;
348 }
349}
350
351void RSPVertexManager::add4Triangles( int v00, int v01, int v02,
352 int v10, int v11, int v12,
353 int v20, int v21, int v22,
354 int v30, int v31, int v32 )
355{
356 //implemented by calling add1Triangle multiple times
357
358
359 static bool warned = false;
360 if ( !warned ) {
361 Logger::getSingleton().printMsg("VertexManager - add4Triangles - Unimplemented", M64MSG_WARNING);
362 warned = true;
363 }
364}
365
366//! @todo Set culling
367void RSPVertexManager::addDMATriangles( unsigned int tris, unsigned int n )
368{
369 unsigned int address = m_memory->getRDRAMAddress(tris);
370
371 if (address + sizeof( DKRTriangle ) * n > m_memory->getRDRAMSize() )
372 {
373 return;
374 }
375
376 DKRTriangle *triangles = (DKRTriangle*)m_memory->getRDRAM(address);
377
378 for (unsigned int i = 0; i < n; i++)
379 {
380 //TODO Set culling
381 //gSP.geometryMode &= ~G_CULL_BOTH;
382 //if (!(triangles->flag & 0x40))
383 //{
384 // if (gSP.viewport.vscale[0] > 0)
385 // gSP.geometryMode |= G_CULL_BACK;
386 // else
387 // gSP.geometryMode |= G_CULL_FRONT;
388 //}
389 //gSP.changed |= CHANGED_GEOMETRYMODE;
390 glDisable(GL_CULL_FACE);
391
392 m_vertices[triangles->v0].s = _FIXED2FLOAT( triangles->s0, 5 );
393 m_vertices[triangles->v0].t = _FIXED2FLOAT( triangles->t0, 5 );
394 m_vertices[triangles->v1].s = _FIXED2FLOAT( triangles->s1, 5 );
395 m_vertices[triangles->v1].t = _FIXED2FLOAT( triangles->t1, 5 );
396 m_vertices[triangles->v2].s = _FIXED2FLOAT( triangles->s2, 5 );
397 m_vertices[triangles->v2].t = _FIXED2FLOAT( triangles->t2, 5 );
398
399 add1Triangle( triangles->v0, triangles->v1, triangles->v2 /*, 0 */ );
400
401 triangles++;
402 }
403}
404
405
406void RSPVertexManager::setConkerAddress(unsigned int segmentAddress)
407{
408 m_conkerRDRAMAddress = m_memory->getRDRAMAddress(segmentAddress);
409}
410
411
412void RSPVertexManager::add1Quadrangle( int v0, int v1, int v2, int v4 )
413{
414 //implemented by calling add1Triangle multiple times
415
416 static bool warned = false;
417 if ( !warned ) {
418 Logger::getSingleton().printMsg("VertexManager - add1Quadrangle - Unimplemented", M64MSG_WARNING);
419 warned = true;
420 }
421}
422
423
424inline float DotProduct( float* v0, float* v1 )
425{
426 float dot;
427 dot = v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
428 return dot;
429}
430
431
432void RSPVertexManager::_processVertex( unsigned int v )
433{
434// float intensity;
435// float r, g, b;
436
437 transformVertex( m_matrixMgr->getViewProjectionMatrix(), &m_vertices[v].x, &m_vertices[v].x);
438 //TransformVertex( &m_vertices[v].x, m_worldProject );
439
440
441 if ( m_billboard )
442 {
443 m_vertices[v].x += m_vertices[0].x;
444 m_vertices[v].y += m_vertices[0].y;
445 m_vertices[v].z += m_vertices[0].z;
446 m_vertices[v].w += m_vertices[0].w;
447 }
448
449
450 if ( !OpenGLManager::getSingleton().getZBufferEnabled() )
451 {
452 m_vertices[v].z = -m_vertices[v].w;
453 }
454
455 //Temporary variables
456 float intensity;
457 float r, g, b;
458
459 if ( m_lightMgr->getLightEnabled() )
460 {
461 //Transform normal
462 transformVector( m_matrixMgr->getModelViewMatrix(), &m_vertices[v].nx, &m_vertices[v].nx );
463 Vec3Normalize( &m_vertices[v].nx );
464
465 //Get Ambient Color
466 const float* ambientColor = m_lightMgr->getAmbientLight();
467 r = ambientColor[0];
468 g = ambientColor[1];
469 b = ambientColor[2];
470
471 for (int i=0; i<m_lightMgr->getNumLights(); ++i)
472 {
473 intensity = DotProduct( (float*)&m_vertices[v].nx, (float*)m_lightMgr->getLightDirection(i) );
474
475 if (intensity < 0.0f) intensity = 0.0f;
476
477 const float* lightColor = m_lightMgr->getLightColor(i);
478 r += lightColor[0] * intensity;
479 g += lightColor[1] * intensity;
480 b += lightColor[2] * intensity;
481 }
482
483 //Set Color
484 m_vertices[v].r = r;
485 m_vertices[v].g = g;
486 m_vertices[v].b = b;
487 }
488
489 //Texture Generation
490 if ( m_texCoordGenType != TCGT_NONE )
491 {
492 transformVector( m_matrixMgr->getProjectionMatrix(), &m_vertices[v].nx, &m_vertices[v].nx );
493
494 Vec3Normalize( &m_vertices[v].nx );
495
496 if ( m_texCoordGenType == TCGT_LINEAR )
497 {
498 m_vertices[v].s = acosf(m_vertices[v].nx) * 325.94931f;
499 m_vertices[v].t = acosf(m_vertices[v].ny) * 325.94931f;
500 }
501 else // TGT_GEN
502 {
503 m_vertices[v].s = (m_vertices[v].nx + 1.0f) * 512.0f;
504 m_vertices[v].t = (m_vertices[v].ny + 1.0f) * 512.0f;
505 }
506 }
507
508 //Clipping
509 if (m_vertices[v].x < -m_vertices[v].w)
510 m_vertices[v].xClip = -1.0f;
511 else if (m_vertices[v].x > m_vertices[v].w)
512 m_vertices[v].xClip = 1.0f;
513 else
514 m_vertices[v].xClip = 0.0f;
515
516 if (m_vertices[v].y < -m_vertices[v].w)
517 m_vertices[v].yClip = -1.0f;
518 else if (m_vertices[v].y > m_vertices[v].w)
519 m_vertices[v].yClip = 1.0f;
520 else
521 m_vertices[v].yClip = 0.0f;
522
523 if (m_vertices[v].w <= 0.0f)
524 m_vertices[v].zClip = -1.0f;
525 else if (m_vertices[v].z < -m_vertices[v].w)
526 m_vertices[v].zClip = -0.1f;
527 else if (m_vertices[v].z > m_vertices[v].w)
528 m_vertices[v].zClip = 1.0f;
529 else
530 m_vertices[v].zClip = 0.0f;
531
532}
533
534
535void RSPVertexManager::addConkerVertices(unsigned int segmentAddress, unsigned int n, unsigned int v0 )
536{
537 unsigned int numVertices = n;
538 unsigned int firstVertexIndex = v0;
539 unsigned int address = m_memory->getRDRAMAddress( segmentAddress );
540
541 //Make sure address is valid
542 if ((address + sizeof( Vertex ) * numVertices) > m_memory->getRDRAMSize()) {
543 return;
544 }
545
546 //Get vertex from rdram
547 Vertex *vertex = (Vertex*) m_memory->getRDRAM(address);
548
549
550 //For each vertex
551 for (unsigned int i=firstVertexIndex; i <numVertices+firstVertexIndex; ++i)
552 {
553 m_vertices[i].x = vertex->x;
554 m_vertices[i].y = vertex->y;
555 m_vertices[i].z = vertex->z;
556 m_vertices[i].flag = vertex->flag;
557 m_vertices[i].s = _FIXED2FLOAT( vertex->s, 5 );
558 m_vertices[i].t = _FIXED2FLOAT( vertex->t, 5 );
559
560 if ( m_lightMgr->getLightEnabled() )
561 {
562 m_vertices[i].nx = vertex->normal.x;
563 m_vertices[i].ny = vertex->normal.y;
564 m_vertices[i].nz = vertex->normal.z;
565 m_vertices[i].a = vertex->color.a * 0.0039215689f;
566 }
567 else
568 {
569 m_vertices[i].r = vertex->color.r * 0.0039215689f;
570 m_vertices[i].g = vertex->color.g * 0.0039215689f;
571 m_vertices[i].b = vertex->color.b * 0.0039215689f;
572 m_vertices[i].a = vertex->color.a * 0.0039215689f;
573 }
574
575 _processVertex(i);
576 vertex++;
577 }
578}