the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 1080 lines 32 kB view raw
1#include "stdafx.h" 2#include "Tesselator.h" 3#include "..\Minecraft.World\BasicTypeContainers.h" 4#include "..\Minecraft.World\FloatBuffer.h" 5#include "..\Minecraft.World\IntBuffer.h" 6#include "..\Minecraft.World\ByteBuffer.h" 7 8bool Tesselator::TRIANGLE_MODE = false; 9bool Tesselator::USE_VBO = false; 10 11/* Things to check we are intialising in the constructor... 12 13 14 15double u, v; 16int col; 17int mode; 18double xo, yo, zo; 19int normal; 20 21 22 23 24 25 26*/ 27DWORD Tesselator::tlsIdx = TlsAlloc(); 28 29Tesselator *Tesselator::getInstance() 30{ 31 return (Tesselator *)TlsGetValue(tlsIdx); 32} 33 34void Tesselator::CreateNewThreadStorage(int bytes) 35{ 36 Tesselator *instance = new Tesselator(bytes/4); 37 TlsSetValue(tlsIdx, instance); 38} 39 40Tesselator::Tesselator(int size) 41{ 42 // 4J - this block of things moved to constructor from general initialisations round Java class 43 vertices = 0; 44 hasColor = false; 45 hasTexture = false; 46 hasTexture2 = false; 47 hasNormal = false; 48 p = 0; 49 count = 0; 50 _noColor = false; 51 tesselating = false; 52 vboMode = false; 53 vboId = 0; 54 vboCounts = 10; 55 56 // 4J - adding these things to constructor just to be sure that they are initialised with something 57 u = v = 0; 58 col = 0; 59 mode = 0; 60 xo = yo = zo = 0; 61 xoo = yoo = zoo = 0; // 4J added 62 _normal = 0; 63 64 useCompactFormat360 = false; // 4J added 65 mipmapEnable = true; // 4J added 66 useProjectedTexturePixelShader = false; // 4J added 67 68 this->size = size; 69 70 _array = new intArray(size); 71 72 vboMode = USE_VBO; // 4J removed - && GLContext.getCapabilities().GL_ARB_vertex_buffer_object; 73 if (vboMode) 74 { 75 vboIds = MemoryTracker::createIntBuffer(vboCounts); 76 ARBVertexBufferObject::glGenBuffersARB(vboIds); 77 } 78 79#ifdef __PSVITA__ 80 // AP - alpha cut out is expensive on vita. Use this to defer primitives that use icons with alpha 81 alphaCutOutEnabled = false; 82 83 // this is the cut out enabled vertex array 84 _array2 = new intArray(size); 85 vertices2 = 0; 86 p2 = 0; 87#endif 88} 89 90Tesselator *Tesselator::getUniqueInstance(int size) 91{ 92 return new Tesselator(size); 93} 94 95void Tesselator::end() 96{ 97// if (!tesselating) throw new IllegalStateException("Not tesselating!"); // 4J - removed 98 tesselating = false; 99#ifdef __PSVITA__ 100 // AP - alpha cut out is expensive on vita. Check both counts for valid vertices 101 if( vertices > 0 || vertices2 > 0 ) 102#else 103 if (vertices > 0) 104#endif 105 { 106 // 4J - a lot of stuff taken out here for fiddling round with enable client states etc. 107 // that don't matter for our renderer 108 if (!hasColor) 109 { 110 // 4J - TEMP put in fixed vertex colors if we don't have any, until we have a shader that can cope without them 111 unsigned int *pColData = (unsigned int *)_array->data; 112 pColData += 5; 113 for( int i = 0; i < vertices; i++ ) 114 { 115 *pColData = 0xffffffff; 116 pColData += 8; 117 } 118#ifdef __PSVITA__ 119 // AP - alpha cut out is expensive on vita. Check both counts for valid vertices 120 pColData = (unsigned int *)_array2->data; 121 pColData += 5; 122 for( int i = 0; i < vertices2; i++ ) 123 { 124 *pColData = 0xffffffff; 125 pColData += 8; 126 } 127#endif 128 } 129 if (mode == GL_QUADS && TRIANGLE_MODE) 130 { 131 // glDrawArrays(GL_TRIANGLES, 0, vertices); // 4J - changed for xbox 132#ifdef _XBOX 133 RenderManager.DrawVertices(D3DPT_TRIANGLELIST,vertices,_array->data, 134 useCompactFormat360?C4JRender::VERTEX_TYPE_PS3_TS2_CS1:C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1, 135 useProjectedTexturePixelShader?C4JRender::PIXEL_SHADER_TYPE_PROJECTION:C4JRender::PIXEL_SHADER_TYPE_STANDARD); 136#else 137 RenderManager.DrawVertices(C4JRender::PRIMITIVE_TYPE_TRIANGLE_LIST,vertices,_array->data, 138 useCompactFormat360?C4JRender::VERTEX_TYPE_COMPRESSED:C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1, 139 useProjectedTexturePixelShader?C4JRender::PIXEL_SHADER_TYPE_PROJECTION:C4JRender::PIXEL_SHADER_TYPE_STANDARD); 140#endif 141 } 142 else 143 { 144// glDrawArrays(mode, 0, vertices); // 4J - changed for xbox 145 // For compact vertices, the vertexCount has to be calculated from the amount of data written, as 146 // we insert extra fake vertices to encode supplementary data for more awkward quads that have non 147 // axis aligned UVs (eg flowing lava/water) 148#ifdef _XBOX 149 int vertexCount = vertices; 150 if( useCompactFormat360 ) 151 { 152 vertexCount = p / 2; 153 RenderManager.DrawVertices((D3DPRIMITIVETYPE)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PS3_TS2_CS1, C4JRender::PIXEL_SHADER_TYPE_STANDARD); 154 } 155 else 156 { 157 if( useProjectedTexturePixelShader ) 158 { 159 RenderManager.DrawVertices((D3DPRIMITIVETYPE)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_TEXGEN, C4JRender::PIXEL_SHADER_TYPE_PROJECTION); 160 } 161 else 162 { 163 RenderManager.DrawVertices((D3DPRIMITIVETYPE)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1, C4JRender::PIXEL_SHADER_TYPE_STANDARD); 164 } 165 } 166#else 167 int vertexCount = vertices; 168 if( useCompactFormat360 ) 169 { 170#ifdef __PSVITA__ 171 // AP - alpha cut out is expensive on vita. Render non-cut out stuff first then send the cut out stuff 172 if( vertexCount ) 173 { 174 RenderManager.DrawVertices((C4JRender::ePrimitiveType)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_COMPRESSED, C4JRender::PIXEL_SHADER_TYPE_STANDARD); 175 } 176 if( vertices2 ) 177 { 178 RenderManager.DrawVerticesCutOut((C4JRender::ePrimitiveType)mode,vertices2,_array2->data,C4JRender::VERTEX_TYPE_COMPRESSED, C4JRender::PIXEL_SHADER_TYPE_STANDARD); 179 } 180#else 181 182 RenderManager.DrawVertices((C4JRender::ePrimitiveType)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_COMPRESSED, C4JRender::PIXEL_SHADER_TYPE_STANDARD); 183#endif 184 } 185 else 186 { 187 if( useProjectedTexturePixelShader ) 188 { 189 RenderManager.DrawVertices((C4JRender::ePrimitiveType)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1_TEXGEN, C4JRender::PIXEL_SHADER_TYPE_PROJECTION); 190 } 191 else 192 { 193 RenderManager.DrawVertices((C4JRender::ePrimitiveType)mode,vertexCount,_array->data,C4JRender::VERTEX_TYPE_PF3_TF2_CB4_NB4_XW1, C4JRender::PIXEL_SHADER_TYPE_STANDARD); 194 } 195 } 196#endif 197 } 198 glDisableClientState(GL_VERTEX_ARRAY); 199 if (hasTexture) glDisableClientState(GL_TEXTURE_COORD_ARRAY); 200 if (hasColor) glDisableClientState(GL_COLOR_ARRAY); 201 if (hasNormal) glDisableClientState(GL_NORMAL_ARRAY); 202 } 203 204 clear(); 205} 206 207void Tesselator::clear() 208{ 209 vertices = 0; 210 211 p = 0; 212 count = 0; 213 214#ifdef __PSVITA__ 215 // AP - alpha cut out is expensive on vita. Clear the cut out variables 216 vertices2 = 0; 217 p2 = 0; 218#endif 219} 220 221void Tesselator::begin() 222{ 223 begin(GL_QUADS); 224 bounds.reset(); // 4J MGH - added 225} 226 227void Tesselator::useProjectedTexture(bool enable) 228{ 229 useProjectedTexturePixelShader = enable; 230} 231 232void Tesselator::useCompactVertices(bool enable) 233{ 234 useCompactFormat360 = enable; 235} 236 237bool Tesselator::getCompactVertices() 238{ 239 return useCompactFormat360; 240} 241 242bool Tesselator::setMipmapEnable(bool enable) 243{ 244 bool prev = mipmapEnable; 245 mipmapEnable = enable; 246 return prev; 247} 248 249#ifdef __PSVITA__ 250// AP - alpha cut out is expensive on vita. Use this to defer primitives that use icons with alpha 251void Tesselator::setAlphaCutOut(bool enable) 252{ 253 alphaCutOutEnabled = enable; 254} 255 256// AP - was any cut out geometry added since the last call to Clear 257bool Tesselator::getCutOutFound() 258{ 259 if( vertices2 ) 260 return true; 261 262 return false; 263} 264#endif 265 266void Tesselator::begin(int mode) 267{ 268 /* // 4J - removed 269 if (tesselating) { 270 throw new IllegalStateException("Already tesselating!"); 271 } */ 272 tesselating = true; 273 274 clear(); 275 this->mode = mode; 276 hasNormal = false; 277 hasColor = false; 278 hasTexture = false; 279 hasTexture2 = false; 280 _noColor = false; 281} 282 283void Tesselator::tex(float u, float v) 284{ 285 hasTexture = true; 286 this->u = u; 287 this->v = v; 288} 289 290void Tesselator::tex2(int tex2) 291{ 292 hasTexture2 = true; 293 this->_tex2 = tex2; 294} 295 296void Tesselator::color(float r, float g, float b) 297{ 298 color((int) (r * 255), (int) (g * 255), (int) (b * 255)); 299} 300 301void Tesselator::color(float r, float g, float b, float a) 302{ 303 color((int) (r * 255), (int) (g * 255), (int) (b * 255), (int) (a * 255)); 304} 305 306void Tesselator::color(int r, int g, int b) 307{ 308 color(r, g, b, 255); 309} 310 311void Tesselator::color(int r, int g, int b, int a) 312{ 313 if (_noColor) return; 314 315 if (r > 255) r = 255; 316 if (g > 255) g = 255; 317 if (b > 255) b = 255; 318 if (a > 255) a = 255; 319 if (r < 0) r = 0; 320 if (g < 0) g = 0; 321 if (b < 0) b = 0; 322 if (a < 0) a = 0; 323 324 hasColor = true; 325 // 4J - removed little-endian option 326 col = (r << 24) | (g << 16) | (b << 8) | (a); 327} 328 329void Tesselator::color(byte r, byte g, byte b) 330{ 331 color(r & 0xff, g & 0xff, b & 0xff); 332} 333 334void Tesselator::vertexUV(float x, float y, float z, float u, float v) 335{ 336 tex(u, v); 337 vertex(x, y, z); 338} 339 340// Pack the 4 vertices of a quad up into a compact format. This is structured as 8 bytes per vertex, 341// arranged in blocks of 4 vertices per quad. Currently this is (one letter per nyblle): 342// 343// cccc xxyy zzll rgbi (vertex 0) 344// umin xxyy zzll rgbi (vertex 1) 345// vmin xxyy zzll rgbi (vertex 2) 346// udvd xxyy zzll rgbi (vertex 3) 347// 348// where: cccc is a 15-bit (5 bits per x/y/z) origin position / offset for the whole quad. Each 349// component is unsigned, and offset by 16 so has a range 0 to 31 actually representing -16 to 15 350// xx,yy,zz are 8-bit deltas from this origin to each vertex. These are unsigned 1.7 fixed point, ie 351// representing a range of 0 to 1.9921875 352// rgb is 4:4:4 RGB 353// umin, vmin are 3:13 unsigned fixed point UVs reprenting the min u and v required by the quad 354// ud,vd are 8-bit unsigned fixed pont UV deltas, which can be added to umin/vmin to get umax, vmax 355// and therefore define the 4 corners of an axis aligned UV mapping 356// i is a code per vertex that indicates which of umin/umax should be used for u, and which 357// of vmin/vmax should be used for v for this vertex. The coding is: 358// 0 - u = umin, v = vmin 359// 1 - u = umin, v = vmax 360// 2 - u = umax, v = vmin 361// 3 - u = umax, v = vmax 362// 4 - not axis aligned, use uv stored in the vertex data 4 on from this one 363// ll is an 8-bit (4 bit per u/v) index into the current lighting texture 364// 365// For quads that don't have axis aligned UVs (ie have a code for 4 in i as described above) the 8 byte vertex 366// is followed by a further 8 bytes which have explicit UVs defined for each vertex: 367// 368// 0000 0000 uuuu vvvv (vertex 0) 369// 0000 0000 uuuu vvvv (vertex 1) 370// 0000 0000 uuuu vvvv (vertex 2) 371// 0000 0000 uuuu vvvv (vertex 3) 372// 373 374void Tesselator::packCompactQuad() 375{ 376 // Offset x/y/z by 16 so that we can deal with a -16 -> 16 range 377 for( int i = 0; i < 4; i++ ) 378 { 379 m_ix[i] += 16 * 128; 380 m_iy[i] += 16 * 128; 381 m_iz[i] += 16 * 128; 382 } 383 // Find min x/y/z 384 unsigned int minx = m_ix[0]; 385 unsigned int miny = m_iy[0]; 386 unsigned int minz = m_iz[0]; 387 for( int i = 1; i < 4; i++ ) 388 { 389 if( m_ix[i] < minx ) minx = m_ix[i]; 390 if( m_iy[i] < miny ) miny = m_iy[i]; 391 if( m_iz[i] < minz ) minz = m_iz[i]; 392 } 393 // Everything has been scaled by a factor of 128 to get it into an int, and so 394 // the minimum now should be in the range of (0->32) * 128. Get the base x/y/z 395 // that our quad will be referenced from now, which can be stored in 5 bits 396 unsigned int basex = ( minx >> 7 ); 397 unsigned int basey = ( miny >> 7 ); 398 unsigned int basez = ( minz >> 7 ); 399 // If the min is 32, then this whole quad must be in that plane - make the min 15 instead so 400 // we can still offset from that with our delta to get to the exact edge 401 if( basex == 32 ) basex = 31; 402 if( basey == 32 ) basey = 31; 403 if( basez == 32 ) basez = 31; 404 // Now get deltas to each vertex - these have an 8-bit range so they can span a 405 // full unit range from the base position 406 for( int i = 0; i < 4; i++ ) 407 { 408 m_ix[i] -= basex << 7; 409 m_iy[i] -= basey << 7; 410 m_iz[i] -= basez << 7; 411 } 412 // Now write the data out 413 unsigned int *data = (unsigned int *)&_array->data[p]; 414 415 for( int i = 0; i < 4; i++ ) 416 { 417 data[i * 2 + 0] = ( m_ix[i] << 8 ) | ( m_iy[i] ); 418 data[i * 2 + 1] = ( m_iz[i] << 24 ) | ( m_clr[i] ); 419 } 420 data[0] |= ( basex << 26 ) | ( basey << 21 )| ( basez << 16 ); 421 422 // Now process UVs. First find min & max U & V 423 unsigned int minu = m_u[0]; 424 unsigned int minv = m_v[0]; 425 unsigned int maxu = m_u[0]; 426 unsigned int maxv = m_v[0]; 427 428 for( int i = 1; i < 4; i++ ) 429 { 430 if( m_u[i] < minu ) minu = m_u[i]; 431 if( m_v[i] < minv ) minv = m_v[i]; 432 if( m_u[i] > maxu ) maxu = m_u[i]; 433 if( m_v[i] > maxv ) maxv = m_v[i]; 434 } 435 // In nearly all cases, all our UVs should be axis aligned for this quad. So the only values they should 436 // have in each dimension should be the min/max. We're going to store: 437 // (1) minu/maxu (16 bits each, only actuall needs to store 14 bits to get a 0 to 2 range for each 438 // (2) du/dv ( ie maxu-minu, maxv-minv) - 8 bits each, to store a range of 0 to 15.9375 texels. This 439 // should be enough to map the full UV range of a single 16x16 region of the terrain texture, since 440 // we always pull UVs in by 1/16th of their range at the sides 441 unsigned int du = maxu - minu; 442 unsigned int dv = maxv - minv; 443 if( du > 255 ) du = 255; 444 if( dv > 255 ) dv = 255; 445 // Check if this quad has UVs that can be referenced this way. This should only happen for flowing water 446 // and lava, where the texture coordinates are rotated for the top surface of the tile. 447 bool axisAligned = true; 448 for( int i = 0; i < 4; i++ ) 449 { 450 if(! ( ( ( m_u[i] == minu ) || ( m_u[i] == maxu ) ) && 451 ( ( m_v[i] == minv ) || ( m_v[i] == maxv ) ) ) ) 452 { 453 axisAligned = false; 454 } 455 } 456 457 if( axisAligned ) 458 { 459 // Now go through each vertex, and work out which of the min/max should be used for each dimension, 460 // and store 461 for( int i = 0; i < 4; i++ ) 462 { 463 unsigned int code = 0; 464 if( m_u[i] == maxu ) code |= 2; 465 if( m_v[i] == maxv ) code |= 1; 466 data[i * 2 + 1] |= code; 467 data[i * 2 + 1] |= m_t2[i] << 16; 468 } 469 // Finally, store the minu/minv/du/dv 470 data[1 * 2 + 0] |= minu << 16; 471 data[2 * 2 + 0] |= minv << 16; 472 data[3 * 2 + 0] |= ( du << 24 | dv << 16 ); 473 474 p += 4 * 2; 475 } 476 else 477 { 478 // The UVs aren't axis aligned - store them in the next 4 vertices. These will be indexed from 479 // our base vertices because we'll set a special code (4) for the UVs. They won't be drawn as actual 480 // verts when these extra vertices go through the vertex shader, because we'll make sure that 481 // they get interpreted as a zero area quad and so they'll be quickly eliminated from rendering post-tranform 482 483 for( int i = 0; i < 4; i++ ) 484 { 485 data[i * 2 + 1] |= ( 4 ); // The special code to indicate they need further data to be fetched 486 data[i * 2 + 1] |= m_t2[i] << 16; 487 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 488 data[9 + i * 2] = m_u[i] << 16 | m_v[i]; 489 } 490 491 // Extra 8 bytes required 492 p += 8 * 2; 493 } 494} 495 496#ifdef __PSVITA__ 497void Tesselator::tileQuad(float x1, float y1, float z1, float u1, float v1, float r1, float g1, float b1, int tex1, 498 float x2, float y2, float z2, float u2, float v2, float r2, float g2, float b2, int tex2, 499 float x3, float y3, float z3, float u3, float v3, float r3, float g3, float b3, int tex3, 500 float x4, float y4, float z4, float u4, float v4, float r4, float g4, float b4, int tex4 501 ) 502{ 503 hasTexture = true; 504 hasTexture2 = true; 505 hasColor = true; 506 507 count+=4; 508 509 // AP - alpha cut out is expensive on vita. This will choose the correct data buffer depending on cut out enabled 510 int16_t* pShortData; 511 if( !alphaCutOutEnabled ) 512 { 513 pShortData = (int16_t*)&_array->data[p]; 514 p += 16; 515 vertices+=4; 516 } 517 else 518 { 519 pShortData = (int16_t*)&_array2->data[p2]; 520 p2 += 16; 521 vertices2+=4; 522 } 523 524 int r = ((int) (r1 * 31)) << 11; 525 int g = ((int) (g1 * 63)) << 5; 526 int b = ((int) (b1 * 31)); 527 int ipackedcol = r | g | b; 528 ipackedcol -= 32768; // -32768 to 32767 range 529 ipackedcol &= 0xffff; 530 531 bounds.addVert(x1+xo, y1+yo, z1+zo); // 4J MGH - added 532 pShortData[0] = (((int)((x1 + xo ) * 1024.0f))&0xffff); 533 pShortData[1] = (((int)((y1 + yo ) * 1024.0f))&0xffff); 534 pShortData[2] = (((int)((z1 + zo ) * 1024.0f))&0xffff); 535 pShortData[3] = ipackedcol; 536 pShortData[4] = (((int)(u1 * 8192.0f))&0xffff); 537 pShortData[5] = (((int)(v1 * 8192.0f))&0xffff); 538 ((int *)pShortData)[3] = tex1; 539 pShortData += 8; 540 541 r = ((int) (r2 * 31)) << 11; 542 g = ((int) (g2 * 63)) << 5; 543 b = ((int) (b2 * 31)); 544 ipackedcol = r | g | b; 545 ipackedcol -= 32768; // -32768 to 32767 range 546 ipackedcol &= 0xffff; 547 548 bounds.addVert(x2+xo, y2+yo, z2+zo); // 4J MGH - added 549 pShortData[0] = (((int)((x2 + xo ) * 1024.0f))&0xffff); 550 pShortData[1] = (((int)((y2 + yo ) * 1024.0f))&0xffff); 551 pShortData[2] = (((int)((z2 + zo ) * 1024.0f))&0xffff); 552 pShortData[3] = ipackedcol; 553 pShortData[4] = (((int)(u2 * 8192.0f))&0xffff); 554 pShortData[5] = (((int)(v2 * 8192.0f))&0xffff); 555 ((int *)pShortData)[3] = tex2; 556 pShortData += 8; 557 558 r = ((int) (r3 * 31)) << 11; 559 g = ((int) (g3 * 63)) << 5; 560 b = ((int) (b3 * 31)); 561 ipackedcol = r | g | b; 562 ipackedcol -= 32768; // -32768 to 32767 range 563 ipackedcol &= 0xffff; 564 565 bounds.addVert(x3+xo, y3+yo, z3+zo); // 4J MGH - added 566 pShortData[0] = (((int)((x3 + xo ) * 1024.0f))&0xffff); 567 pShortData[1] = (((int)((y3 + yo ) * 1024.0f))&0xffff); 568 pShortData[2] = (((int)((z3 + zo ) * 1024.0f))&0xffff); 569 pShortData[3] = ipackedcol; 570 pShortData[4] = (((int)(u3 * 8192.0f))&0xffff); 571 pShortData[5] = (((int)(v3 * 8192.0f))&0xffff); 572 ((int *)pShortData)[3] = tex3; 573 pShortData += 8; 574 575 r = ((int) (r4 * 31)) << 11; 576 g = ((int) (g4 * 63)) << 5; 577 b = ((int) (b4 * 31)); 578 ipackedcol = r | g | b; 579 ipackedcol -= 32768; // -32768 to 32767 range 580 ipackedcol &= 0xffff; 581 582 bounds.addVert(x4+xo, y4+yo, z4+zo); // 4J MGH - added 583 pShortData[0] = (((int)((x4 + xo ) * 1024.0f))&0xffff); 584 pShortData[1] = (((int)((y4 + yo ) * 1024.0f))&0xffff); 585 pShortData[2] = (((int)((z4 + zo ) * 1024.0f))&0xffff); 586 pShortData[3] = ipackedcol; 587 pShortData[4] = (((int)(u4 * 8192.0f))&0xffff); 588 pShortData[5] = (((int)(v4 * 8192.0f))&0xffff); 589 ((int *)pShortData)[3] = tex4; 590 591 // Max 65535 verts in D3D, so 65532 is the last point at the end of a quad to catch it 592 if ( (!alphaCutOutEnabled && vertices % 4 == 0 && ( ( p >= size - 4 * 4 ) || ( ( p / 4 ) >= 65532 ) )) || 593 (alphaCutOutEnabled && vertices2 % 4 == 0 && ( ( p2 >= size - 4 * 4 ) || ( ( p2 / 4 ) >= 65532 ) )) ) 594 { 595 end(); 596 tesselating = true; 597 } 598} 599 600void Tesselator::tileRainQuad(float x1, float y1, float z1, float u1, float v1, 601 float x2, float y2, float z2, float u2, float v2, 602 float x3, float y3, float z3, float u3, float v3, 603 float x4, float y4, float z4, float u4, float v4, 604 float r1, float g1, float b1, float a1, 605 float r2, float g2, float b2, float a2, 606 int tex1 607 ) 608{ 609 hasTexture = true; 610 hasTexture2 = true; 611 hasColor = true; 612 613 float* pfData = (float*)&_array->data[p]; 614 615 count+=4; 616 p += 4 * 8; 617 vertices+=4; 618 619 unsigned int col1 = ((int)(r1*255) << 24) | ((int)(g1*255) << 16) | ((int)(b1*255) << 8) | (int)(a1*255); 620 621 bounds.addVert(x1+xo, y1+yo, z1+zo); 622 pfData[0] = (x1 + xo); 623 pfData[1] = (y1 + yo); 624 pfData[2] = (z1 + zo); 625 pfData[3] = u1; 626 pfData[4] = v1; 627 ((int*)pfData)[5] = col1; 628 ((int*)pfData)[7] = tex1; 629 pfData += 8; 630 631 bounds.addVert(x2+xo, y2+yo, z2+zo); 632 pfData[0] = (x2 + xo); 633 pfData[1] = (y2 + yo); 634 pfData[2] = (z2 + zo); 635 pfData[3] = u2; 636 pfData[4] = v2; 637 ((int*)pfData)[5] = col1; 638 ((int*)pfData)[7] = tex1; 639 pfData += 8; 640 641 col1 = ((int)(r2*255) << 24) | ((int)(g2*255) << 16) | ((int)(b2*255) << 8) | (int)(a2*255); 642 643 bounds.addVert(x3+xo, y3+yo, z3+zo); 644 pfData[0] = (x3 + xo); 645 pfData[1] = (y3 + yo); 646 pfData[2] = (z3 + zo); 647 pfData[3] = u3; 648 pfData[4] = v3; 649 ((int*)pfData)[5] = col1; 650 ((int*)pfData)[7] = tex1; 651 pfData += 8; 652 653 bounds.addVert(x4+xo, y4+yo, z4+zo); 654 pfData[0] = (x4 + xo); 655 pfData[1] = (y4 + yo); 656 pfData[2] = (z4 + zo); 657 pfData[3] = u4; 658 pfData[4] = v4; 659 ((int*)pfData)[5] = col1; 660 ((int*)pfData)[7] = tex1; 661 pfData += 8; 662 663 if (vertices % 4 == 0 && p >= size - 8 * 4) 664 { 665 end(); 666 tesselating = true; 667 } 668} 669 670void Tesselator::tileParticleQuad(float x1, float y1, float z1, float u1, float v1, 671 float x2, float y2, float z2, float u2, float v2, 672 float x3, float y3, float z3, float u3, float v3, 673 float x4, float y4, float z4, float u4, float v4, 674 float r1, float g1, float b1, float a1) 675{ 676 hasTexture = true; 677 hasTexture2 = true; 678 hasColor = true; 679 680 float* pfData = (float*)&_array->data[p]; 681 682 count+=4; 683 p += 4 * 8; 684 vertices+=4; 685 686 unsigned int col1 = ((int)(r1*255) << 24) | ((int)(g1*255) << 16) | ((int)(b1*255) << 8) | (int)(a1*255); 687 688 bounds.addVert(x1+xo, y1+yo, z1+zo); 689 pfData[0] = (x1 + xo); 690 pfData[1] = (y1 + yo); 691 pfData[2] = (z1 + zo); 692 pfData[3] = u1; 693 pfData[4] = v1; 694 ((int*)pfData)[5] = col1; 695 ((int*)pfData)[7] = _tex2; 696 pfData += 8; 697 698 bounds.addVert(x2+xo, y2+yo, z2+zo); 699 pfData[0] = (x2 + xo); 700 pfData[1] = (y2 + yo); 701 pfData[2] = (z2 + zo); 702 pfData[3] = u2; 703 pfData[4] = v2; 704 ((int*)pfData)[5] = col1; 705 ((int*)pfData)[7] = _tex2; 706 pfData += 8; 707 708 bounds.addVert(x3+xo, y3+yo, z3+zo); 709 pfData[0] = (x3 + xo); 710 pfData[1] = (y3 + yo); 711 pfData[2] = (z3 + zo); 712 pfData[3] = u3; 713 pfData[4] = v3; 714 ((int*)pfData)[5] = col1; 715 ((int*)pfData)[7] = _tex2; 716 pfData += 8; 717 718 bounds.addVert(x4+xo, y4+yo, z4+zo); 719 pfData[0] = (x4 + xo); 720 pfData[1] = (y4 + yo); 721 pfData[2] = (z4 + zo); 722 pfData[3] = u4; 723 pfData[4] = v4; 724 ((int*)pfData)[5] = col1; 725 ((int*)pfData)[7] = _tex2; 726 pfData += 8; 727 728 if (vertices % 4 == 0 && p >= size - 8 * 4) 729 { 730 end(); 731 tesselating = true; 732 } 733} 734#endif 735 736typedef unsigned short hfloat; 737extern hfloat convertFloatToHFloat(float f); 738extern float convertHFloatToFloat(hfloat hf); 739 740void Tesselator::vertex(float x, float y, float z) 741{ 742 bounds.addVert(x+xo, y+yo, z+zo); // 4J MGH - added 743 count++; 744 745 // Signal to pixel shader whether to use mipmapping or not, by putting u into > 1 range if it is to be disabled 746 float uu = mipmapEnable ? u : (u + 1.0f); 747 748 // 4J - this format added for 360 to keep memory size of tesselated tiles down - 749 // see comments in packCompactQuad() for exact format 750 if( useCompactFormat360 ) 751 { 752 unsigned int ucol = (unsigned int)col; 753 754#ifdef _XBOX 755 // Pack as 4:4:4 RGB_ 756 unsigned short packedcol = (((col & 0xf0000000 ) >> 16 ) | 757 ((col & 0x00f00000 ) >> 12 ) | 758 ((col & 0x0000f000 ) >> 8 )); 759 int ipackedcol = ((int)packedcol) & 0xffff; // 0 to 65535 range 760 761 int quadIdx = vertices % 4; 762 m_ix[ quadIdx ] = (unsigned int)((x + xo) * 128.0f); 763 m_iy[ quadIdx ] = (unsigned int)((y + yo) * 128.0f); 764 m_iz[ quadIdx ] = (unsigned int)((z + zo) * 128.0f); 765 m_clr[ quadIdx ] = (unsigned int)ipackedcol; 766 m_u[ quadIdx ] = (int)(uu * 4096.0f); 767 m_v[ quadIdx ] = (int)(v * 4096.0f); 768 m_t2[ quadIdx ] = ( ( _tex2 & 0x00f00000 ) >> 20 ) | ( _tex2 & 0x000000f0 ); 769 if( quadIdx == 3 ) 770 { 771 packCompactQuad(); 772 } 773#else 774 unsigned short packedcol = ((col & 0xf8000000 ) >> 16 ) | 775 ((col & 0x00fc0000 ) >> 13 ) | 776 ((col & 0x0000f800 ) >> 11 ); 777 int ipackedcol = ((int)packedcol) & 0xffff; // 0 to 65535 range 778 779 ipackedcol -= 32768; // -32768 to 32767 range 780 ipackedcol &= 0xffff; 781 782#ifdef __PSVITA__ 783 // AP - alpha cut out is expensive on vita. This will choose the correct data buffer depending on cut out enabled 784 int16_t* pShortData; 785 if( !alphaCutOutEnabled ) 786 { 787 pShortData = (int16_t*)&_array->data[p]; 788 } 789 else 790 { 791 pShortData = (int16_t*)&_array2->data[p2]; 792 } 793#else 794 int16_t* pShortData = (int16_t*)&_array->data[p]; 795 796#endif 797 798 799 800#ifdef __PS3__ 801 float tex2U = ((int16_t*)&_tex2)[1] + 8; 802 float tex2V = ((int16_t*)&_tex2)[0] + 8; 803 float colVal1 = ((col&0xff000000)>>24)/256.0f; 804 float colVal2 = ((col&0x00ff0000)>>16)/256.0f; 805 float colVal3 = ((col&0x0000ff00)>>8)/256.0f; 806 807// pShortData[0] = convertFloatToHFloat(x + xo); 808// pShortData[1] = convertFloatToHFloat(y + yo); 809// pShortData[2] = convertFloatToHFloat(z + zo); 810// pShortData[3] = convertFloatToHFloat(uu); 811// pShortData[4] = convertFloatToHFloat(tex2U + colVal1); 812// pShortData[5] = convertFloatToHFloat(tex2V + colVal2); 813// pShortData[6] = convertFloatToHFloat(colVal3); 814// pShortData[7] = convertFloatToHFloat(v); 815 816 pShortData[0] = (((int)((x + xo ) * 1024.0f))&0xffff); 817 pShortData[1] = (((int)((y + yo ) * 1024.0f))&0xffff); 818 pShortData[2] = (((int)((z + zo ) * 1024.0f))&0xffff); 819 pShortData[3] = ipackedcol; 820 pShortData[4] = (((int)(uu * 8192.0f))&0xffff); 821 pShortData[5] = (((int)(v * 8192.0f))&0xffff); 822 pShortData[6] = (((int)(tex2U * (8192.0f/256.0f)))&0xffff); 823 pShortData[7] = (((int)(tex2V * (8192.0f/256.0f)))&0xffff); 824 825 p += 4; 826#else 827 pShortData[0] = (((int)((x + xo ) * 1024.0f))&0xffff); 828 pShortData[1] = (((int)((y + yo ) * 1024.0f))&0xffff); 829 pShortData[2] = (((int)((z + zo ) * 1024.0f))&0xffff); 830 pShortData[3] = ipackedcol; 831 pShortData[4] = (((int)(uu * 8192.0f))&0xffff); 832 pShortData[5] = (((int)(v * 8192.0f))&0xffff); 833 int16_t u2 = ((int16_t*)&_tex2)[0]; 834 int16_t v2 = ((int16_t*)&_tex2)[1]; 835#if defined _XBOX_ONE || defined __ORBIS__ 836 // Optimisation - pack the second UVs into a single short (they could actually go in a byte), which frees up a short to store the x offset for this chunk in the vertex itself. 837 // This means that when rendering chunks, we don't need to update the vertex constants that specify the location for a chunk, when only the x offset has changed. 838 pShortData[6] = ( u2 << 8 ) | v2; 839 pShortData[7] = -xoo; 840#else 841 pShortData[6] = u2; 842 pShortData[7] = v2; 843#endif 844 845#ifdef __PSVITA__ 846 // AP - alpha cut out is expensive on vita. This will choose the correct data buffer depending on cut out enabled 847 if( !alphaCutOutEnabled ) 848 { 849 p += 4; 850 } 851 else 852 { 853 p2 += 4; 854 } 855#else 856 p += 4; 857#endif 858 859#endif 860 861#endif 862 863#ifdef __PSVITA__ 864 // AP - alpha cut out is expensive on vita. Increase the correct vertices depending on cut out enabled 865 if( !alphaCutOutEnabled ) 866 { 867 vertices++; 868 } 869 else 870 { 871 vertices2++; 872 } 873#else 874 875 vertices++; 876#endif 877 878#ifdef _XBOX 879 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 880#else 881 882#ifdef __PSVITA__ 883 // Max 65535 verts in D3D, so 65532 is the last point at the end of a quad to catch it 884 if ( (!alphaCutOutEnabled && vertices % 4 == 0 && ( ( p >= size - 4 * 4 ) || ( ( p / 4 ) >= 65532 ) )) || 885 (alphaCutOutEnabled && vertices2 % 4 == 0 && ( ( p2 >= size - 4 * 4 ) || ( ( p2 / 4 ) >= 65532 ) )) ) 886#else 887 888 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 889#endif 890 891#endif 892 { 893 end(); 894 tesselating = true; 895 } 896 } 897 else 898 { 899 if (mode == GL_QUADS && TRIANGLE_MODE && count % 4 == 0) 900 { 901 for (int i = 0; i < 2; i++) 902 { 903 int offs = 8 * (3 - i); 904 if (hasTexture) 905 { 906 _array->data[p + 3] = _array->data[p - offs + 3]; 907 _array->data[p + 4] = _array->data[p - offs + 4]; 908 } 909 if (hasColor) 910 { 911 _array->data[p + 5] = _array->data[p - offs + 5]; 912 } 913 914 _array->data[p + 0] = _array->data[p - offs + 0]; 915 _array->data[p + 1] = _array->data[p - offs + 1]; 916 _array->data[p + 2] = _array->data[p - offs + 2]; 917 918 vertices++; 919 p += 8; 920 } 921 } 922 923 if (hasTexture) 924 { 925 float *fdata = (float *)(_array->data + p + 3); 926 *fdata++ = uu; 927 *fdata++ = v; 928 } 929 if (hasColor) 930 { 931 _array->data[p + 5] = col; 932 } 933 if (hasNormal) 934 { 935 _array->data[p + 6] = _normal; 936 } 937 if (hasTexture2) 938 { 939#ifdef _XBOX 940 _array->data[p + 7] = ( ( _tex2 >> 16 ) & 0xffff ) | ( _tex2 << 16 ); 941#else 942 #ifdef __PS3__ 943 int16_t tex2U = ((int16_t*)&_tex2)[1] + 8; 944 int16_t tex2V = ((int16_t*)&_tex2)[0] + 8; 945 int16_t* pShortArray = (int16_t*)&_array->data[p + 7]; 946 pShortArray[0] = tex2U; 947 pShortArray[1] = tex2V; 948 #else 949 _array->data[p + 7] = _tex2; 950 #endif 951#endif 952 } 953 else 954 { 955 // -512 each for u/v will mean that the renderer will use global settings (set via 956 // RenderManager.StateSetVertexTextureUV) rather than these local ones 957 *(unsigned int *)(&_array->data[p + 7]) = 0xfe00fe00; 958 } 959 960 float *fdata = (float *)(_array->data + p); 961 *fdata++ = (x + xo); 962 *fdata++ = (y + yo); 963 *fdata++ = (z + zo); 964 p += 8; 965 966 vertices++; 967 if (vertices % 4 == 0 && p >= size - 8 * 4) 968 { 969 end(); 970 tesselating = true; 971 } 972 } 973} 974 975void Tesselator::color(int c) 976{ 977 int r = ((c >> 16) & 255); 978 int g = ((c >> 8) & 255); 979 int b = ((c) & 255); 980 color(r, g, b); 981} 982 983void Tesselator::color(int c, int alpha) 984{ 985 int r = ((c >> 16) & 255); 986 int g = ((c >> 8) & 255); 987 int b = ((c) & 255); 988 color(r, g, b, alpha); 989} 990 991void Tesselator::noColor() 992{ 993 _noColor = true; 994} 995 996#ifdef __PS3__ 997uint32_t _ConvertF32toX11Y11Z10N(float x, float y, float z) 998{ 999 // 11111111111 X 0x000007FF 1000 // 1111111111100000000000 Y 0x003FF800 1001 // 11111111110000000000000000000000 Z 0xFFC00000 1002 // ZZZZZZZZZZYYYYYYYYYYYXXXXXXXXXXX 1003 // #defines for X11Y11Z10N format 1004#define X11Y11Z10N_X_MASK 0x000007FF 1005#define X11Y11Z10N_X_BITS 11 1006#define X11Y11Z10N_X_SHIFT 0 1007 1008#define X11Y11Z10N_Y_MASK 0x003FF800 1009#define X11Y11Z10N_Y_BITS 11 1010#define X11Y11Z10N_Y_SHIFT 11 1011 1012#define X11Y11Z10N_Z_MASK 0xFFC00000 1013#define X11Y11Z10N_Z_BITS 10 1014#define X11Y11Z10N_Z_SHIFT 22 1015 1016#ifndef _CONTENT_PACKAGE 1017 if (x<-1.0f || x>1.0f) { printf("Value (%5.3f) should be in range [-1..1]. Conversion will clamp to X11Y11Z10N.\n", x); } 1018 if (y<-1.0f || y>1.0f) { printf("Value (%5.3f) should be in range [-1..1]. Conversion will clamp to X11Y11Z10N.\n", y); } 1019 if (z<-1.0f || z>1.0f) { printf("Value (%5.3f) should be in range [-1..1]. Conversion will clamp to X11Y11Z10N.\n", z); } 1020#endif 1021 1022 const uint32_t uX = ((int32_t(max(min(((x)*2047.f - 1.f)*0.5f, 1023.f), -1024.f)) & (X11Y11Z10N_X_MASK >> X11Y11Z10N_X_SHIFT)) << X11Y11Z10N_X_SHIFT); 1023 const uint32_t uY = ((int32_t(max(min(((y)*2047.f - 1.f)*0.5f, 1023.f), -1024.f)) & (X11Y11Z10N_Y_MASK >> X11Y11Z10N_Y_SHIFT)) << X11Y11Z10N_Y_SHIFT); 1024 const uint32_t uZ = ((int32_t(max(min(((z)*1023.f - 1.f)*0.5f, 511.f), -512.f )) & (X11Y11Z10N_Z_MASK >> X11Y11Z10N_Z_SHIFT)) << X11Y11Z10N_Z_SHIFT); 1025 const uint32_t xyz = uX | uY | uZ; 1026 return xyz; 1027} 1028#endif // __PS3__ 1029 1030void Tesselator::normal(float x, float y, float z) 1031{ 1032 hasNormal = true; 1033 1034#ifdef __PS3__ 1035 _normal = _ConvertF32toX11Y11Z10N(x,y,z); 1036#elif __PSVITA__ 1037 // AP - casting a negative value to 'byte' on Vita results in zero. changed to a signed 8 value 1038 int8_t xx = (int8_t) (x * 127); 1039 int8_t yy = (int8_t) (y * 127); 1040 int8_t zz = (int8_t) (z * 127); 1041 _normal = (xx & 0xff) | ((yy & 0xff) << 8) | ((zz & 0xff) << 16); 1042#else 1043 byte xx = (byte) (x * 127); 1044 byte yy = (byte) (y * 127); 1045 byte zz = (byte) (z * 127); 1046 _normal = (xx & 0xff) | ((yy & 0xff) << 8) | ((zz & 0xff) << 16); 1047#endif 1048} 1049 1050void Tesselator::offset(float xo, float yo, float zo) 1051{ 1052 this->xo = xo; 1053 this->yo = yo; 1054 this->zo = zo; 1055 1056 // 4J added 1057 this->xoo = xo; 1058 this->yoo = yo; 1059 this->zoo = zo; 1060} 1061 1062void Tesselator::addOffset(float x, float y, float z) 1063{ 1064 xo += x; 1065 yo += y; 1066 zo += z; 1067} 1068 1069bool Tesselator::hasMaxVertices() 1070{ 1071#ifdef __ORBIS__ 1072 // On PS4, the way we push data to the command buffer has a maximum size of a single command packet of 2^16 bytes, 1073 // and the effective maximum size will be slightly less than that due to packet headers and padding. 1074 int bytes = vertices * (useCompactFormat360?16:32); 1075 1076 return bytes > 60 * 1024; 1077#else 1078 return false; 1079#endif 1080}