package com.yarin.android.Examples_13_09;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView.Renderer;
public class GLRender implements Renderer
{
public final static int MIN_DIVS = 1;
public final static int MAX_DIVS =64;
/* Rotation about the Z axis */
float rotz=0.0f;
/* The bezier patch we're going to use (NEW) */
BEZIER_PATCH mybezier = new BEZIER_PATCH();
/* Toggles displaying the control point grid (NEW) */
boolean showCPoints=true;
/* Number of intrapolations (conrols poly resolution) (NEW) */
int divs=7;
/****************************************************************************/
/* Adds 2 points. Don't just use '+' ;) */
POINT_3D pointAdd(POINT_3D p, POINT_3D q)
{
p.x+=q.x;
p.y+=q.y;
p.z+=q.z;
return p;
}
/* Multiplies a point and a constant. Don't just use '*' */
POINT_3D pointTimes(float c, POINT_3D p)
{
p.x*=c;
p.y*=c;
p.z*=c;
return p;
}
/* Function for quick point creation */
POINT_3D makePoint(float a, float b, float c)
{
POINT_3D p = new POINT_3D();
p.x=a;
p.y=b;
p.z=c;
return p;
}
/* Calculates 3rd degree polynomial based on array of 4 points */
/* and a single variable (u) which is generally between 0 and 1 */
POINT_3D Bernstein(float u, POINT_3D[] p)
{
POINT_3D a, b, c, d, r;
a=pointTimes((float)Math.pow(u,3.0f), p[0]);
b=pointTimes((float)(3*Math.pow(u,2.0f)*(1.0f-u)), p[1]);
c=pointTimes((float)(3*u*Math.pow((1.0f-u),2.0f)), p[2]);
d=pointTimes((float)Math.pow((1.0f-u),3.0f), p[3]);
r=pointAdd(pointAdd(a, b), pointAdd(c, d));
return r;
}
/* Generates a arrays based on the data in the patch */
/* and the number of divisions */
void genBezier(BEZIER_PATCH patch, int divs)
{
int u=0;
int v;
float py, px, pyold;
/* make the arrays */
POINT_3D temp[]=new POINT_3D[4];
/* array of points to mark the first line of polys */
POINT_3D[] last= new POINT_3D[divs+1];//(POINT_3D*)malloc(sizeof(POINT_3D)*(divs+1));
/* the first derived curve (along x axis) */
temp[0]=patch.anchors[0][3];
temp[1]=patch.anchors[1][3];
temp[2]=patch.anchors[2][3];
temp[3]=patch.anchors[3][3];
/* create the first line of points */
for (v=0; v<=divs; v++)
{
/* percent along y axis */
px=((float)v)/((float)divs);
/* use the 4 points from the derives curve to calculate the points along that curve */
last[v]=Bernstein(px, temp);
}
//������������������������
// patch.texcoords.clear();
// patch.vertices.clear();
for (u=1; u<=divs; u++)
{
/* Percent along Y axis */
py=((float)u)/((float)divs);
/* Percent along old Y axis */
pyold=((float)u-1.0f)/((float)divs);
/* Calculate new bezier points */
temp[0]=Bernstein(py, patch.anchors[0]);
temp[1]=Bernstein(py, patch.anchors[1]);
temp[2]=Bernstein(py, patch.anchors[2]);
temp[3]=Bernstein(py, patch.anchors[3]);
/* Begin a new triangle strip */
for (v=0; v<=divs; v++)
{
/* Percent along the X axis */
px=((float)v)/((float)divs);
// /* Apply the old texture coords */
// patch.texcoords.put((u-1)*2*(divs+1)+v*2,pyold);
// patch.texcoords.put((u-1)*2*(divs+1)+v*2+1,1.0f-px);
// /* Old Point */
// patch.vertices.put((u-1)*2*(divs+1)+v*2,last[v].x);
// patch.vertices.put((u-1)*2*(divs+1)+v*2+1,last[v].y);
// patch.vertices.put((u-1)*2*(divs+1)+v*2+2,last[v].z);
//
// /* Generate new point */
// last[v]=Bernstein(px, temp);
// /* Apply the new texture coords */
// patch.texcoords.put((u-1)*2*(divs+1)+v*2+1,py);
// patch.texcoords.put((u-1)*2*(divs+1)+v*2+1+1,1.0f-px);
// /* New Point */
// patch.vertices.put((u-1)*2*(divs+1)+v*2+1,last[v].x);
// patch.vertices.put((u-1)*2*(divs+1)+v*2+1+1,last[v].y);
// patch.vertices.put((u-1)*2*(divs+1)+v*2+1+2,last[v].z);
/* Apply the old texture coords */
patch.texcoords[((u-1)*2*(divs+1)+v*2)*2]=pyold;
patch.texcoords[((u-1)*2*(divs+1)+v*2)*2+1]=1.0f-px;
/* Old Point */
patch.vertices[((u-1)*2*(divs+1)+v*2)*3]=last[v].x;
patch.vertices[((u-1)*2*(divs+1)+v*2)*3+1]=last[v].y;
patch.vertices[((u-1)*2*(divs+1)+v*2)*3+2]=last[v].z;
/* Generate new point */
last[v]=Bernstein(px, temp);
/* Apply the new texture coords */
patch.texcoords[((u-1)*2*(divs+1)+v*2+1)*2]=py;
patch.texcoords[((u-1)*2*(divs+1)+v*2+1)*2+1]=1.0f-px;
/* New Point */
patch.vertices[((u-1)*2*(divs+1)+v*2+1)*3]=last[v].x;
patch.vertices[((u-1)*2*(divs+1)+v*2+1)*3+1]=last[v].y;
patch.vertices[((u-1)*2*(divs+1)+v*2+1)*3+2]=last[v].z;
}
}
/* Free the old vertices array */
//free(last);
/* Return the array */
return;
}
/****************************************************************************/
void initBezier()
{
/* set the bezier vertices */
mybezier.anchors[0][0]=makePoint(-0.75f, -0.75f, -0.5f);
mybezier.anchors[0][1]=makePoint(-0.25f, -0.75f, 0.0f);
mybezier.anchors[0][2]=makePoint( 0.25f, -0.75f, 0.0f);
mybezier.anchors[0][3]=makePoint( 0.75f, -0.75f, -0.5f);
mybezier.anchors[1][0]=makePoint(-0.75f, -0.25f, -0.75f);
mybezier.anchors[1][1]=makePoint(-0.25f, -0.25f, 0.5f);
mybezier.anchors[1][2]=makePoint( 0.25f, -0.25f, 0.5f);
mybezier.anchors[1][3]=makePoint( 0.75f, -0.25f, -0.75f);
mybezier.anchors[2][0]=makePoint(-0.75f, 0.25f, 0.0f);
mybezier.anchors[2][1]=makePoint(-0.25f, 0.25f, -0.5f);
mybezier.anchors[2][2]=makePoint( 0.25f, 0.25f, -0.5f);
mybezier.anchors[2][3]=makePoint( 0.75f, 0.25f, 0.0f);
mybezier.anchors[3][0]=makePoint(-0.75f, 0.75f, -0.5f);
mybezier.anchors[3][1]=makePoint(-0.25f, 0.75f, -1.0f);
mybezier.anchors[3][2]=makePoint( 0.25f, 0.75f, -1.0f);
mybezier.anchors[3][3]=makePoint( 0.75f, 0.75f, -0.5f);
}
public int LoadGLTexture(GL10 gl)
{
int texture = -1;
IntBuffer textureBuffer = IntBuffer.allocate(1);
// ��������
gl.glGenTextures(1, textureBuffer);
texture = textureBuffer.get();
/* Typical Texture Generation Using Data From The Bitmap */
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
/* Generate The Texture */
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0);
/* Linear Filtering */
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
return texture;
}
@Override
public void onDrawFrame(GL10 gl)
{
int i, j;
FloatBuffer baseverts = FloatBuffer.wrap(new float[12]);
/* Clear Screen And Depth Buffer */
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
/* Reset The Current Modelview Matrix */
gl.glLoadIdentity();
/* Move Left 1.5 Units And Into The Screen 6.0 */
gl.glTranslatef(0.0f, 0.0f, -6.0f);
gl.glRotatef(-75.0f, 1.0f, 0.0f, 0.0f);
/* Rotate The Triangle On The Z axis ( NEW ) */
gl.glRotatef(rotz, 0.0f, 0.0f, 1.0f);
/* Bind the texture */
gl.glBindTexture(GL10.GL_TEXTURE_2D, mybezier.texture);
/* Draw the Bezier's array */
/* this need only be updated when the patch changes */
/* Set pointers to vertices and texcoords */
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, FloatBuffer.wrap(mybezier.vertices) );
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0,FloatBuffer.wrap(mybezier.texcoords));
/* Enable vertices and texcoords arrays */
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
/* Draw bezier patch */
for (i=0; i<divs; i++)
{
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, i*(divs+1)*2, (divs+1)*2);
}
/* Disable vertices and texcoords arrays */
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
/* Set pointers to vertices and texcoords */
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, baseverts);
/* Enable vertices array */
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
/* If drawing the grid is toggled on */
if (showCPoints)
{
gl.glDisable(GL10.GL_TEXTURE_2D);
/* Set color to Red for control points */
gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
/* draw the horizontal lines */
for(i=0; i<4; i++)
{
baseverts.clear();
for(j=0; j<4; j++)
{
baseverts.put(mybezier.anchors[i][j].x);
baseverts.put(mybezier.anchors[i][j].y);
baseverts.put(mybezier.anchors[i][j].z);
}
gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, 4);
}
/* draw the vertical lines */
for(i=0; i<4; i++)
{
baseverts.clear();
for(j=0; j<4; j++)
{
baseverts.put(mybezier.anchors[j][i].x);
baseverts.put(mybezier.anchors[j][i].y);
baseverts.put(mybezier.anchors[j][i].z);
}
gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, 4);
}
/* Restore default color to avoid texture color modulation */
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
gl.glEnable(GL10.GL_TEXTURE_2D);
}
/* Disable vertices array */
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glFinish();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
float ratio;
/* Prevent A Divide By Zero By */
if (height==0)
{
/* Making Height Equal One */
height=1;
}
ratio=(float)width/(float)height;
/* Reset The Current Viewport */
gl.glViewport(0, 0, width, height);
/* Select The Projection Matrix */
gl.glMatrixMode(GL10.GL_PROJECTION);
/* Reset The Projection Matrix */
gl.glLoadIdentity();
/* Calculate The Aspect Ratio Of The Window */
gl.glFrustumf(-ratio, ratio, -1, 1,4.0f, 200.0f);
//gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);
/* Select The Modelview Matrix */
gl.glMatrixMode(GL10.GL_MODELVIEW);
/* Reset The Modelview Matrix */
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
/* Enable Texture Mapping */
gl.glEnable(GL10.GL_TEXTURE_2D);
/* Enable Smooth Shading */
gl.glShadeModel(GL10.GL_SMOOTH);
/* Black Background */
gl.glClearColor(0.25f, 0.25f, 0.25f, 0.5f);
/* Depth Buffer Setup */
gl.glClearDepthf(1.0f);
/* Enables Depth Testing */
gl.glEnable(GL10.GL_DEPTH_TEST);
/* The Type Of Depth Testing To Do */
gl.glDepthFunc(GL10.GL_LEQUAL);
/* Really Nice Perspective Calculations */
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
/* Initialize the Bezier's control grid */
initBezier();
/* Load the texture */
mybezier.texture=LoadGLTexture(gl);
/* Generate the patch */
genBezier(mybezier, divs);
}
}
/* Structure for a 3-dimensional point (NEW) */
class POINT_3D
{
float x, y, z;
}
/* Structure for a 3rd degree bezier patch (NEW) */
class BEZIER_PATCH
{
POINT_3D anchors[][]=new POINT_3D[4][4]; /* 4x4 grid of anchor points */
// FloatBuffer vertices = FloatBuffer.wrap(new float[(GLRender.MAX_DIVS)*(GLRender.MAX_DIVS+1)*2*3]);
// FloatBuffer texcoords = FloatBuffer.wrap(new float[(GLRender.MAX_DIVS)*(GLRender.MAX_DIVS+1)*2*2]);
// public void f1()
// {
// }
float vertices[] = new float[(GLRender.MAX_DIVS)*(GLRender.MAX_DIVS+1)*2*3];
float texcoords[]=new float[(GLRender.MAX_DIVS)*(GLRender.MAX_DIVS+1)*2*2];
int texture; /* Texture for the patch */
}