package org.jzy3d.plot3d.primitives.axes;
import java.nio.FloatBuffer;
import org.apache.log4j.Logger;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.plot3d.primitives.axes.layout.IAxeLayout;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
/**
* This {@link AxeBox} implementation was the first to appear in Jzy3d.
* It computes hidden faces via method {@link getHiddenQuads} using the
* OpenGL feedback buffer, which seems to fail on some laptop GPU.
* (especially Lenovo notepads).
*
* @author Martin Pernollet
*/
public class FeedbackBufferAxeBox extends AxeBox implements IAxe{
static Logger logger = Logger.getLogger(FeedbackBufferAxeBox.class);
public FeedbackBufferAxeBox(BoundingBox3d bbox){
super(bbox);
}
public FeedbackBufferAxeBox(BoundingBox3d bbox, IAxeLayout layout){
super(bbox, layout);
}
/**
* Render the cube into the feedback buffer, in order to parse feedback
* and determine which quad where displayed or not.
*/
protected boolean [] getHiddenQuads(GL gl){
int feedbacklength = 1024;
FloatBuffer floatbuffer = Buffers.newDirectFloatBuffer(feedbacklength);
float [] feedback = new float[feedbacklength];
// Draw the cube into feedback buffer
gl.getGL2().glFeedbackBuffer(feedbacklength, GL2.GL_3D_COLOR, floatbuffer);
gl.getGL2().glRenderMode(GL2.GL_FEEDBACK);
drawCube(gl, GL2.GL_FEEDBACK);
gl.getGL2().glRenderMode(GL2.GL_RENDER);
// Parse feedback buffer and return hidden quads
floatbuffer.get(feedback);
return getEmptyTokens(6, feedback, feedbacklength);
}
/**
* This utility function inform wether a GL_PASS_THROUGH_TOKEN was followed
* by other OpenGL tokens (GL_POLYGON_TOKEN, GL_LINE_TOKEN, etc), or not.
* In the first case, the given token is considered as non empty, in the other
* case, it is considered as empty.
* The expected use of this function is to inform the user wether a polygon
* has been displayed or not in the case Culling was activated.
*
* Note: this function is only intended to work in the case where gl.glFeedbackBuffer
* is called with GL.GL_3D_COLOR as second argument, i.e. vertices are made of
* x, y, z, alpha values and a color. Thus, no texture may be used, and trying
* to parse a GL_BITMAP_TOKEN, GL_DRAW_PIXEL_TOKEN, or GL_COPY_PIXEL_TOKEN
* will throw a RuntimeException.
*
* Note: this function only works with PASS_THROUGH_TOKEN with a
* positive integer value, since this value will be used as an index in
* the boolean array returned by the function
*
* TODO: use a map to associate a float token to a polygon with an id?
*
* @throws a RuntimeException if a parsed token is either GL_BITMAP_TOKEN, GL_DRAW_PIXEL_TOKEN, or GL_COPY_PIXEL_TOKEN.
*/
protected boolean[] getEmptyTokens(int ntokens, float[] buffer, int size){
boolean[] isempty = new boolean[ntokens];
boolean printout = false; // for debugging parsing
int count = size;
float token_type;
float prevtoken_type = Float.NaN;
float passthrough_value = Float.NaN;
float prevpassthrough_value = Float.NaN;
int prevtoken_id;
float EMPTY_TOKEN = 0.0f;
while(count>0){
token_type = buffer[size-count];
count--;
// Case of a PASS THROUGH token
if (token_type == GL2.GL_PASS_THROUGH_TOKEN) { // can't use switch cause we have floats
passthrough_value = buffer[size - count];
count--;
if(printout)
logger.info("GL.GL_PASS_THROUGH_TOKEN: " + passthrough_value);
// If the preceding token is also a GL_PASS_THROUGH_TOKEN
// we consider it as an empty token
if(!Float.isNaN(prevpassthrough_value)){
prevtoken_id = (int)prevpassthrough_value;
if( token_type == prevtoken_type )
isempty[prevtoken_id] = true;
else
isempty[prevtoken_id] = false;
}
// Store current token value as previous
prevpassthrough_value = passthrough_value;
}
// Other cases: just consume buffer
else if (token_type == GL2.GL_POINT_TOKEN) {
if(printout){
logger.info(" GL.GL_POINT_TOKEN");
count = print3DcolorVertex(size, count, buffer);
}else{
count = count - 7;
}
}
else if (token_type == GL2.GL_LINE_TOKEN) {
if(printout){
logger.info(" GL.GL_LINE_TOKEN ");
count = print3DcolorVertex(size, count, buffer);
count = print3DcolorVertex(size, count, buffer);
}else{
count = count - 14;
}
}
else if (token_type == GL2.GL_LINE_RESET_TOKEN) {
if(printout){
logger.info(" GL.GL_LINE_RESET_TOKEN ");
count = print3DcolorVertex(size, count, buffer);
count = print3DcolorVertex(size, count, buffer);
}else{
count = count - 14;
}
}
else if (token_type == GL2.GL_POLYGON_TOKEN) {
int n = (int)buffer[size - count];
count--;
if(printout)
logger.info(" GL.GL_POLYGON_TOKEN: " + n + " vertices");
for(int i=0; i
Ads help maintain this website.