#include ".\impostor.h" #include #include #include Impostor::Impostor(void) { m_OwnCamera.setAspectRatio(1); m_OwnCamera.SetUpVector(0,1,0); NeedRefresh=true; m_ErrorTolerance=0.1; UVs[0]=0; UVs[1]=1; UVs[2]=1; UVs[3]=1; UVs[4]=1; UVs[5]=0; UVs[6]=0; UVs[7]=0; } Impostor::~Impostor(void) { } void Impostor::DisplayScreenQuad(int u,int v) { glDisable(GL_LIGHTING); glShadeModel(GL_FLAT); //glViewport(0,0,u, v); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glBegin(GL_QUADS); glTexCoord2f(0,v); glVertex3f(-1,1,0); glTexCoord2f(u,v); glVertex3f(1,1,0); glTexCoord2f(u,0); glVertex3f(1,-1,0); glTexCoord2f(0,0); glVertex3f(-1,-1,0); glEnd(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } void Impostor::Display() { glDisable(GL_LIGHTING); glShadeModel(GL_FLAT); /* glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer (3, GL_DOUBLE, 0, Vertices); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2,GL_DOUBLE,0,UVs); glDrawArrays(GL_QUADS, 0, 4);*/ glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glBegin(GL_QUADS); glTexCoord2dv(&UVs[0]); glVertex3dv(&Vertices[0]); glTexCoord2dv(&UVs[2]); glVertex3dv(&Vertices[3]); glTexCoord2dv(&UVs[4]); glVertex3dv(&Vertices[6]); glTexCoord2dv(&UVs[6]); glVertex3dv(&Vertices[9]); glEnd(); } void Impostor::updateCamera(bool forceRefresh) { bool needRefresh=false; Vector prevViewdir=m_ObjectPosition-m_OwnCamera.getPosition(); if(prevViewdir.x==0&&prevViewdir.y==0&&prevViewdir.z==0) { needRefresh=true; } if(!forceRefresh&&!needRefresh) { //compute error double error; prevViewdir.Normalize(); prevViewdir*=m_ObjectBSphereRadius; Vector point1=m_ObjectPosition+prevViewdir; Vector point2=m_ObjectPosition-prevViewdir; Vector v1=point1-m_ViewCamera->getPosition(); Vector v2=point2-m_ViewCamera->getPosition(); error=acos((v1*v2)/(v1.Length()*v2.Length())); error*=180/M_PI; //if error > error tolerance then refresh is needed if(error>m_ErrorTolerance) { needRefresh=true; } } //refresh camera if(forceRefresh||needRefresh) { //to tell the object to refresh the impostor image NeedRefresh=true; //refresh own camera:position, viewangle, clipplanes m_OwnCamera.SetPosition(m_ViewCamera->getPosition()); Vector toObject=m_ObjectPosition-m_OwnCamera.getPosition(); double distance=toObject.Length(); double nearplane=distance-m_ObjectBSphereRadius; double farplane=distance+m_ObjectBSphereRadius; double angle=atan(m_ObjectBSphereRadius/distance); m_OwnCamera.setFovY(2*angle/M_PI*180); m_OwnCamera.setFovX(m_OwnCamera.getFovY()); m_OwnCamera.setNearClipDistance(nearplane); m_OwnCamera.setFarClipDistance(farplane); m_OwnCamera.setCorners(-m_ObjectBSphereRadius,m_ObjectBSphereRadius,m_ObjectBSphereRadius,-m_ObjectBSphereRadius); //if object has moved m_OwnCamera.setLookAt(m_ObjectPosition); } else NeedRefresh=false; m_UpLeft=m_ViewCamera->getUpVector()-m_ViewCamera->getRightVector(); m_UpRight=m_ViewCamera->getUpVector()+m_ViewCamera->getRightVector(); m_DownLeft=m_ViewCamera->getUpVector()*-1-m_ViewCamera->getRightVector(); m_DownRight=m_ViewCamera->getUpVector()*-1+m_ViewCamera->getRightVector(); m_UpLeft.Normalize(); m_DownLeft.Normalize(); m_UpRight.Normalize(); m_DownRight.Normalize(); double corndist=m_ObjectBSphereRadius*sqrt(2.0); m_UpLeft*=corndist; m_DownLeft*=corndist; m_UpRight*=corndist; m_DownRight*=corndist; //update corner vertices Vertices[9]=m_UpLeft.x; Vertices[10]=m_UpLeft.y; Vertices[11]=m_UpLeft.z; Vertices[6]=m_UpRight.x; Vertices[7]=m_UpRight.y; Vertices[8]=m_UpRight.z; Vertices[3]=m_DownRight.x; Vertices[4]=m_DownRight.y; Vertices[5]=m_DownRight.z; Vertices[0]=m_DownLeft.x; Vertices[1]=m_DownLeft.y; Vertices[2]=m_DownLeft.z; }