/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Modifications
Copyright 2003-2004 Bytonic Software
Copyright 2010 Google Inc.
*/
package com.googlecode.gwtquake.client;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import com.google.gwt.html5.client.CanvasElement;
import com.google.gwt.html5.client.CanvasRenderingContext2D;
import com.googlecode.gwtquake.shared.render.DisplayMode;
import com.googlecode.gwtquake.shared.render.Gl1Context;
import com.googlecode.gwtquake.shared.util.CanvasHelper;
/**
* Crude attempt at showing some of the output on a regular 2D canvas for
* debugging.
*
* @author Stefan Haustein
*/
public class WireframeGl1Context extends Gl1Context {
FloatBuffer colorBuffer;
private int vertexPointerSize;
private int vertexPointerType;
private int vertexPointerStride;
private Buffer vertexPointerData;
private int colorPointerSize;
private int colorPointerType;
private int colorPointerStride;
private Buffer colorPointerBuffer;
private String uniformColor;
private boolean colorArrayEnabled;
private CanvasRenderingContext2D ctx;
private int vertexPointerPosition;
private boolean debugHighlight;
private final CanvasElement canvas;
public WireframeGl1Context(CanvasElement canvas) {
this.canvas = canvas;
swapBuffers();
}
@Override
public final void glBindTexture(int t, int i) {
}
@Override
public final void glBlendFunc(int a, int b) {
}
@Override
public final void glClear(int mask) {
ctx.clearRect(0, 0, 3000, 3000);
}
@Override
public final void glColor4f(float red, float green, float blue, float alpha) {
uniformColor = CanvasHelper.getCssColor(red, green, blue, alpha);
}
@Override
public void glDrawElements(int mode, ShortBuffer indices) {
debugDraw(mode, indices.position(),
indices.limit(), indices);
}
@Override
public final void glEnable(int i) {
}
@Override
public final int glGetError() {
return GL_NO_ERROR;
}
@Override
public final void glClearColor(float f, float g, float h, float i) {
}
private void debugDraw(int mode, int first, int count, Buffer indices) {
updateMvpMatrix();
float[] v = new float[4];
float[] result = new float[4];
float x0 = 0;
float x1 = 0;
float x2 = 0;
float y0 = 0;
float y1 = 0;
float y2 = 0;
float z0 = 0;
float z1 = 0;
float z2 = 0;
// System.out.println("Viewport x: " + viewportX + " y: " + viewportY
// + " w:" + viewportW + " h:" + viewportH);
// if (AUTO_REWIND) {
// vertexPointerData.rewind();
// }
if (!(vertexPointerData instanceof FloatBuffer)) {
throw new RuntimeException("float coordinates only!");
}
FloatBuffer vertexBuf = (FloatBuffer) vertexPointerData;
int stride = vertexPointerStride == 0 ? vertexPointerSize : vertexPointerStride / 4;
if (vertexPointerSize != 3 || vertexPointerStride % 4 != 0) {
System.out.println("VertexPointerSize: " + vertexPointerSize);
}
int[] view = { viewportX, viewportY, viewportW, viewportH };
float[] win = new float[3];
// System.out.println("VertexPointerType: " + GLDebugWrapper.c(vertexPointerType));
int p = vertexPointerPosition;
boolean v2 = false;
boolean v1 = false;
boolean v0 = false;
if(debugHighlight) {
System.out.println("going to draw "+ count + " points");
}
for (int j = 0; j < count; j++) {
int i;
if (indices == null) {
i = first + j;
} else if (indices instanceof ShortBuffer) {
i = ((ShortBuffer) indices).get(j);
} else if (indices instanceof IntBuffer) {
i = ((IntBuffer) indices).get(j);
} else {
throw new RuntimeException("Unsupported: " + indices.getClass());
}
// TODO(Haustein) use MVP matrix here...
// GLU.gluProject(vertexBuf.get(p + i * stride), vertexBuf.get(p + i * stride + 1),
// vertexBuf.get(p + i * stride + 2), modelViewMatrix, 0, projectionMatrix,
// 0, view, 0, win, 0);
if (mode != GL_TRIANGLE_FAN || j == 2) {
x0 = x1;
y0 = y1;
z0 = z1;
v0 = v1;
}
x1 = x2;
y1 = y2;
z1 = z2;
v1 = v2;
v2 = project(vertexBuf.get(p + i * stride), vertexBuf.get(p + i * stride + 1),
vertexBuf.get(p + i * stride + 2), view, win);
if(!v2 && debugHighlight) {
System.out.println("projection returned false");
}
x2 = win[0] ;
y2 = viewportH - win[1] ;
z2 = win[2];
v2 &= z2 < 1;
// v2 &= x2 > viewportX && x2 < viewportX + viewportW;
// v2 &= y2 > viewportY && y2 < viewportY + viewportH;
int k = i * 4;
boolean fill = false;
boolean draw = false;
switch (mode) {
case GL_TRIANGLE_FAN:
case GL_TRIANGLE_STRIP:
fill = j >= 2;
break;
case GL_TRIANGLES:
fill = (j % 3) == 2;
break;
case GL_LINES:
draw = (j & 1) == 1;
break;
default:
throw new IllegalArgumentException();
}
if (fill && v0 && v1 && v2) {
float z = (z1+z0+z2)/3;
float alpha = (1 - z);
if (alpha < 0) {
alpha = 0;
} else if (alpha > 1) {
alpha = 1;
}
float am1 = alpha-1;
alpha = 1-am1*am1*am1*am1;
// System.out.println("z: "+z + " sqrt "+ Math.sqrt(z) + " sqr "+ z*z + " e" + Math.exp(z));
ctx.setGlobalAlpha(debugHighlight ? 0.5f : alpha);
if (debugHighlight) {
System.out.println("x0: " + x0 + " y0: "+ y0 +
"x1: " + x1 + " y1: " + y1 + " x2: " + x2 + " y2: " + y2);
}
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineTo(x0, y0);
ctx.stroke();
} else if (draw && v1 && v2) {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
}
}
@Override
public void glDrawArrays(int mode, int first, int count) {
// mv-matrix
//
debugDraw(mode, first, count, null);
}
// private void prepareDraw() {
// Matrix
// .multiplyMM(mvpMatrix, 0, projectionMatrix, 0, modelViewMatrix,
// 0);
// }
public final void glHint(int h, int i) {
}
public final void glReadPixels(int i, int j, int width, int height,
int format, int type, IntBuffer buffer) {
}
@Override
public final void swapBuffers() {
ctx = canvas.getContext2D();
ctx.setFont("8px Courier");
ctx.setStrokeStyleColor("#00ff00");
ctx.setFillStyleColor("#00ff00");
}
public final void glEnableClientState(int i) {
switch (i) {
case GL_COLOR_ARRAY:
colorArrayEnabled = true;
break;
case GL_VERTEX_ARRAY:
break;
case GL_TEXTURE_COORD_ARRAY:
break;
default:
System.out.println("unsupported / unrecogized client state");
}
}
public final void glDisableClientState(int i) {
switch (i) {
case GL_COLOR_ARRAY:
colorArrayEnabled = false;
break;
case GL_VERTEX_ARRAY:
break;
case GL_TEXTURE_COORD_ARRAY:
break;
default:
System.out.println("unsupported / unrecogized client state");
}
}
@Override
public void glColorPointer(int size, int stride, FloatBuffer buf) {
colorPointerSize = size;
colorPointerType = GL_FLOAT;
colorPointerStride = stride;
colorPointerBuffer = buf;
}
@Override
public void glColorPointer(int size, boolean b, int stride, ByteBuffer buf) {
colorPointerSize = size;
colorPointerType = GL_UNSIGNED_BYTE;
colorPointerStride = stride;
colorPointerBuffer = buf;
}
@Override
public void glVertexPointer(int size, int byteStride, FloatBuffer buf) {
vertexPointerSize = size;
vertexPointerType = GL_FLOAT;
vertexPointerStride = byteStride;
vertexPointerData = buf;
vertexPointerPosition = buf.position();
}
public final void glScissor(int i, int j, int width, int height) {
}
public final void glTexEnvx(int env, int mode, int replace) {
}
@Override
public void glTexParameterf(int target, int pname, float param) {
}
public final void glDeleteTextures(int i, int[] textureId, int j) {
}
public final void glGenTextures(int n, int[] result, int offset) {
}
public final void glTexCoordPointer(int size, int type, int stride,
Buffer buf) {
}
public final void glDisable(int i) {
}
public final void glCullFace(int c) {
}
public final void glFrontFace(int f) {
}
public final void glShadeModel(int s) {
}
@Override
public void glAlphaFunc(int i, float j) {
}
@Override
public void glDeleteTextures(IntBuffer texnumBuffer) {
}
@Override
public void glDepthFunc(int func) {
}
@Override
public void glDepthMask(boolean b) {
}
@Override
public void glDepthRange(float gldepthmin, float gldepthmax) {
}
@Override
public void glDrawBuffer(int buf) {
// selects front or back buffer (???)
}
@Override
public void glFinish() {
}
@Override
public String glGetString(int id) {
switch (id) {
case GL_VENDOR: return "Google";
case GL_RENDERER: return "Wireframe Debug OpenGL Engine";
case GL_VERSION: return "2.0 Wireframe-1.0.0";
case GL_EXTENSIONS: return "GL_ARB_transpose_matrix GL_ARB_vertex_program GL_ARB_vertex_blend GL_ARB_window_pos GL_ARB_shader_objects GL_ARB_vertex_shader GL_ARB_shading_language_100 GL_EXT_multi_draw_arrays GL_EXT_clip_volume_hint GL_EXT_rescale_normal GL_EXT_draw_range_elements GL_EXT_fog_coord GL_EXT_gpu_program_parameters GL_EXT_geometry_shader4 GL_EXT_transform_feedback GL_APPLE_client_storage GL_APPLE_specular_vector GL_APPLE_transform_hint GL_APPLE_packed_pixels GL_APPLE_fence GL_APPLE_vertex_array_object GL_APPLE_vertex_program_evaluators GL_APPLE_element_array GL_APPLE_flush_render GL_APPLE_aux_depth_stencil GL_NV_texgen_reflection GL_NV_light_max_exponent GL_IBM_rasterpos_clip GL_SGIS_generate_mipmap GL_ARB_imaging GL_ARB_point_parameters GL_ARB_texture_env_crossbar GL_ARB_texture_border_clamp GL_ARB_multitexture GL_ARB_texture_env_add GL_ARB_texture_cube_map GL_ARB_texture_env_dot3 GL_ARB_multisample GL_ARB_texture_env_combine GL_ARB_texture_compression GL_ARB_texture_mirrored_repeat GL_ARB_shadow GL_ARB_depth_texture GL_ARB_fragment_program GL_ARB_fragment_program_shadow GL_ARB_fragment_shader GL_ARB_occlusion_query GL_ARB_point_sprite GL_ARB_texture_non_power_of_two GL_ARB_vertex_buffer_object GL_ARB_pixel_buffer_object GL_ARB_draw_buffers GL_ARB_shader_texture_lod GL_EXT_compiled_vertex_array GL_EXT_framebuffer_object GL_EXT_framebuffer_blit GL_EXT_framebuffer_multisample GL_EXT_texture_rectangle GL_ARB_texture_rectangle GL_EXT_texture_env_add GL_EXT_blend_color GL_EXT_blend_minmax GL_EXT_blend_subtract GL_EXT_texture_lod_bias GL_EXT_abgr GL_EXT_bgra GL_EXT_stencil_wrap GL_EXT_texture_filter_anisotropic GL_EXT_secondary_color GL_EXT_blend_func_separate GL_EXT_shadow_funcs GL_EXT_stencil_two_side GL_EXT_depth_bounds_test GL_EXT_texture_compression_s3tc GL_EXT_texture_compression_dxt1 GL_EXT_texture_sRGB GL_EXT_blend_equation_separate GL_EXT_texture_mirror_clamp GL_EXT_packed_depth_stencil GL_EXT_bindable_uniform GL_EXT_texture_integer GL_EXT_gpu_shader4 GL_EXT_draw_buffers2 GL_APPLE_flush_buffer_range GL_APPLE_ycbcr_422 GL_APPLE_vertex_array_range GL_APPLE_texture_range GL_APPLE_float_pixels GL_ATI_texture_float GL_ARB_texture_float GL_ARB_half_float_pixel GL_APPLE_pixel_buffer GL_APPLE_object_purgeable GL_NV_point_sprite GL_NV_register_combiners GL_NV_register_combiners2 GL_NV_blend_square GL_NV_texture_shader GL_NV_texture_shader2 GL_NV_texture_shader3 GL_NV_fog_distance GL_NV_depth_clamp GL_NV_multisample_filter_hint GL_NV_fragment_program_option GL_NV_fragment_program2 GL_NV_vertex_program2_option GL_NV_vertex_program3 GL_ATI_texture_mirror_once GL_ATI_texture_env_combine3 GL_ATI_separate_stencil GL_SGIS_texture_edge_clamp GL_SGIS_texture_lod ";
default: return "Unknown Sting ID";
}
}
@Override
public void glPixelStorei(int i, int j) {
}
@Override
public void glPointSize(float value) {
}
@Override
public void glPolygonMode(int i, int j) {
}
@Override
public void glReadPixels(int x, int y, int width, int height, int glBgr,
int glUnsignedByte, ByteBuffer image) {
}
@Override
public void glTexCoordPointer(int size, int byteStride, FloatBuffer buf) {
}
@Override
public void glTexEnvi(int glTextureEnv, int glTextureEnvMode, int mode) {
}
@Override
public void glTexImage2D(int target, int level, int internalformat,
int width, int height, int border, int format, int type,
ByteBuffer pixels) {
}
@Override
public void glTexImage2D(int target, int level, int internalformat,
int width, int height, int border, int format, int type,
IntBuffer pixels) {
}
@Override
public void glTexParameteri(int glTexture2d, int glTextureMinFilter,
int glFilterMin) {
}
@Override
public void glTexSubImage2D(int target, int level, int xoffset,
int yoffset, int width, int height, int format, int type,
ByteBuffer pixels) {
}
@Override
public void glTexSubImage2D(int target, int level, int xoffset,
int yoffset, int width, int height, int format, int type,
IntBuffer pixels) {
}
@Override
public void shutdow() {
// ignored
}
@Override
public void glActiveTexture(int texture) {
// TODO Auto-generated method stub
}
@Override
public void glClientActiveTexture(int texture) {
// TODO Auto-generated method stub
}
@Override
public void glPointParameterf(int id, float value) {
// TODO Auto-generated method stub
}
public CanvasRenderingContext2D get2dContext() {
return ctx;
}
@Override
public void debugHighlight(boolean on) {
System.out.println("debugHL: " + on);
debugHighlight = on;
ctx.setStrokeStyleColor(on ? "#ff8888" : "#0000ff");
}
}