the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2
3
4#ifdef SN_TARGET_PS3_SPU
5#include <stdint.h>
6#include <stddef.h>
7#include <stdlib.h>
8#include <spu_intrinsics.h>
9#include <cell/spurs.h>
10#include <cell/dma.h>
11#include <math.h>
12#include "..\Common\spu_assert.h"
13#endif // SN_TARGET_PS3_SPU
14
15#include "Tesselator_SPU.h"
16
17static const bool sc_verbose = false;
18// #include "..\Minecraft.World\BasicTypeContainers.h"
19// #include "..\Minecraft.World\FloatBuffer.h"
20// #include "..\Minecraft.World\IntBuffer.h"
21// #include "..\Minecraft.World\ByteBuffer.h"
22
23#ifdef SN_TARGET_PS3_SPU
24
25const int GL_LINES = 4;//C4JRender::PRIMITIVE_TYPE_LINE_LIST;
26const int GL_LINE_STRIP = 5;//C4JRender::PRIMITIVE_TYPE_LINE_STRIP;
27const int GL_QUADS = 3;//C4JRender::PRIMITIVE_TYPE_QUAD_LIST;
28const int GL_TRIANGLE_FAN = 2;//C4JRender::PRIMITIVE_TYPE_TRIANGLE_FAN;
29const int GL_TRIANGLE_STRIP = 1;//C4JRender::PRIMITIVE_TYPE_TRIANGLE_STRIP;
30
31#endif
32
33bool Tesselator_SPU::TRIANGLE_MODE = false;
34// bool Tesselator_SPU::USE_VBO = false;
35
36/* Things to check we are intialising in the constructor...
37
38
39
40double u, v;
41int col;
42int mode;
43double xo, yo, zo;
44int normal;
45
46
47
48
49
50
51*/
52////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53// taken from http://my.safaribooksonline.com/book/programming/opengl/9780321563835/gl-half-float-oes/app01lev1sec2
54
55// -15 stored using a single precision bias of 127
56const unsigned int HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
57// max exponent value in single precision that will be converted
58// to Inf or Nan when stored as a half-float
59const unsigned int HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
60
61// 255 is the max exponent biased value
62const unsigned int FLOAT_MAX_BIASED_EXP = (0xFF << 23);
63
64const unsigned int HALF_FLOAT_MAX_BIASED_EXP = (0x1F << 10);
65
66typedef unsigned short hfloat;
67
68hfloat convertFloatToHFloat(float f)
69{
70 unsigned int x = *(unsigned int *)&f;
71 unsigned int sign = (unsigned short)(x >> 31);
72 unsigned int mantissa;
73 unsigned int exp;
74 hfloat hf;
75
76 // get mantissa
77 mantissa = x & ((1 << 23) - 1);
78 // get exponent bits
79 exp = x & FLOAT_MAX_BIASED_EXP;
80 if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
81 {
82 // check if the original single precision float number is a NaN
83 if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
84 {
85 // we have a single precision NaN
86 mantissa = (1 << 23) - 1;
87 }
88 else
89 {
90 // 16-bit half-float representation stores number as Inf
91 mantissa = 0;
92 }
93 hf = (((hfloat)sign) << 15) | (hfloat)(HALF_FLOAT_MAX_BIASED_EXP) |
94 (hfloat)(mantissa >> 13);
95 }
96 // check if exponent is <= -15
97 else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
98 {
99
100 // store a denorm half-float value or zero
101 exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
102 mantissa >>= (14 + exp);
103
104 hf = (((hfloat)sign) << 15) | (hfloat)(mantissa);
105 }
106 else
107 {
108 hf = (((hfloat)sign) << 15) |
109 (hfloat)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) |
110 (hfloat)(mantissa >> 13);
111 }
112
113 return hf;
114}
115
116float convertHFloatToFloat(hfloat hf)
117{
118 unsigned int sign = (unsigned int)(hf >> 15);
119 unsigned int mantissa = (unsigned int)(hf & ((1 << 10) - 1));
120 unsigned int exp = (unsigned int)(hf & HALF_FLOAT_MAX_BIASED_EXP);
121 unsigned int f;
122
123 if (exp == HALF_FLOAT_MAX_BIASED_EXP)
124 {
125 // we have a half-float NaN or Inf
126 // half-float NaNs will be converted to a single precision NaN
127 // half-float Infs will be converted to a single precision Inf
128 exp = FLOAT_MAX_BIASED_EXP;
129 if (mantissa)
130 mantissa = (1 << 23) - 1; // set all bits to indicate a NaN
131 }
132 else if (exp == 0x0)
133 {
134 // convert half-float zero/denorm to single precision value
135 if (mantissa)
136 {
137 mantissa <<= 1;
138 exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
139 // check for leading 1 in denorm mantissa
140 while ((mantissa & (1 << 10)) == 0)
141 {
142 // for every leading 0, decrement single precision exponent by 1
143 // and shift half-float mantissa value to the left
144 mantissa <<= 1;
145 exp -= (1 << 23);
146 }
147 // clamp the mantissa to 10-bits
148 mantissa &= ((1 << 10) - 1);
149 // shift left to generate single-precision mantissa of 23-bits
150 mantissa <<= 13;
151 }
152 }
153 else
154 {
155 // shift left to generate single-precision mantissa of 23-bits
156 mantissa <<= 13;
157 // generate single precision biased exponent value
158 exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
159 }
160
161 f = (sign << 31) | exp | mantissa;
162 return *((float *)&f);
163}
164
165
166////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
167
168
169// DWORD Tesselator_SPU::tlsIdx = TlsAlloc();
170//
171Tesselator_SPU *Tesselator_SPU::getInstance()
172{
173 return NULL;
174// return (Tesselator_SPU *)TlsGetValue(tlsIdx);
175}
176
177// void Tesselator_SPU::CreateNewThreadStorage(int bytes)
178// {
179// Tesselator_SPU *instance = new Tesselator_SPU(bytes/4);
180// TlsSetValue(tlsIdx, instance);
181// }
182
183
184
185 void Tesselator_SPU::end()
186 {
187// // if (!tesselating) throw new IllegalStateException("Not tesselating!"); // 4J - removed
188// tesselating = false;
189// if (vertices > 0)
190// {
191// // 4J - a lot of stuff taken out here for fiddling round with enable client states etc.
192// // that don't matter for our renderer
193// if (!hasColor)
194// {
195// // 4J - TEMP put in fixed vertex colors if we don't have any, until we have a shader that can cope without them
196// unsigned int *pColData = (unsigned int *)_array->data;
197// pColData += 5;
198// for( int i = 0; i < vertices; i++ )
199// {
200// *pColData = 0xffffffff;
201// pColData += 8;
202// }
203// }
204// if (mode == GL_QUADS && TRIANGLE_MODE)
205// {
206// // glDrawArrays(GL_TRIANGLES, 0, vertices); // 4J - changed for xbox
207// #ifdef _XBOX
208// RenderManager.DrawVertices(D3DPT_TRIANGLELIST,vertices,_array->data,
209// useCompactFormat360?C4JRender::VERTEX_TYPE_PS3_TS2_CS1:C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1,
210// useProjectedTexturePixelShader?C4JRender::PIXEL_SHADER_TYPE_PROJECTION:C4JRender::PIXEL_SHADER_TYPE_STANDARD);
211// #else
212// RenderManager.DrawVertices(C4JRender::PRIMITIVE_TYPE_TRIANGLE_LIST,vertices,_array->data,
213// useCompactFormat360?C4JRender::VERTEX_TYPE_COMPRESSED:C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1,
214// useProjectedTexturePixelShader?C4JRender::PIXEL_SHADER_TYPE_PROJECTION:C4JRender::PIXEL_SHADER_TYPE_STANDARD);
215// #endif
216// }
217// else
218// {
219// // glDrawArrays(mode, 0, vertices); // 4J - changed for xbox
220// // For compact vertices, the vertexCount has to be calculated from the amount of data written, as
221// // we insert extra fake vertices to encode supplementary data for more awkward quads that have non
222// // axis aligned UVs (eg flowing lava/water)
223// #ifdef _XBOX
224// int vertexCount = vertices;
225// if( useCompactFormat360 )
226// {
227// vertexCount = p / 2;
228// RenderManager.DrawVertices((D3DPRIMITIVETYPE)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PS3_TS2_CS1, C4JRender::PIXEL_SHADER_TYPE_STANDARD);
229// }
230// else
231// {
232// if( useProjectedTexturePixelShader )
233// {
234// RenderManager.DrawVertices((D3DPRIMITIVETYPE)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_TEXGEN, C4JRender::PIXEL_SHADER_TYPE_PROJECTION);
235// }
236// else
237// {
238// RenderManager.DrawVertices((D3DPRIMITIVETYPE)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1, C4JRender::PIXEL_SHADER_TYPE_STANDARD);
239// }
240// }
241// #else
242// int vertexCount = vertices;
243// if( useCompactFormat360 )
244// {
245// RenderManager.DrawVertices((C4JRender::ePrimitiveType)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_COMPRESSED, C4JRender::PIXEL_SHADER_TYPE_STANDARD);
246// }
247// else
248// {
249// if( useProjectedTexturePixelShader )
250// {
251// RenderManager.DrawVertices((C4JRender::ePrimitiveType)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_TEXGEN, C4JRender::PIXEL_SHADER_TYPE_PROJECTION);
252// }
253// else
254// {
255// RenderManager.DrawVertices((C4JRender::ePrimitiveType)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1, C4JRender::PIXEL_SHADER_TYPE_STANDARD);
256// }
257// }
258// #endif
259// }
260// glDisableClientState(GL_VERTEX_ARRAY);
261// if (hasTexture) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
262// if (hasColor) glDisableClientState(GL_COLOR_ARRAY);
263// if (hasNormal) glDisableClientState(GL_NORMAL_ARRAY);
264// }
265//
266// clear();
267}
268
269void Tesselator_SPU::clear()
270{
271 vertices = 0;
272
273 p = 0;
274 count = 0;
275}
276
277void Tesselator_SPU::begin()
278{
279 begin(GL_QUADS);
280 bounds.reset();
281}
282
283void Tesselator_SPU::useProjectedTexture(bool enable)
284{
285 useProjectedTexturePixelShader = enable;
286}
287
288void Tesselator_SPU::useCompactVertices(bool enable)
289{
290 useCompactFormat360 = enable;
291}
292
293bool Tesselator_SPU::setMipmapEnable(bool enable)
294{
295 bool prev = mipmapEnable;
296 mipmapEnable = enable;
297 return prev;
298}
299
300void Tesselator_SPU::begin(int mode)
301{
302 /* // 4J - removed
303 if (tesselating) {
304 throw new IllegalStateException("Already tesselating!");
305 } */
306 tesselating = true;
307
308 clear();
309 this->mode = mode;
310 hasNormal = false;
311 hasColor = false;
312 hasTexture = false;
313 hasTexture2 = false;
314 _noColor = false;
315}
316
317void Tesselator_SPU::tex(float u, float v)
318{
319 hasTexture = true;
320 this->u = u;
321 this->v = v;
322}
323
324void Tesselator_SPU::tex2(int tex2)
325{
326 hasTexture2 = true;
327 this->_tex2 = tex2;
328}
329
330void Tesselator_SPU::color(float r, float g, float b)
331{
332 color((int) (r * 255), (int) (g * 255), (int) (b * 255));
333}
334
335void Tesselator_SPU::color(float r, float g, float b, float a)
336{
337 color((int) (r * 255), (int) (g * 255), (int) (b * 255), (int) (a * 255));
338}
339
340void Tesselator_SPU::color(int r, int g, int b)
341{
342 color(r, g, b, 255);
343}
344
345void Tesselator_SPU::color(int r, int g, int b, int a)
346{
347 if (_noColor) return;
348
349 if (r > 255) r = 255;
350 if (g > 255) g = 255;
351 if (b > 255) b = 255;
352 if (a > 255) a = 255;
353 if (r < 0) r = 0;
354 if (g < 0) g = 0;
355 if (b < 0) b = 0;
356 if (a < 0) a = 0;
357
358 hasColor = true;
359 // 4J - removed little-endian option
360 col = (r << 24) | (g << 16) | (b << 8) | (a);
361}
362
363void Tesselator_SPU::color(byte r, byte g, byte b)
364{
365 color(r & 0xff, g & 0xff, b & 0xff);
366}
367
368void Tesselator_SPU::vertexUV(float x, float y, float z, float u, float v)
369{
370 tex(u, v);
371 vertex(x, y, z);
372}
373
374// Pack the 4 vertices of a quad up into a compact format. This is structured as 8 bytes per vertex,
375// arranged in blocks of 4 vertices per quad. Currently this is (one letter per nyblle):
376//
377// cccc xxyy zzll rgbi (vertex 0)
378// umin xxyy zzll rgbi (vertex 1)
379// vmin xxyy zzll rgbi (vertex 2)
380// udvd xxyy zzll rgbi (vertex 3)
381//
382// where: cccc is a 15-bit (5 bits per x/y/z) origin position / offset for the whole quad. Each
383// component is unsigned, and offset by 16 so has a range 0 to 31 actually representing -16 to 15
384// xx,yy,zz are 8-bit deltas from this origin to each vertex. These are unsigned 1.7 fixed point, ie
385// representing a range of 0 to 1.9921875
386// rgb is 4:4:4 RGB
387// umin, vmin are 3:13 unsigned fixed point UVs reprenting the min u and v required by the quad
388// ud,vd are 8-bit unsigned fixed pont UV deltas, which can be added to umin/vmin to get umax, vmax
389// and therefore define the 4 corners of an axis aligned UV mapping
390// i is a code per vertex that indicates which of umin/umax should be used for u, and which
391// of vmin/vmax should be used for v for this vertex. The coding is:
392// 0 - u = umin, v = vmin
393// 1 - u = umin, v = vmax
394// 2 - u = umax, v = vmin
395// 3 - u = umax, v = vmax
396// 4 - not axis aligned, use uv stored in the vertex data 4 on from this one
397// ll is an 8-bit (4 bit per u/v) index into the current lighting texture
398//
399// For quads that don't have axis aligned UVs (ie have a code for 4 in i as described above) the 8 byte vertex
400// is followed by a further 8 bytes which have explicit UVs defined for each vertex:
401//
402// 0000 0000 uuuu vvvv (vertex 0)
403// 0000 0000 uuuu vvvv (vertex 1)
404// 0000 0000 uuuu vvvv (vertex 2)
405// 0000 0000 uuuu vvvv (vertex 3)
406//
407
408void Tesselator_SPU::packCompactQuad()
409{
410 // Offset x/y/z by 16 so that we can deal with a -16 -> 16 range
411 for( int i = 0; i < 4; i++ )
412 {
413 m_ix[i] += 16 * 128;
414 m_iy[i] += 16 * 128;
415 m_iz[i] += 16 * 128;
416 }
417 // Find min x/y/z
418 unsigned int minx = m_ix[0];
419 unsigned int miny = m_iy[0];
420 unsigned int minz = m_iz[0];
421 for( int i = 1; i < 4; i++ )
422 {
423 if( m_ix[i] < minx ) minx = m_ix[i];
424 if( m_iy[i] < miny ) miny = m_iy[i];
425 if( m_iz[i] < minz ) minz = m_iz[i];
426 }
427 // Everything has been scaled by a factor of 128 to get it into an int, and so
428 // the minimum now should be in the range of (0->32) * 128. Get the base x/y/z
429 // that our quad will be referenced from now, which can be stored in 5 bits
430 unsigned int basex = ( minx >> 7 );
431 unsigned int basey = ( miny >> 7 );
432 unsigned int basez = ( minz >> 7 );
433 // If the min is 32, then this whole quad must be in that plane - make the min 15 instead so
434 // we can still offset from that with our delta to get to the exact edge
435 if( basex == 32 ) basex = 31;
436 if( basey == 32 ) basey = 31;
437 if( basez == 32 ) basez = 31;
438 // Now get deltas to each vertex - these have an 8-bit range so they can span a
439 // full unit range from the base position
440 for( int i = 0; i < 4; i++ )
441 {
442 m_ix[i] -= basex << 7;
443 m_iy[i] -= basey << 7;
444 m_iz[i] -= basez << 7;
445 }
446 // Now write the data out
447 unsigned int *data = (unsigned int *)&_array->data[p];
448
449 for( int i = 0; i < 4; i++ )
450 {
451 data[i * 2 + 0] = ( m_ix[i] << 8 ) | ( m_iy[i] );
452 data[i * 2 + 1] = ( m_iz[i] << 24 ) | ( m_clr[i] );
453 }
454 data[0] |= ( basex << 26 ) | ( basey << 21 )| ( basez << 16 );
455
456 // Now process UVs. First find min & max U & V
457 unsigned int minu = m_u[0];
458 unsigned int minv = m_v[0];
459 unsigned int maxu = m_u[0];
460 unsigned int maxv = m_v[0];
461
462 for( int i = 1; i < 4; i++ )
463 {
464 if( m_u[i] < minu ) minu = m_u[i];
465 if( m_v[i] < minv ) minv = m_v[i];
466 if( m_u[i] > maxu ) maxu = m_u[i];
467 if( m_v[i] > maxv ) maxv = m_v[i];
468 }
469 // In nearly all cases, all our UVs should be axis aligned for this quad. So the only values they should
470 // have in each dimension should be the min/max. We're going to store:
471 // (1) minu/maxu (16 bits each, only actuall needs to store 14 bits to get a 0 to 2 range for each
472 // (2) du/dv ( ie maxu-minu, maxv-minv) - 8 bits each, to store a range of 0 to 15.9375 texels. This
473 // should be enough to map the full UV range of a single 16x16 region of the terrain texture, since
474 // we always pull UVs in by 1/16th of their range at the sides
475 unsigned int du = maxu - minu;
476 unsigned int dv = maxv - minv;
477 if( du > 255 ) du = 255;
478 if( dv > 255 ) dv = 255;
479 // Check if this quad has UVs that can be referenced this way. This should only happen for flowing water
480 // and lava, where the texture coordinates are rotated for the top surface of the tile.
481 bool axisAligned = true;
482 for( int i = 0; i < 4; i++ )
483 {
484 if(! ( ( ( m_u[i] == minu ) || ( m_u[i] == maxu ) ) &&
485 ( ( m_v[i] == minv ) || ( m_v[i] == maxv ) ) ) )
486 {
487 axisAligned = false;
488 }
489 }
490
491 if( axisAligned )
492 {
493 // Now go through each vertex, and work out which of the min/max should be used for each dimension,
494 // and store
495 for( int i = 0; i < 4; i++ )
496 {
497 unsigned int code = 0;
498 if( m_u[i] == maxu ) code |= 2;
499 if( m_v[i] == maxv ) code |= 1;
500 data[i * 2 + 1] |= code;
501 data[i * 2 + 1] |= m_t2[i] << 16;
502 }
503 // Finally, store the minu/minv/du/dv
504 data[1 * 2 + 0] |= minu << 16;
505 data[2 * 2 + 0] |= minv << 16;
506 data[3 * 2 + 0] |= ( du << 24 | dv << 16 );
507
508 incData(4 * 2);
509 }
510 else
511 {
512 // The UVs aren't axis aligned - store them in the next 4 vertices. These will be indexed from
513 // our base vertices because we'll set a special code (4) for the UVs. They won't be drawn as actual
514 // verts when these extra vertices go through the vertex shader, because we'll make sure that
515 // they get interpreted as a zero area quad and so they'll be quickly eliminated from rendering post-tranform
516
517 for( int i = 0; i < 4; i++ )
518 {
519 data[i * 2 + 1] |= ( 4 ); // The special code to indicate they need further data to be fetched
520 data[i * 2 + 1] |= m_t2[i] << 16;
521 data[8 + i * 2] = 0; // This includes x/y coordinate of each vert as (0,0) so they will be interpreted as a zero area quad
522 data[9 + i * 2] = m_u[i] << 16 | m_v[i];
523 }
524
525 // Extra 8 bytes required
526 incData(8 * 2);
527 }
528}
529
530void Tesselator_SPU::vertex(float x, float y, float z)
531{
532 bounds.addVert(x+xo, y+yo, z+zo); // 4J MGH - added
533 count++;
534
535 // Signal to pixel shader whether to use mipmapping or not, by putting u into > 1 range if it is to be disabled
536 float uu = mipmapEnable ? u : (u + 1.0f);
537
538 // 4J - this format added for 360 to keep memory size of tesselated tiles down -
539 // see comments in packCompactQuad() for exact format
540 if( useCompactFormat360 )
541 {
542 unsigned int ucol = (unsigned int)col;
543
544#ifdef _XBOX
545 // Pack as 4:4:4 RGB_
546 unsigned short packedcol = (((col & 0xf0000000 ) >> 16 ) |
547 ((col & 0x00f00000 ) >> 12 ) |
548 ((col & 0x0000f000 ) >> 8 ));
549 int ipackedcol = ((int)packedcol) & 0xffff; // 0 to 65535 range
550
551 int quadIdx = vertices % 4;
552 m_ix[ quadIdx ] = (unsigned int)((x + xo) * 128.0f);
553 m_iy[ quadIdx ] = (unsigned int)((y + yo) * 128.0f);
554 m_iz[ quadIdx ] = (unsigned int)((z + zo) * 128.0f);
555 m_clr[ quadIdx ] = (unsigned int)ipackedcol;
556 m_u[ quadIdx ] = (int)(uu * 4096.0f);
557 m_v[ quadIdx ] = (int)(v * 4096.0f);
558 m_t2[ quadIdx ] = ( ( _tex2 & 0x00f00000 ) >> 20 ) | ( _tex2 & 0x000000f0 );
559 if( quadIdx == 3 )
560 {
561 packCompactQuad();
562 }
563#else
564 unsigned short packedcol = ((col & 0xf8000000 ) >> 16 ) |
565 ((col & 0x00fc0000 ) >> 13 ) |
566 ((col & 0x0000f800 ) >> 11 );
567 int ipackedcol = ((int)packedcol) & 0xffff; // 0 to 65535 range
568
569 ipackedcol -= 32768; // -32768 to 32767 range
570 ipackedcol &= 0xffff;
571
572 int16_t* pShortData = (int16_t*)&_array->data[p];
573#ifdef __PS3__
574#define INT_ROUND(x) (int)(floorf(x+0.5))
575 float tex2U = ((int16_t*)&_tex2)[1] + 8;
576 float tex2V = ((int16_t*)&_tex2)[0] + 8;
577 float colVal1 = ((col&0xff000000)>>24)/256.0f;
578 float colVal2 = ((col&0x00ff0000)>>16)/256.0f;
579 float colVal3 = ((col&0x0000ff00)>>8)/256.0f;
580
581 // pShortData[0] = convertFloatToHFloat(x + xo);
582 // pShortData[1] = convertFloatToHFloat(y + yo);
583 // pShortData[2] = convertFloatToHFloat(z + zo);
584 // pShortData[3] = convertFloatToHFloat(uu);
585 // pShortData[4] = convertFloatToHFloat(tex2U + colVal1);
586 // pShortData[5] = convertFloatToHFloat(tex2V + colVal2);
587 // pShortData[6] = convertFloatToHFloat(colVal3);
588 // pShortData[7] = convertFloatToHFloat(v);
589
590 pShortData[0] = ((INT_ROUND((x + xo ) * 1024.0f))&0xffff);
591 pShortData[1] = ((INT_ROUND((y + yo ) * 1024.0f))&0xffff);
592 pShortData[2] = ((INT_ROUND((z + zo ) * 1024.0f))&0xffff);
593 pShortData[3] = ipackedcol;
594 pShortData[4] = ((INT_ROUND(uu * 8192.0f))&0xffff);
595 pShortData[5] = ((INT_ROUND(v * 8192.0f))&0xffff);
596 pShortData[6] = ((INT_ROUND(tex2U * (8192.0f/256.0f)))&0xffff);
597 pShortData[7] = ((INT_ROUND(tex2V * (8192.0f/256.0f)))&0xffff);
598 incData(4);
599#else
600 pShortData[0] = (((int)((x + xo ) * 1024.0f))&0xffff);
601 pShortData[1] = (((int)((y + yo ) * 1024.0f))&0xffff);
602 pShortData[2] = (((int)((z + zo ) * 1024.0f))&0xffff);
603 pShortData[3] = ipackedcol;
604 pShortData[4] = (((int)(uu * 8192.0f))&0xffff);
605 pShortData[5] = (((int)(v * 8192.0f))&0xffff);
606 pShortData[6] = ((int16_t*)&_tex2)[0];
607 pShortData[7] = ((int16_t*)&_tex2)[1];
608 incData(4);
609#endif
610
611#endif
612
613 vertices++;
614#ifdef _XBOX
615 if (vertices % 4 == 0 && ( ( p >= size - 8 * 2 ) || ( ( p / 2 ) >= 65532 ) ) ) // Max 65535 verts in D3D, so 65532 is the last point at the end of a quad to catch it
616#else
617 if (vertices % 4 == 0 && ( ( p >= size - 4 * 4 ) || ( ( p / 4 ) >= 65532 ) ) ) // Max 65535 verts in D3D, so 65532 is the last point at the end of a quad to catch it
618#endif
619 {
620// end();
621 tesselating = true;
622 }
623 }
624 else
625 {
626 if (mode == GL_QUADS && TRIANGLE_MODE && count % 4 == 0)
627 {
628 for (int i = 0; i < 2; i++)
629 {
630 int offs = 8 * (3 - i);
631 if (hasTexture)
632 {
633 _array->data[p + 3] = _array->data[p - offs + 3];
634 _array->data[p + 4] = _array->data[p - offs + 4];
635 }
636 if (hasColor)
637 {
638 _array->data[p + 5] = _array->data[p - offs + 5];
639 }
640
641 _array->data[p + 0] = _array->data[p - offs + 0];
642 _array->data[p + 1] = _array->data[p - offs + 1];
643 _array->data[p + 2] = _array->data[p - offs + 2];
644
645 vertices++;
646 incData(8);
647 }
648 }
649
650 if (hasTexture)
651 {
652 float *fdata = (float *)(_array->data + p + 3);
653 *fdata++ = uu;
654 *fdata++ = v;
655 }
656 if (hasColor)
657 {
658 _array->data[p + 5] = col;
659 }
660 if (hasNormal)
661 {
662 _array->data[p + 6] = _normal;
663 }
664 if (hasTexture2)
665 {
666#ifdef _XBOX
667 _array->data[p + 7] = ( ( _tex2 >> 16 ) & 0xffff ) | ( _tex2 << 16 );
668#else
669#ifdef __PS3__
670 int16_t tex2U = ((int16_t*)&_tex2)[1] + 8;
671 int16_t tex2V = ((int16_t*)&_tex2)[0] + 8;
672 int16_t* pShortArray = (int16_t*)&_array->data[p + 7];
673 pShortArray[0] = tex2U;
674 pShortArray[1] = tex2V;
675#else
676 _array->data[p + 7] = _tex2;
677#endif
678#endif
679 }
680 else
681 {
682 // -512 each for u/v will mean that the renderer will use global settings (set via
683 // RenderManager.StateSetVertexTextureUV) rather than these local ones
684 *(unsigned int *)(&_array->data[p + 7]) = 0xfe00fe00;
685 }
686
687 float *fdata = (float *)(_array->data + p);
688 *fdata++ = (x + xo);
689 *fdata++ = (y + yo);
690 *fdata++ = (z + zo);
691 incData(8);
692
693 vertices++;
694 if (vertices % 4 == 0 && p >= size - 8 * 4)
695 {
696// end();
697 tesselating = true;
698 }
699 }
700}
701
702void Tesselator_SPU::color(int c)
703{
704 int r = ((c >> 16) & 255);
705 int g = ((c >> 8) & 255);
706 int b = ((c) & 255);
707 color(r, g, b);
708}
709
710void Tesselator_SPU::color(int c, int alpha)
711{
712 int r = ((c >> 16) & 255);
713 int g = ((c >> 8) & 255);
714 int b = ((c) & 255);
715 color(r, g, b, alpha);
716}
717
718void Tesselator_SPU::noColor()
719{
720 _noColor = true;
721}
722
723void Tesselator_SPU::normal(float x, float y, float z)
724{
725 hasNormal = true;
726 byte xx = (byte) (x * 127);
727 byte yy = (byte) (y * 127);
728 byte zz = (byte) (z * 127);
729
730 _normal = (xx & 0xff) | ((yy & 0xff) << 8) | ((zz & 0xff) << 16);
731}
732
733void Tesselator_SPU::offset(float xo, float yo, float zo)
734{
735 this->xo = xo;
736 this->yo = yo;
737 this->zo = zo;
738}
739
740void Tesselator_SPU::addOffset(float x, float y, float z)
741{
742 xo += x;
743 yo += y;
744 zo += z;
745}
746
747void Tesselator_SPU::incData( int numInts )
748{
749 p+=numInts;
750
751#ifdef SN_TARGET_PS3_SPU
752 if(p > 4096)
753 {
754 int dmaSize = p*4;
755 unsigned int dmaTag = 2;
756 void* src = _array->data;
757 uintptr_t dest = (uintptr_t)(((char*)m_PPUArray) + m_PPUOffset);
758 if(sc_verbose)
759 spu_print("Tesselator : DMA SPU->PPU : 0x%08x -> 0x%08x : size : %d bytes\n", (unsigned int)src, (unsigned int)dest, dmaSize);
760 cellDmaLargePut(src, dest, dmaSize, dmaTag, 0, 0);
761 cellDmaWaitTagStatusAll(1 << dmaTag);
762
763// int copySize = (p-4096);
764// for(int i=0;i<copySize;i++)
765// _array->data[i] = _array->data[4096+i];
766 //p -= 4096;
767 p=0;
768 m_PPUOffset += dmaSize;//16384;
769 }
770#endif // SN_TARGET_PS3_SPU
771}
772
773void Tesselator_SPU::endData()
774{
775#ifdef SN_TARGET_PS3_SPU
776 int dmaSize = p*4;
777 unsigned int dmaTag = 2;
778 void* src = _array->data;
779 uintptr_t dest = (uintptr_t)(((char*)m_PPUArray) + m_PPUOffset);
780 if(sc_verbose)
781 spu_print("Tesselator : DMA SPU->PPU : 0x%08x -> 0x%08x : size : %d bytes\n", (unsigned int)src, (unsigned int)dest, dmaSize);
782 cellDmaLargePut(src, dest, dmaSize, dmaTag, 0, 0);
783 cellDmaWaitTagStatusAll(1 << dmaTag);
784 if(sc_verbose)
785 spu_print("endData - Tesselator : DMA SPU->PPU complete : %d verts, %d bytes in total\n", vertices, m_PPUOffset+ dmaSize);
786 p=0;
787 m_PPUOffset += dmaSize;
788#else // SN_TARGET_PS3_SPU
789 m_PPUOffset = p*4;
790#endif
791}
792
793void Tesselator_SPU::beginData()
794{
795 p = 0;
796}