/* *EERT = EERT enhanced rendering technology * *Copyright (C) [2008] [Robert "BuRnEr" Schadek] *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 3 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, see <http://www.gnu.org/licenses/>. */ package Engine; import Types.Geometrie.Obj; import Types.Geometrie.ObjIns; import Types.Geometrie.Vector; import Types.Illumination.PointLight; import Util.Geometrie.VectorUtil; import Util.Logic.Camera; import javax.media.opengl.GL; public class EOcMaster { public int numNodes; public float[][] frustum = new float[6][4]; private ObjIns[] objs; private Obj[] realObjs; public boolean[] drawn; public boolean[] lightDrawn; private EOcNode root; private Vector middle; private float radius; private float bSize = 0; private float bHalf; private GL gl; public int facRender; public Camera cam; public Engine engine; public int treeDepth; public float frustLight; private int shadowList; public EOcMaster(Engine engine, ObjIns[] allObj, Obj[] realObj, GL gl, Camera cam) { this.treeDepth = 4; this.engine = engine; this.cam = cam; this.drawn = new boolean[allObj.length]; this.lightDrawn = new boolean[allObj.length]; this.realObjs = realObj; this.gl = gl; this.objs = allObj; this.numNodes = 0; makeFirstCubeInfo(); this.bHalf = this.bSize / 2; this.root = new EOcNode(this, this.objs, this.middle, this.radius, this.bSize, this.drawn, 0); } private void makeFirstCubeInfo() { this.middle = new Vector(); this.radius = 0f; //make the middle of all objIns for (ObjIns obj : this.objs) { //middle this.middle.x += obj.origin.x / this.objs.length; this.middle.y += obj.origin.y / this.objs.length; this.middle.z += obj.origin.z / this.objs.length; } //make a bounding sphere around all ObjIns for (ObjIns obj : this.objs) { float dis = (float) Math.sqrt(Math.pow(obj.origin.x - this.middle.x, 2) + Math.pow(obj.origin.y - this.middle.y, 2) + Math.pow(obj.origin.z - this.middle.z, 2)); dis += Math.abs(obj.boundSph); if (dis > this.radius) { this.radius = dis; } dis = obj.origin.x - this.middle.x; if (this.bSize < Math.abs(dis)) { this.bSize = Math.abs(dis); } dis = obj.origin.y - this.middle.y; if (this.bSize < Math.abs(dis)) { this.bSize = Math.abs(dis); } dis = obj.origin.z - this.middle.z; if (this.bSize < Math.abs(dis)) { this.bSize = Math.abs(dis); } } } public void drawOctree(GL gl) { gl.glEnable(GL.GL_TEXTURE); //Reset Counter for (Obj rObj : this.realObjs) { rObj.facesRendered = 0; } this.drawn = new boolean[this.objs.length]; float mat_specular[] = {1.0f, 1.0f, 1.0f, 1.0f}; float mat_shininess[] = {50.0f}; gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, mat_specular, 0); gl.glMaterialfv(GL.GL_FRONT, GL.GL_SHININESS, mat_shininess, 0); //actually draw if(this.engine.frame.octree)drawBox(gl); extractFrustum(); this.facRender = 0; this.root.draw(gl); //make Info for (Obj rObj : this.realObjs) { this.facRender += rObj.facesRendered; } gl.glDisable(GL.GL_TEXTURE); } /* public void drawLightVolume(GL gl) { this.lightDrawn = new boolean[this.objs.length]; //make the list of shadow volumes //this one gone take a lot of juice //goes all the way done the octree gl.glNewList(this.shadowList, GL.GL_COMPILE); this.root.drawLight(gl); gl.glEndList(); //setup Opengl gl.glColorMask(false, false, false, false); gl.glDepthMask(false); gl.glEnable(GL.GL_STENCIL_TEST); gl.glStencilFunc(GL.GL_ALWAYS, 0, 0xFFFFFFF); //activate stencil gl.glStencilOp(GL.GL_KEEP, GL.GL_INCR_WRAP, GL.GL_KEEP); gl.glEnable(GL.GL_CULL_FACE); gl.glFrontFace(GL.GL_CW); //draw frontface gl.glCallList(this.shadowList); //draw backfaces gl.glStencilOp(GL.GL_KEEP, GL.GL_DECR_WRAP, GL.GL_KEEP); gl.glFrontFace(GL.GL_CCW); gl.glCallList(this.shadowList); //skybox gl.glStencilFunc(GL.GL_NOTEQUAL, 0, 0xFFFFFFFF); gl.glStencilOp(GL.GL_KEEP, GL.GL_DECR, GL.GL_KEEP); gl.glDepthFunc(GL.GL_NEVER); gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthMask(true); //draw skybox over the actual shadow this.engine.skybox.draw(); gl.glColorMask(true, true, true, true); gl.glStencilFunc(GL.GL_NOTEQUAL, 0, 0xFFFFFFFF); gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); gl.glDepthFunc(GL.GL_ALWAYS); gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthMask(true); gl.glColor4f(0.0f, 0.0f, 0.0f, 0.8f); gl.glEnable(GL.GL_CULL_FACE); gl.glFrontFace(GL.GL_CCW); gl.glDisable(GL.GL_LIGHTING); gl.glEnable(GL.GL_BLEND); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); gl.glPushMatrix(); gl.glLoadIdentity(); gl.glBegin(GL.GL_TRIANGLE_STRIP); gl.glVertex3f(-0.1f, 0.1f, -0.1f); gl.glVertex3f(-0.1f, -0.1f, -0.1f); gl.glVertex3f(0.1f, 0.1f, -0.1f); gl.glVertex3f(0.1f, -0.1f, -0.1f); gl.glEnd(); gl.glPopMatrix(); gl.glDisable(GL.GL_BLEND); gl.glDepthFunc(GL.GL_LESS); gl.glDisable(GL.GL_STENCIL_TEST); this.engine.skybox.draw(); gl.glFlush(); }*/ public void drawBox(GL gl) { gl.glPushMatrix(); gl.glTranslatef(this.middle.x, this.middle.y, this.middle.z); gl.glColor3f(0.4f, 0.2f, 0.7f); //Back gl.glBegin(GL.GL_LINE_LOOP); gl.glVertex3f(-this.bHalf, -this.bHalf, -this.bHalf); gl.glVertex3f(this.bHalf, -this.bHalf, -this.bHalf); gl.glVertex3f(this.bHalf, this.bHalf, -this.bHalf); gl.glVertex3f(-this.bHalf, this.bHalf, -this.bHalf); gl.glEnd(); //Front gl.glBegin(GL.GL_LINE_LOOP); gl.glVertex3f(-this.bHalf, -this.bHalf, this.bHalf); gl.glVertex3f(this.bHalf, -this.bHalf, this.bHalf); gl.glVertex3f(this.bHalf, this.bHalf, this.bHalf); gl.glVertex3f(-this.bHalf, this.bHalf, this.bHalf); gl.glEnd(); //Left gl.glBegin(GL.GL_LINE_LOOP); gl.glVertex3f(-this.bHalf, -this.bHalf, -this.bHalf); gl.glVertex3f(-this.bHalf, -this.bHalf, this.bHalf); gl.glVertex3f(-this.bHalf, this.bHalf, this.bHalf); gl.glVertex3f(-this.bHalf, this.bHalf, -this.bHalf); gl.glEnd(); //Right gl.glBegin(GL.GL_LINE_LOOP); gl.glVertex3f(this.bHalf, -this.bHalf, -this.bHalf); gl.glVertex3f(this.bHalf, -this.bHalf, this.bHalf); gl.glVertex3f(this.bHalf, this.bHalf, this.bHalf); gl.glVertex3f(this.bHalf, this.bHalf, -this.bHalf); gl.glEnd(); gl.glPopMatrix(); gl.glColor3f(1f,1f,1f); } private void extractFrustum() { float[] proj = new float[16]; float[] modl = new float[16]; float[] clip = new float[16]; float t; /* Get the current PROJECTION matrix from OpenGL */ gl.glGetFloatv(GL.GL_PROJECTION_MATRIX, proj, 0); /* Get the current MODELVIEW matrix from OpenGL */ gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, modl, 0); /* Combine the two matrices (multiply projection by modelview) */ clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12]; clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13]; clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14]; clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15]; clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12]; clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13]; clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14]; clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15]; clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12]; clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13]; clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14]; clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15]; clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12]; clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13]; clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14]; clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15]; /* Extract the numbers for the RIGHT plane */ this.frustum[0][0] = clip[ 3] - clip[ 0]; this.frustum[0][1] = clip[ 7] - clip[ 4]; this.frustum[0][2] = clip[11] - clip[ 8]; this.frustum[0][3] = clip[15] - clip[12]; /* Normalize the result */ t = (float) Math.sqrt(this.frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2]); this.frustum[0][0] /= t; this.frustum[0][1] /= t; this.frustum[0][2] /= t; this.frustum[0][3] /= t; /* Extract the numbers for the LEFT plane */ this.frustum[1][0] = clip[ 3] + clip[ 0]; this.frustum[1][1] = clip[ 7] + clip[ 4]; this.frustum[1][2] = clip[11] + clip[ 8]; this.frustum[1][3] = clip[15] + clip[12]; /* Normalize the result */ t = (float) Math.sqrt(this.frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2]); this.frustum[1][0] /= t; this.frustum[1][1] /= t; this.frustum[1][2] /= t; this.frustum[1][3] /= t; /* Extract the BOTTOM plane */ this.frustum[2][0] = clip[ 3] + clip[ 1]; this.frustum[2][1] = clip[ 7] + clip[ 5]; this.frustum[2][2] = clip[11] + clip[ 9]; this.frustum[2][3] = clip[15] + clip[13]; /* Normalize the result */ t = (float) Math.sqrt(this.frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2]); this.frustum[2][0] /= t; this.frustum[2][1] /= t; this.frustum[2][2] /= t; this.frustum[2][3] /= t; /* Extract the TOP plane */ this.frustum[3][0] = clip[ 3] - clip[ 1]; this.frustum[3][1] = clip[ 7] - clip[ 5]; this.frustum[3][2] = clip[11] - clip[ 9]; this.frustum[3][3] = clip[15] - clip[13]; /* Normalize the result */ t = (float) Math.sqrt(this.frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2]); this.frustum[3][0] /= t; this.frustum[3][1] /= t; this.frustum[3][2] /= t; this.frustum[3][3] /= t; /* Extract the FAR plane */ this.frustum[4][0] = clip[ 3] - clip[ 2]; this.frustum[4][1] = clip[ 7] - clip[ 6]; this.frustum[4][2] = clip[11] - clip[10]; this.frustum[4][3] = clip[15] - clip[14]; /* Normalize the result */ t = (float) Math.sqrt(this.frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2]); this.frustum[4][0] /= t; this.frustum[4][1] /= t; this.frustum[4][2] /= t; this.frustum[4][3] /= t; /* Extract the NEAR plane */ this.frustum[5][0] = clip[ 3] + clip[ 2]; this.frustum[5][1] = clip[ 7] + clip[ 6]; this.frustum[5][2] = clip[11] + clip[10]; this.frustum[5][3] = clip[15] + clip[14]; /* Normalize the result */ t = (float) Math.sqrt(this.frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2]); this.frustum[5][0] /= t; this.frustum[5][1] /= t; this.frustum[5][2] /= t; this.frustum[5][3] /= t; /* //Boudingsphere around the frustum and all lights // this.engine.cam.updateFrustMiddle(); //Check if a light is outside of the boundingsphere //and if so extend the radius of the sphere if (this.engine.lights == null) { return; } for (PointLight light : this.engine.lights.lights) { this.frustLight = this.cam.frustRadius; float dis = VectorUtil.distance(this.cam.frustMiddle, light.origin); if (dis > this.frustLight) { this.frustLight = dis; } }*/ } }