create Tessellator
This commit is contained in:
275
src/java/ru/dmitriymx/lwjgl/tools/Tessellator.java
Normal file
275
src/java/ru/dmitriymx/lwjgl/tools/Tessellator.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user