#include #include #include "glext.h" #include "scene.h" #include "CG/cgInit.h" #include "reflector.h" using namespace std; /*-------------------------------------------------------------------------- * Constructor: create materials and render targets, etc. *--------------------------------------------------------------------------*/ Reflector::Reflector() { reflectorMesh = NULL; //TODO: automate this in loading script GCRMaterial = new Material("GCR", false); SPOCRMaterial = new Material("SPOCR", false); SPOCRefractMaterial = new Material("SPOCRefract", false); PPCRMaterial = new Material("imposterReflections", false); PPCRefractMaterial = new Material("imposterRefractions", false); BBRMaterial = new Material("environmentMappedReflections", false); PhongMaterial = new Material("phongShading", false); RefractionConstrMaterial = new Material("RefractionConstruction", false); lightInterfaceType = ReflectorType; normalsRT = NULL; refractedRaysRT = NULL; clearColor = Vex3(100 / 255.0f, 149 / 255.0f, 237 / 255.0f); reflectorMeshIsMorpher = false; renderSPOCRays = false; RaysN = 0; VertsN = 0; impostorIndex = 0; } /*-------------------------------------------------------------------------- * Release memory *--------------------------------------------------------------------------*/ Reflector::~Reflector() { if(reflectorMesh) delete reflectorMesh; reflectiveImposters.clear(); diffuseImposters.clear(); if(normalsRT) delete normalsRT; if(refractedRaysRT) delete refractedRaysRT; //materials unloaded by material manager } /*-------------------------------------------------------------------------- * Set the reference mesh that will be a reflector *--------------------------------------------------------------------------*/ void Reflector::SetReferenceMesh(TriangleMesh *mesh) { reflectorMesh = mesh; refractionParams.objectScale = reflectorMesh->scaleFactor; if(!strcmp(typeid(*reflectorMesh).name(), "class MorphedMesh")) reflectorMeshIsMorpher = true; } /*-------------------------------------------------------------------------- * Add a diffuse or reflective impostor to this reflectors list of impostors *--------------------------------------------------------------------------*/ void Reflector::AddImposter(ImposterType imposterType, TriangleMesh *mesh) { Imposter *imposter = new Imposter(); imposter->SetReferenceMesh(mesh); imposter->imposterType = imposterType; if(mesh->isReflector) { reflectiveImposters.push_back(imposter); } else { diffuseImposters.push_back(imposter); } } /*-------------------------------------------------------------------------- * Update the diffuse/reflective impostors for this reflector *--------------------------------------------------------------------------*/ void Reflector::UpdateImposters(RenderMode renderMode) { for(unsigned int i = 0; i < diffuseImposters.size(); i++) { if(diffuseImposters[i]->hasMoved) { diffuseImposters[i]->UpdateImposter(reflectorMesh->GetCenter(), renderMode); if(diffuseImposters[i]->refMeshIsMorpher) diffuseImposters[i]->hasMoved = true; else diffuseImposters[i]->hasMoved = false; } } Material *oldMaterial; PhongMaterial->active = true; for(unsigned int i = 0; i < reflectiveImposters.size(); i++) { if(reflectiveImposters[i]->hasMoved) { //disable reflective material oldMaterial = reflectiveImposters[i]->referenceMesh->material; reflectiveImposters[i]->referenceMesh->material = PhongMaterial; reflectiveImposters[i]->UpdateImposter(reflectorMesh->GetCenter(), renderMode); reflectiveImposters[i]->hasMoved = false; reflectiveImposters[i]->referenceMesh->material = oldMaterial; } } } /*-------------------------------------------------------------------------- * Link this reflector with the reflective impostor at specified index *--------------------------------------------------------------------------*/ void Reflector::LinkReflectiveImposterWithReflector(int index, Reflector* reflector) { reflectiveImposters[index]->reflectorMeshLink = reflector; } /*-------------------------------------------------------------------------- * Create the render targets for this reflector *--------------------------------------------------------------------------*/ void Reflector::CreateRenderTargets() { normalsRT = new RenderTarget(); normalsRT->currentConfig = RenderTarget::verifiedFBOconfig; normalsRT->currentFBO = RenderTarget::verifiedFBOdata; normalsRT->currentConfig.colorBits = NormalsRTBitsN; normalsRT->currentConfig.colorFormat = NormalsRTFormat; normalsRT->currentConfig.width = RenderTargetResolution; normalsRT->currentConfig.height = RenderTargetResolution; //no multisampling normalsRT->currentConfig.coverageSamples = 0; normalsRT->currentConfig.depthSamples = 0; refractedRaysRT = new RenderTarget(); refractedRaysRT->currentConfig = RenderTarget::verifiedFBOconfig; refractedRaysRT->currentFBO = RenderTarget::verifiedFBOdata; refractedRaysRT->currentConfig.colorBits = RefractedRayRTBitsN; refractedRaysRT->currentConfig.colorFormat = RefractedRayRTFormat; refractedRaysRT->currentConfig.width = RenderTargetResolution; refractedRaysRT->currentConfig.height = RenderTargetResolution; //no multisampling refractedRaysRT->currentConfig.coverageSamples = 0; refractedRaysRT->currentConfig.depthSamples = 0; //check to see if the configurations are valid if(!RenderTarget::CreateFBO(normalsRT->currentConfig, normalsRT->currentFBO)) { cerr << "ERROR: error creating render target!" << endl; } if(!RenderTarget::CreateFBO(refractedRaysRT->currentConfig, refractedRaysRT->currentFBO)) { cerr << "ERROR: error creating render target!" << endl; } //create the render targets for the impostors for(unsigned int i = 0; i < diffuseImposters.size(); i++) { diffuseImposters[i]->CreateRenderTarget(); } for(unsigned int i = 0; i < reflectiveImposters.size(); i++) { reflectiveImposters[i]->CreateRenderTarget(); } } /*-------------------------------------------------------------------------- * Draw all the impostors. For testing only. * Draws their billboarded quad or their visible mesh geometry(if PPC/SPOC) *--------------------------------------------------------------------------*/ void Reflector::RenderImposters(RenderMode renderMode) { for(unsigned int i = 0; i < diffuseImposters.size(); i++) { if(diffuseImposters[i]->imposterMesh) diffuseImposters[i]->imposterMesh->RenderHW(renderMode); else diffuseImposters[i]->RenderHW(renderMode); break; } for(unsigned int i = 0; i < reflectiveImposters.size(); i++) { reflectiveImposters[i]->RenderHW(renderMode); } } /*-------------------------------------------------------------------------- * Update the refraciton maps of this reflector. *--------------------------------------------------------------------------*/ void Reflector::UpdateRefractionMaps(RenderMode renderMode) { //set the current reflector to be used when setting parameters in cgInit scene->currReflector = this; Material *oldMaterial = reflectorMesh->material; //1st pass: render the depth and normals of the back faces reflectorMesh->material = PhongMaterial; reflectorMesh->material->active = true; glCullFace( GL_FRONT ); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, normalsRT->currentConfig.width, normalsRT->currentConfig.height); normalsRT->BeginRender(clearColor, 0); reflectorMesh->RenderHW(renderMode); normalsRT->EndRender(); glPopAttrib(); glCullFace( GL_BACK ); //2nd pass: compute the final refracted ray reflectorMesh->material = RefractionConstrMaterial; reflectorMesh->material->active = true; //set the vertex distances used for thickness glClientActiveTexture(GL_TEXTURE0); glTexCoordPointer(1, GL_FLOAT, 0, reflectorMesh->vertexDistances); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, refractedRaysRT->currentConfig.width, refractedRaysRT->currentConfig.height); refractedRaysRT->BeginRender(clearColor, 0); reflectorMesh->RenderHW(renderMode); refractedRaysRT->EndRender(); glClientActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glPopAttrib(); reflectorMesh->material = oldMaterial; scene->currReflector = 0; } /*-------------------------------------------------------------------------- * Draw the geometry assigned to this reflector *--------------------------------------------------------------------------*/ void Reflector::RenderHW(RenderMode renderMode) { //set the current reflector to be used when setting parameters in cgInit scene->currReflector = this; Material *oldMaterial = reflectorMesh->material; if(lightInterfaceType == ReflectorType) { //get the current type of impostor from the GUI int imposterType = scene->GetImposterTypeFromGUI(0); switch(imposterType) { case imposterTypeBB: reflectorMesh->material = BBRMaterial; break; case imposterTypePPC: reflectorMesh->material = PPCRMaterial; break; case imposterTypeSPOC: reflectorMesh->material = SPOCRMaterial; break; case imposterTypeSPOC2: reflectorMesh->material = SPOCRMaterial; break; case imposterTypeGC: reflectorMesh->material = GCRMaterial; break; default: cout << "Error: No applicable material can be applied!" << endl; break; } } else { //1st and 2nd passes performed during update //3rd pass: finally render the refractor with the PHC or SPOC impostors int imposterType = scene->GetImposterTypeFromGUI(0); switch(imposterType) { case imposterTypeBB: reflectorMesh->material = BBRMaterial; break; case imposterTypePPC: reflectorMesh->material = PPCRefractMaterial; break; case imposterTypeSPOC: reflectorMesh->material = SPOCRefractMaterial; break; case imposterTypeSPOC2: reflectorMesh->material = SPOCRefractMaterial; break; default: cout << "Error: No applicable material can be applied!" << endl; break; } } reflectorMesh->material->active = true; reflectorMesh->RenderHW(renderMode); reflectorMesh->material = oldMaterial; scene->currReflector = 0; } /*-------------------------------------------------------------------------- * Binds the vertices of type VertexType to the cgParam *--------------------------------------------------------------------------*/ void Reflector::CGBindImposterVerts(CGparameter *cgParam, VertexType type, int index, bool diffuse) { switch(type) { case Quad: { static float verts[4 * 3]; int k = 0; if(diffuse) { for(int i = 0; i < 4; i++) { verts[k++] = diffuseImposters[index]->imposterVerts[i].x; verts[k++] = diffuseImposters[index]->imposterVerts[i].y; verts[k++] = diffuseImposters[index]->imposterVerts[i].z; } } else { for(int i = 0; i < 4; i++) { verts[k++] = reflectiveImposters[index]->imposterVerts[i].x; verts[k++] = reflectiveImposters[index]->imposterVerts[i].y; verts[k++] = reflectiveImposters[index]->imposterVerts[i].z; } } cgGLSetParameterArray3f(*cgParam, 0, 0, verts); break; } case BoundingVolume: { static float verts[8 * 3]; int k = 0; if(diffuse) { for(int i = 0; i < 8; i++) { verts[k++] = diffuseImposters[index]->boundingVolume[i].x; verts[k++] = diffuseImposters[index]->boundingVolume[i].y; verts[k++] = diffuseImposters[index]->boundingVolume[i].z; } } else { for(int i = 0; i < 8; i++) { verts[k++] = reflectiveImposters[index]->boundingVolume[i].x; verts[k++] = reflectiveImposters[index]->boundingVolume[i].y; verts[k++] = reflectiveImposters[index]->boundingVolume[i].z; } } cgGLSetParameterArray3f(*cgParam, 0, 0, verts); break; } } } /*-------------------------------------------------------------------------- * Binds a float of type FloatType to the cgParam *--------------------------------------------------------------------------*/ void Reflector::CGBindImposterFloat(CGparameter *cgParam, FloatType type, int index, bool diffuse) { float value = 0; switch(type) { case CamProp_f: { if(diffuse) value = diffuseImposters[index]->view->phc->Getf(); else value = reflectiveImposters[index]->view->phc->Getf(); break; } case NearZ: { if(diffuse) value = diffuseImposters[index]->nearZ; else value = reflectiveImposters[index]->nearZ; break; } case FarZ: { if(diffuse) value = diffuseImposters[index]->farZ; else value = reflectiveImposters[index]->farZ; break; } case IsReflective: { if(!diffuse) { value = 1.0f; } break; } default: break; } cgGLSetParameter1f(*cgParam, value); } /*-------------------------------------------------------------------------- * Binds a vector of type VectorType to the cgParam *--------------------------------------------------------------------------*/ void Reflector::CGBindImposterVector(CGparameter *cgParam, VectorType type, int index, bool diffuse) { Vex3 vector; switch(type) { case Normal: { if(diffuse) vector = diffuseImposters[index]->GetNormal(); else vector = reflectiveImposters[index]->GetNormal(); break; } case Tangent: { if(diffuse) vector = diffuseImposters[index]->GetTangent(); else vector = reflectiveImposters[index]->GetTangent(); break; } case CamProp_C: { if(diffuse) vector = diffuseImposters[index]->view->phc->GetC(); else vector = reflectiveImposters[index]->view->phc->GetC(); break; } case CamProp_a: { if(diffuse) vector = diffuseImposters[index]->view->phc->_a; else vector = reflectiveImposters[index]->view->phc->_a; break; } case CamProp_b: { if(diffuse) vector = diffuseImposters[index]->view->phc->_b; else vector = reflectiveImposters[index]->view->phc->_b; break; } case CamProp_c: { if(diffuse) vector = diffuseImposters[index]->view->phc->_c; else vector = reflectiveImposters[index]->view->phc->_c; break; } default: break; } cgGLSetParameter3f(*cgParam, vector.x, vector.y, vector.z); } /*-------------------------------------------------------------------------- * Binds the near and far points to the cg parameters *--------------------------------------------------------------------------*/ void Reflector::CGBindImposterNearFarP(CGparameter *cgParam1, CGparameter *cgParam2, int index, bool diffuse) { Vex3 nearp, farp; if(diffuse) { nearp = diffuseImposters[index]->nearPoint; farp = diffuseImposters[index]->farPoint; } else { nearp = reflectiveImposters[index]->nearPoint; farp = reflectiveImposters[index]->farPoint; } cgGLSetParameter3f(*cgParam1, nearp.x, nearp.y, nearp.z); cgGLSetParameter3f(*cgParam2, farp.x, farp.y, farp.z); } /*-------------------------------------------------------------------------- * Binds the texture of the render target to the cgParam *--------------------------------------------------------------------------*/ void Reflector::CGBindImposterTex(CGparameter *cgParam, RenderTargetType type, int index, bool diffuse) { switch(type) { case Tex: { if(diffuse) cgGLSetTextureParameter(*cgParam, diffuseImposters[index]->renderTarget->GetTextureID()); else cgGLSetTextureParameter(*cgParam, reflectiveImposters[index]->renderTarget->GetTextureID()); break; } case DepthTex: { if(diffuse) cgGLSetTextureParameter(*cgParam, diffuseImposters[index]->renderTarget->GetDepthTexID()); else cgGLSetTextureParameter(*cgParam, reflectiveImposters[index]->renderTarget->GetDepthTexID()); break; } } } /*-------------------------------------------------------------------------- * Binds a matrix of type MatrixType to the cgParam *--------------------------------------------------------------------------*/ void Reflector::CGBindImposterMatrix(CGparameter* cgParam, MatrixType type, int index, bool diffuse) { double* matrix; switch(type) { case MVP: { if(diffuse) matrix = diffuseImposters[index]->mvp; else matrix = reflectiveImposters[index]->mvp; break; } case InvMVP: { if(diffuse) matrix = diffuseImposters[index]->invMVP; else matrix = reflectiveImposters[index]->invMVP; break; } } cgGLSetMatrixParameterdc(*cgParam, matrix); } /*-------------------------------------------------------------------------- * Updates the impostors if a request is sent from the GUI *--------------------------------------------------------------------------*/ bool Reflector::RequestUpdateIfNeeded(ImposterType *newTypes) { bool ret = false; for (unsigned int i = 0; i < diffuseImposters.size(); i++) { if (diffuseImposters[i]->imposterType != newTypes[0]) { diffuseImposters[i]->imposterType = newTypes[0]; diffuseImposters[i]->hasMoved = true; ret = true; } } for (unsigned int i = 0; i < reflectiveImposters.size(); i++) { if (reflectiveImposters[i]->imposterType != newTypes[0]) { reflectiveImposters[i]->imposterType = newTypes[0]; reflectiveImposters[i]->hasMoved = true; ret = true; } } return ret; } /*-------------------------------------------------------------------------- * Image-space Refraction Params *--------------------------------------------------------------------------*/ //param = float[4] void RefractionParams::GetLocal1(float *param) { // local1 = { 2*f*n, f-n, f+n, } // f = distance to the OpenGL far plane // n = distance to the OpwnGL near plane float znear = scene->frameBuffer->phc->hither; float zfar = scene->frameBuffer->phc->yon; param[0] = 2 * zfar * znear; param[1] = zfar - znear; param[2] = zfar + znear; param[3] = 0.0f; } //param = float[4] void RefractionParams::GetLocal2(float *param) { // local2 = { n_i/n_t, (n_i/n_t)^2, , } // n_i = index of refraction of external material (air) // n_t = index of refraction of internal material param[0] = index_1 / index_2; param[1] = param[0] * param[0]; param[2] = 0.0f; param[3] = 0.0f; } //param = float[4] void RefractionParams::GetLocal3(float *param) { // local3 = { n_t/n_i, (n_t/n_i)^2, objectSize, sqrt( 1 - (n_i/n_t)^2 ) } param[0] = index_1 / index_2; param[1] = param[0] * param[0]; param[2] = objectScale; param[3] = sqrtf( 1 - param[1] ); }