mirror of
https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1.git
synced 2026-03-20 06:53:30 +00:00
438 lines
9.5 KiB
C++
Executable File
438 lines
9.5 KiB
C++
Executable File
#include "Tesselator.h"
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
|
|
Tesselator Tesselator::instance(sizeof(GLfloat) * MAX_FLOATS); // max size in bytes
|
|
|
|
const int VertexSizeBytes = sizeof(VERTEX);
|
|
|
|
Tesselator::Tesselator( int size )
|
|
: size(size),
|
|
vertices(0),
|
|
u(0), v(0),
|
|
_color(0),
|
|
hasColor(false),
|
|
hasTexture(false),
|
|
hasNormal(false),
|
|
p(0),
|
|
count(0),
|
|
_noColor(false),
|
|
mode(0),
|
|
xo(0), yo(0), zo(0),
|
|
_normal(0),
|
|
_sx(1), _sy(1),
|
|
|
|
tesselating(false),
|
|
vboId(-1),
|
|
vboCounts(128),
|
|
totalSize(0),
|
|
accessMode(ACCESS_STATIC),
|
|
maxVertices(size / sizeof(VERTEX)),
|
|
_voidBeginEnd(false)
|
|
{
|
|
vboIds = new GLuint[vboCounts];
|
|
|
|
_varray = new VERTEX[maxVertices];
|
|
|
|
char* a = (char*)&_varray[0];
|
|
char* b = (char*)&_varray[1];
|
|
LOGI("Vsize: %lu, %d\n", sizeof(VERTEX), (b-a));
|
|
}
|
|
|
|
Tesselator::~Tesselator()
|
|
{
|
|
delete[] vboIds;
|
|
delete[] _varray;
|
|
}
|
|
|
|
void Tesselator::init()
|
|
{
|
|
#ifndef STANDALONE_SERVER
|
|
glGenBuffers2(vboCounts, vboIds);
|
|
#endif
|
|
}
|
|
|
|
void Tesselator::clear()
|
|
{
|
|
accessMode = ACCESS_STATIC;
|
|
vertices = 0;
|
|
count = 0;
|
|
p = 0;
|
|
_voidBeginEnd = false;
|
|
}
|
|
|
|
int Tesselator::getVboCount() {
|
|
return vboCounts;
|
|
}
|
|
|
|
RenderChunk Tesselator::end( bool useMine, int bufferId )
|
|
{
|
|
#ifndef STANDALONE_SERVER
|
|
//if (!tesselating) throw /*new*/ IllegalStateException("Not tesselating!");
|
|
if (!tesselating)
|
|
LOGI("not tesselating!\n");
|
|
|
|
if (!tesselating || _voidBeginEnd) return RenderChunk();
|
|
|
|
tesselating = false;
|
|
const int o_vertices = vertices;
|
|
|
|
if (vertices > 0) {
|
|
if (p <= 0 || p > maxVertices) { clear(); return RenderChunk(); }
|
|
int bytes = p * sizeof(VERTEX);
|
|
if (bytes <= 0) return RenderChunk();
|
|
if (++vboId >= vboCounts)
|
|
vboId = 0;
|
|
|
|
#ifdef USE_VBO
|
|
// Using VBO, use default buffer id only if we don't send in any
|
|
if (!useMine) {
|
|
bufferId = vboIds[vboId];
|
|
}
|
|
#else
|
|
// Not using VBO - always use the next buffer object
|
|
bufferId = vboIds[vboId];
|
|
#endif
|
|
int access = GL_STATIC_DRAW;//(accessMode==ACCESS_DYNAMIC) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
|
|
glBindBuffer2(GL_ARRAY_BUFFER, bufferId);
|
|
glBufferData2(GL_ARRAY_BUFFER, bytes, _varray, access); // GL_STREAM_DRAW
|
|
|
|
totalSize += bytes;
|
|
|
|
#ifndef USE_VBO
|
|
// 0 1 2 3 4 5 6 7
|
|
// x y z u v c
|
|
if (hasTexture) {
|
|
glTexCoordPointer2(2, GL_FLOAT, VertexSizeBytes, (GLvoid*) (3 * 4));
|
|
glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
|
|
}
|
|
if (hasColor) {
|
|
glColorPointer2(4, GL_UNSIGNED_BYTE, VertexSizeBytes, (GLvoid*) (5 * 4));
|
|
glEnableClientState2(GL_COLOR_ARRAY);
|
|
}
|
|
if (hasNormal) {
|
|
glNormalPointer(GL_BYTE, VertexSizeBytes, (GLvoid*) (6 * 4));
|
|
glEnableClientState2(GL_NORMAL_ARRAY);
|
|
}
|
|
glVertexPointer2(3, GL_FLOAT, VertexSizeBytes, 0);
|
|
glEnableClientState2(GL_VERTEX_ARRAY);
|
|
|
|
if (mode == GL_QUADS) {
|
|
glDrawArrays2(GL_TRIANGLES, 0, vertices);
|
|
} else {
|
|
glDrawArrays2(mode, 0, vertices);
|
|
}
|
|
//printf("drawing %d tris, size %d (%d,%d,%d)\n", vertices, p, hasTexture, hasColor, hasNormal);
|
|
glDisableClientState2(GL_VERTEX_ARRAY);
|
|
if (hasTexture) glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
|
|
if (hasColor) glDisableClientState2(GL_COLOR_ARRAY);
|
|
if (hasNormal) glDisableClientState2(GL_NORMAL_ARRAY);
|
|
#endif /*!USE_VBO*/
|
|
}
|
|
|
|
clear();
|
|
RenderChunk out(bufferId, o_vertices);
|
|
//map.insert( std::make_pair(bufferId, out.id) );
|
|
return out;
|
|
#else
|
|
return RenderChunk();
|
|
#endif
|
|
|
|
}
|
|
|
|
void Tesselator::begin( int mode )
|
|
{
|
|
if (tesselating || _voidBeginEnd) {
|
|
if (tesselating && !_voidBeginEnd)
|
|
LOGI("already tesselating!\n");
|
|
return;
|
|
}
|
|
//if (tesselating) {
|
|
// throw /*new*/ IllegalStateException("Already tesselating!");
|
|
//}
|
|
tesselating = true;
|
|
|
|
clear();
|
|
this->mode = mode;
|
|
hasNormal = false;
|
|
hasColor = false;
|
|
hasTexture = false;
|
|
_noColor = false;
|
|
}
|
|
|
|
void Tesselator::begin()
|
|
{
|
|
begin(GL_QUADS);
|
|
}
|
|
|
|
void Tesselator::tex( float u, float v )
|
|
{
|
|
hasTexture = true;
|
|
this->u = u;
|
|
this->v = v;
|
|
}
|
|
|
|
int Tesselator::getColor() {
|
|
return _color;
|
|
}
|
|
|
|
void Tesselator::color( float r, float g, float b )
|
|
{
|
|
color((int) (r * 255), (int) (g * 255), (int) (b * 255));
|
|
}
|
|
|
|
void Tesselator::color( float r, float g, float b, float a )
|
|
{
|
|
color((int) (r * 255), (int) (g * 255), (int) (b * 255), (int) (a * 255));
|
|
}
|
|
|
|
void Tesselator::color( int r, int g, int b )
|
|
{
|
|
color(r, g, b, 255);
|
|
}
|
|
|
|
void Tesselator::color( int r, int g, int b, int a )
|
|
{
|
|
if (_noColor) return;
|
|
|
|
if (r > 255) r = 255;
|
|
if (g > 255) g = 255;
|
|
if (b > 255) b = 255;
|
|
if (a > 255) a = 255;
|
|
if (r < 0) r = 0;
|
|
if (g < 0) g = 0;
|
|
if (b < 0) b = 0;
|
|
if (a < 0) a = 0;
|
|
|
|
hasColor = true;
|
|
//if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
|
|
if (true) {
|
|
_color = (a << 24) | (b << 16) | (g << 8) | (r);
|
|
} else {
|
|
_color = (r << 24) | (g << 16) | (b << 8) | (a);
|
|
}
|
|
}
|
|
|
|
void Tesselator::color( char r, char g, char b )
|
|
{
|
|
color(r & 0xff, g & 0xff, b & 0xff);
|
|
}
|
|
|
|
void Tesselator::color( int c )
|
|
{
|
|
int r = ((c >> 16) & 255);
|
|
int g = ((c >> 8) & 255);
|
|
int b = ((c) & 255);
|
|
color(r, g, b);
|
|
}
|
|
|
|
//@note: doesn't care about endianess
|
|
void Tesselator::colorABGR( int c )
|
|
{
|
|
if (_noColor) return;
|
|
hasColor = true;
|
|
_color = c;
|
|
}
|
|
|
|
void Tesselator::color( int c, int alpha )
|
|
{
|
|
int r = ((c >> 16) & 255);
|
|
int g = ((c >> 8) & 255);
|
|
int b = ((c) & 255);
|
|
color(r, g, b, alpha);
|
|
}
|
|
|
|
void Tesselator::vertexUV( float x, float y, float z, float u, float v )
|
|
{
|
|
tex(u, v);
|
|
vertex(x, y, z);
|
|
}
|
|
|
|
void Tesselator::scale2d(float sx, float sy) {
|
|
_sx *= sx;
|
|
_sy *= sy;
|
|
}
|
|
|
|
void Tesselator::resetScale() {
|
|
_sx = _sy = 1;
|
|
}
|
|
|
|
void Tesselator::vertex( float x, float y, float z )
|
|
{
|
|
#ifndef STANDALONE_SERVER
|
|
count++;
|
|
|
|
if (mode == GL_QUADS && (count & 3) == 0) {
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
const int offs = 3 - i;
|
|
if (p - offs < 0 || p >= maxVertices) { clear(); return; }
|
|
VERTEX& src = _varray[p - offs];
|
|
VERTEX& dst = _varray[p];
|
|
|
|
if (hasTexture) {
|
|
dst.u = src.u;
|
|
dst.v = src.v;
|
|
}
|
|
if (hasColor) {
|
|
dst.color = src.color;
|
|
}
|
|
//if (hasNormal) {
|
|
// dst.normal = src.normal;
|
|
//}
|
|
|
|
dst.x = src.x;
|
|
dst.y = src.y;
|
|
dst.z = src.z;
|
|
|
|
++vertices;
|
|
++p;
|
|
}
|
|
}
|
|
|
|
if (p < 0 || p >= maxVertices) { clear(); return; }
|
|
VERTEX& vertex = _varray[p];
|
|
|
|
if (hasTexture) {
|
|
vertex.u = u;
|
|
vertex.v = v;
|
|
}
|
|
if (hasColor) {
|
|
vertex.color = _color;
|
|
}
|
|
//if (hasNormal) {
|
|
// vertex.normal = _normal;
|
|
//}
|
|
|
|
vertex.x = _sx * (x + xo);
|
|
vertex.y = _sy * (y + yo);
|
|
vertex.z = z + zo;
|
|
|
|
++p;
|
|
++vertices;
|
|
|
|
if ((vertices & 3) == 0 && p >= maxVertices-1) {
|
|
for (int i = 0; i < 3; ++i)
|
|
printf("Overwriting the vertex buffer! This chunk/entity won't show up\n");
|
|
clear();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void Tesselator::noColor()
|
|
{
|
|
_noColor = true;
|
|
}
|
|
|
|
void Tesselator::setAccessMode(int mode)
|
|
{
|
|
accessMode = mode;
|
|
}
|
|
|
|
void Tesselator::normal( float x, float y, float z )
|
|
{
|
|
static int _warn_t = 0;
|
|
if ((++_warn_t & 32767) == 1)
|
|
LOGI("WARNING: Can't use normals (Tesselator::normal)\n");
|
|
return;
|
|
|
|
if (!tesselating) printf("But..");
|
|
hasNormal = true;
|
|
char xx = (char) (x * 128);
|
|
char yy = (char) (y * 127);
|
|
char zz = (char) (z * 127);
|
|
|
|
_normal = xx | (yy << 8) | (zz << 16);
|
|
}
|
|
|
|
void Tesselator::offset( float xo, float yo, float zo ) {
|
|
this->xo = xo;
|
|
this->yo = yo;
|
|
this->zo = zo;
|
|
}
|
|
|
|
void Tesselator::addOffset( float x, float y, float z ) {
|
|
xo += x;
|
|
yo += y;
|
|
zo += z;
|
|
}
|
|
|
|
void Tesselator::offset( const Vec3& v ) {
|
|
xo = v.x;
|
|
yo = v.y;
|
|
zo = v.z;
|
|
}
|
|
|
|
void Tesselator::addOffset( const Vec3& v ) {
|
|
xo += v.x;
|
|
yo += v.y;
|
|
zo += v.z;
|
|
}
|
|
|
|
void Tesselator::draw()
|
|
{
|
|
#ifndef STANDALONE_SERVER
|
|
if (!tesselating)
|
|
LOGI("not (draw) tesselating!\n");
|
|
|
|
if (!tesselating || _voidBeginEnd)
|
|
return;
|
|
|
|
tesselating = false;
|
|
|
|
if (vertices > 0) {
|
|
if (p <= 0 || p > maxVertices) { clear(); return; }
|
|
int bytes = p * sizeof(VERTEX);
|
|
if (bytes <= 0) { clear(); return; }
|
|
if (++vboId >= vboCounts)
|
|
vboId = 0;
|
|
|
|
int bufferId = vboIds[vboId];
|
|
|
|
int access = GL_DYNAMIC_DRAW;//(accessMode==ACCESS_DYNAMIC) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
|
|
glBindBuffer2(GL_ARRAY_BUFFER, bufferId);
|
|
glBufferData2(GL_ARRAY_BUFFER, bytes, _varray, access); // GL_STREAM_DRAW
|
|
|
|
if (hasTexture) {
|
|
glTexCoordPointer2(2, GL_FLOAT, VertexSizeBytes, (GLvoid*) (3 * 4));
|
|
//glTexCoordPointer2(2, GL_FLOAT, VertexSizeBytes, (GLvoid*) &_varray->u);
|
|
glEnableClientState2(GL_TEXTURE_COORD_ARRAY);
|
|
}
|
|
if (hasColor) {
|
|
glColorPointer2(4, GL_UNSIGNED_BYTE, VertexSizeBytes, (GLvoid*) (5 * 4));
|
|
//glColorPointer2(4, GL_UNSIGNED_BYTE, VertexSizeBytes, (GLvoid*) &_varray->color);
|
|
glEnableClientState2(GL_COLOR_ARRAY);
|
|
}
|
|
//if (hasNormal) {
|
|
// glNormalPointer(GL_BYTE, VertexSizeBytes, (GLvoid*) (6 * 4));
|
|
// glEnableClientState2(GL_NORMAL_ARRAY);
|
|
//}
|
|
//glVertexPointer2(3, GL_FLOAT, VertexSizeBytes, (GLvoid*)&_varray);
|
|
glVertexPointer2(3, GL_FLOAT, VertexSizeBytes, 0);
|
|
glEnableClientState2(GL_VERTEX_ARRAY);
|
|
|
|
if (mode == GL_QUADS) {
|
|
glDrawArrays2(GL_TRIANGLES, 0, vertices);
|
|
} else {
|
|
glDrawArrays2(mode, 0, vertices);
|
|
}
|
|
|
|
glDisableClientState2(GL_VERTEX_ARRAY);
|
|
if (hasTexture) glDisableClientState2(GL_TEXTURE_COORD_ARRAY);
|
|
if (hasColor) glDisableClientState2(GL_COLOR_ARRAY);
|
|
//if (hasNormal) glDisableClientState2(GL_NORMAL_ARRAY);
|
|
}
|
|
|
|
clear();
|
|
#endif
|
|
}
|
|
|
|
void Tesselator::voidBeginAndEndCalls(bool doVoid) {
|
|
_voidBeginEnd = doVoid;
|
|
}
|
|
|
|
void Tesselator::enableColor() {
|
|
_noColor = false;
|
|
}
|