the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at master 796 lines 25 kB view raw
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}