Archived
0

create Tessellator

This commit is contained in:
2015-09-18 12:20:03 +03:00
parent 487e2b7c61
commit f0c24650d2

View File

@@ -0,0 +1,275 @@
package ru.dmitriymx.lwjgl.tools;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
public class Tessellator {
private static Tessellator instance = new Tessellator();
private int draw_mode;
private float[] float_buffer;
private int float_buffer_position;
private boolean use_dl, use_vbo, use_va;
private int vertex_count;
private boolean use_color, use_texture;
private int display_list_id;
private Tessellator() {
float_buffer = new float[0x200000];
}
public Tessellator getInstance() {
return instance;
}
public void reset() {
use_vbo = false;
draw_mode = 0;
vertex_count = 0;
float_buffer_position = 0;
use_color = false;
use_texture = false;
}
public void addVertex(float x, float y, float z) {
if (use_dl) {
dl_add_vertex(x, y, z);
} else if (use_vbo) {
vbo_add_vertex(x, y, z);
} else if (use_va) {
va_add_vertex(x, y, z);
}
}
public Tessellator setTexture(float u, float v) {
if (use_dl) {
dl_set_texture(u, v);
} else if (use_vbo) {
vbo_set_texture(u, v);
} else if (use_va) {
va_set_texture(u, v);
}
return this;
}
public Tessellator setColor(float red, float green, float blue, float alpha) {
if (use_dl) {
dl_set_color(red, green, blue, alpha);
} else if (use_vbo) {
vbo_set_color(red, green, blue, alpha);
} else if (use_va) {
va_set_color(red, green, blue, alpha);
}
return this;
}
public Tessellator setColor(float red, float green, float blue) {
return setColor(red, green, blue, 1f);
}
// DISPLAY LIST (DL) ======================================================
public void startDrawingUseDL(int drawMode) {
use_dl = true;
display_list_id = glGenLists(1);
glNewList(display_list_id, GL_COMPILE);
glBegin(drawMode);
}
private void dl_add_vertex(float x, float y, float z) {
glVertex3f(x, y, z);
}
private void dl_set_color(float red, float green, float blue, float alpha) {
glColor4f(red, green, blue, alpha);
}
private void dl_set_texture(float u, float v) {
glTexCoord2f(u, v);
}
public int createDL() {
if (use_dl) {
glEnd();
glEndList();
int result = display_list_id;
reset();
return result;
} else {
throw new IllegalAccessError("Drawing with display list not started");
}
}
public void removeDL(int displayListId){
glDeleteLists(displayListId, 1);
}
public void drawDL(int displayListId) {
glCallList(displayListId);
}
// VERTEX BUFFER OBJECT (VBO) =============================================
public void startDrawingUseVBO(int drawMode) {
draw_mode = drawMode;
use_vbo = true;
}
private void vbo_add_vertex(float x, float y, float z) {
float_buffer[float_buffer_position] = x;
float_buffer[float_buffer_position + 1] = y;
float_buffer[float_buffer_position + 2] = z;
float_buffer_position += 9;
vertex_count++;
}
private void vbo_set_color(float red, float green, float blue, float alpha) {
float_buffer[float_buffer_position + 5] = red;
float_buffer[float_buffer_position + 6] = green;
float_buffer[float_buffer_position + 7] = blue;
float_buffer[float_buffer_position + 8] = alpha;
use_color = true;
}
private void vbo_set_texture(float u, float v) {
float_buffer[float_buffer_position + 3] = u;
float_buffer[float_buffer_position + 4] = v;
use_texture = true;
}
public int createVBO() {
if (use_vbo) {
if (vertex_count > 0) {
FloatBuffer vbo_buffer = BufferUtils.createFloatBuffer(float_buffer_position);
vbo_buffer.put(float_buffer, 0, float_buffer_position);
vbo_buffer.flip();
int vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vbo_buffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
int r2 = vboId | (draw_mode << 8) | (vertex_count << 16) | ((use_color ? 1 : 0) << 24) | ((use_texture ? 1 : 0) << 32);
reset();
return r2;
} else {
throw new IllegalAccessError("Vertex count < 1");
}
} else {
throw new IllegalAccessError("Drawing with vertex buffer object not started");
}
}
public void removeVBO(long vboData){
glDeleteBuffers((int) (0b11111111 & vboData));
}
public void drawVBO(int vboData) {
glBindBuffer(GL_ARRAY_BUFFER, (int) (0b11111111 & vboData));
boolean has_color = (0b11111111 & vboData >>> 24) == 1;
boolean has_texture = (0b11111111 & vboData >>> 32) == 1;
if (has_color) {
glEnableClientState(GL_COLOR_ARRAY);
// 12L -> 3 << 2
glColorPointer(4, GL_FLOAT, 9 << 2, 5 << 2);
}
if (has_texture) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// X << 3 -> (X * 2) << 2
glTexCoordPointer(2, GL_FLOAT, 9 << 2, 3 << 2);
}
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 9 << 2, 0);
glDrawArrays((int) (0b11111111 & vboData >>> 8), 0, (int) (0b11111111 & vboData >>> 16));
if (has_texture) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (has_color) {
glDisableClientState(GL_COLOR_ARRAY);
}
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
// VERTEX ARRAY (VA) ======================================================
public void startDrawingUseVA(int drawMode) {
use_va = true;
draw_mode = drawMode;
use_color = false; //TODO а надоли? есть же reset()
use_texture = false;
}
private void va_add_vertex(float x, float y, float z) {
float_buffer[float_buffer_position] = x;
float_buffer[float_buffer_position + 1] = y;
float_buffer[float_buffer_position + 2] = z;
float_buffer_position += 9;
vertex_count++;
}
private void va_set_color(float red, float green, float blue, float alpha) {
float_buffer[float_buffer_position + 5] = red;
float_buffer[float_buffer_position + 6] = green;
float_buffer[float_buffer_position + 7] = blue;
float_buffer[float_buffer_position + 8] = alpha;
use_color = true;
}
private void va_set_texture(float u, float v) {
float_buffer[float_buffer_position + 3] = u;
float_buffer[float_buffer_position + 4] = v;
use_texture = true;
}
public void drawVA() {
if (use_va) {
if (vertex_count > 0) {
FloatBuffer va_buffer = BufferUtils.createFloatBuffer(float_buffer_position);
va_buffer.put(float_buffer, 0, float_buffer_position);
va_buffer.flip();
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, 9 << 2, va_buffer);
// 1 float = 32 bits = 4 bytes
// => sizeOf(float) * 9 = (4 bytes) * 9 = _36 bytes_ = (9 << 2)
if (use_color) {
va_buffer.position(5);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, 9 << 2, va_buffer);
}
if (use_texture) {
va_buffer.position(3);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, 9 << 2, va_buffer);
}
glDrawArrays(draw_mode, 0, vertex_count);
if (use_texture) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (use_color) glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
reset();
}
}
}
}