void PerspectiveCamera::setCameraForSelection(int x,int y,int selectionWidth,int selectionHeight,float width,float height,float ratio) { GLint viewport[4]; glGetIntegerv(GL_VIEWPORT,viewport); glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* glColor3ub(255,0,0); glBegin(GL_QUADS); glVertex2f(-1,-1); glVertex2f(-1,1); glVertex2f(1,1); glVertex2f(1,-1); glEnd(); */ gluPickMatrix(x+selectionWidth*0.5f,viewport[3]-y-selectionHeight*0.5f,selectionWidth,selectionHeight,viewport); gluPerspective(fov(), ratio, nearPlane(), farPlane()); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(from()[0],from()[1],from()[2] ,to()[0],to()[1], to()[2],up()[0],up()[1],up()[2]); }
void PerspectiveCamera::setCamera(float width,float height,float ratio) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); //qDebug("%f,%f,",nearPlane(),farPlane()); gluPerspective(fov(), ratio, nearPlane(), farPlane()); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(from()[0],from()[1],from()[2] ,to()[0],to()[1], to()[2],up()[0],up()[1],up()[2]); }
void PerspectiveCamera::save(const QString &filename) { FILE *fp=fopen(filename.toStdString().c_str(),"wb"); float sfov=fov(); float sfarPlane=farPlane(); float snearPlane=nearPlane(); GGL::Point3f sfrom=from(); GGL::Point3f sto=to(); GGL::Point3f sup=up(); fwrite(&sfov,sizeof(float),1,fp); fwrite(&sfarPlane,sizeof(float),1,fp); fwrite(&snearPlane,sizeof(float),1,fp); float vsfrom[3]; vsfrom[0]=from().X(); vsfrom[1]=from().Y(); vsfrom[2]=from().Z(); fwrite(vsfrom,sizeof(float),3,fp); float vsto[3]; vsto[0]=to().X(); vsto[1]=to().Y(); vsto[2]=to().Z(); fwrite(vsto,sizeof(float),3,fp); float vsup[3]; vsup[0]=up().X(); vsup[1]=up().Y(); vsup[2]=up().Z(); fwrite(vsup,sizeof(float),3,fp); fclose(fp); }
/** * @brief cwOrthogonalProjection::calculateProjection * @return */ cwProjection cwOrthogonalProjection::calculateProjection() { cwProjection proj; if(projection().isNull()) { proj = viewer()->orthoProjectionDefault(); setPrivateFarPlane(proj.far()); setPrivateNearPlane(proj.near()); } else { proj = projection(); } cwProjection viewProj = viewer()->orthoProjectionDefault(); proj.setOrtho(viewProj.left(), viewProj.right(), viewProj.bottom(), viewProj.top(), nearPlane(), farPlane()); return proj; }
bool Frustum::bakeProjectionOffset() { // Nothing to bake if ortho if( mIsOrtho ) return false; // Nothing to bake if no offset if( mProjectionOffset.isZero() ) return false; // Near plane points in camera space Point3F np[4]; np[0].set( mNearLeft, mNearDist, mNearTop ); // NearTopLeft np[1].set( mNearRight, mNearDist, mNearTop ); // NearTopRight np[2].set( mNearLeft, mNearDist, mNearBottom ); // NearBottomLeft np[3].set( mNearRight, mNearDist, mNearBottom ); // NearBottomRight // Generate the near plane PlaneF nearPlane( np[0], np[1], np[3] ); // Far plane points in camera space const F32 farOverNear = mFarDist / mNearDist; Point3F fp0( mNearLeft * farOverNear, mFarDist, mNearTop * farOverNear ); // FarTopLeft Point3F fp1( mNearRight * farOverNear, mFarDist, mNearTop * farOverNear ); // FarTopRight Point3F fp2( mNearLeft * farOverNear, mFarDist, mNearBottom * farOverNear ); // FarBottomLeft Point3F fp3( mNearRight * farOverNear, mFarDist, mNearBottom * farOverNear ); // FarBottomRight // Generate the far plane PlaneF farPlane( fp0, fp1, fp3 ); // The offset camera point Point3F offsetCamera( mProjectionOffset.x, 0.0f, mProjectionOffset.y ); // The near plane point we'll be using for our calculations below U32 nIndex = 0; if( mProjectionOffset.x < 0.0 ) { // Offset to the left so we'll need to use the near plane point on the right nIndex = 1; } if( mProjectionOffset.y > 0.0 ) { // Offset to the top so we'll need to use the near plane point at the bottom nIndex += 2; } // Begin by calculating the offset point on the far plane as it goes // from the offset camera to the edge of the near plane. Point3F farPoint; Point3F fdir = np[nIndex] - offsetCamera; fdir.normalize(); if( farPlane.intersect(offsetCamera, fdir, &farPoint) ) { // Calculate the new near plane edge from the non-offset camera position // to the far plane point from above. Point3F nearPoint; Point3F ndir = farPoint; ndir.normalize(); if( nearPlane.intersect( Point3F::Zero, ndir, &nearPoint) ) { // Handle a x offset if( mProjectionOffset.x < 0.0 ) { // The new near plane right side mNearRight = nearPoint.x; } else if( mProjectionOffset.x > 0.0 ) { // The new near plane left side mNearLeft = nearPoint.x; } // Handle a y offset if( mProjectionOffset.y < 0.0 ) { // The new near plane top side mNearTop = nearPoint.y; } else if( mProjectionOffset.y > 0.0 ) { // The new near plane bottom side mNearBottom = nearPoint.y; } } } mDirty = true; // Indicate that we've modified the frustum return true; }
Frustum<float> Camera::getFrustum() const { float hnear, wnear; float hfar, wfar; hnear = 2 * tanf(fov / 2) * nearDist; wnear = hnear * ratio; hfar = 2 * tanf(fov / 2) * farDist; wfar = hfar * ratio; vector3f farCenter = front * farDist; vector3f nearCenter = front * nearDist; vector3f right = cross(front, up); //tworzę wierzchołki vector3f ftl = farCenter + (up * hfar / 2) - (right * wfar / 2); vector3f ftr = farCenter + (up * hfar / 2) + (right * wfar / 2); vector3f fbl = farCenter - (up * hfar / 2) - (right * wfar / 2); vector3f fbr = farCenter - (up * hfar / 2) + (right * wfar / 2); vector3f ntl = nearCenter + (up * hnear / 2) - (right * wnear / 2); vector3f ntr = nearCenter + (up * hnear / 2) + (right * wnear / 2); vector3f nbl = nearCenter - (up * hnear / 2) - (right * wnear / 2); vector3f nbr = nearCenter - (up * hnear / 2) + (right * wnear / 2); //tworzę płaszczyzny plane<float> nearPlane(nearCenter, front); plane<float> farPlane(farCenter, -front); plane<float> rightPlane(vector3f(0, 0, 0), cross(up, (nearCenter + right * wnear / 2).normalized())); plane<float> leftPlane(vector3f(0, 0, 0), cross((nearCenter - right * wnear / 2).normalized(), up)); plane<float> topPlane(vector3f(0, 0, 0), cross((nearCenter + up * hnear / 2).normalized(), right)); plane<float> bottomPlane(vector3f(0, 0, 0), cross(right, (nearCenter - up * hnear / 2).normalized())); /* tu może być komszmarnie dużo błędów, to najbardziej "ludzki" fragment kodu top=3 | v 7___________________6 /: /| / : / | / : / | / : / | /__________________/ | 4| : 5| | 4=left->| : | | <- right =5 | : far=\ | | | : rear=1 | | | :.............|....| | . 3 | / 2 | . | / | . | / |. front=0=near |/ |__________________/ 0 1 ^ | bottom=2 */ std::vector < plane < float >> planes; std::vector < vector3f> vertices; std::vector<Polyhedron<float>::PolyhedronEdge> edges; //KOLEJNOŚĆ ŚCIAN MA ZNACZENIE! #define pp(_plane) planes.push_back(_plane) pp(nearPlane); pp(farPlane); pp(bottomPlane); pp(topPlane); pp(leftPlane); pp(rightPlane); #undef pp //KOLEJNOŚĆ WIERZCHOŁKÓW MA ZNACZENIE! #define pv(_vert) vertices.push_back(_vert) pv(nbl); pv(nbr); pv(fbr); pv(fbl); pv(ntl); pv(ntr); pv(ftr); pv(ftl); #undef pv //kolejność krawędzi nie ma znaczenia #define pe(v1, v2, p1, p2) edges.push_back(Polyhedron<float>::PolyhedronEdge(v1, v2, p1, p2)) pe(0, 1, 2, 0); //bottom-front pe(1, 2, 2, 5); //bottom-right pe(2, 3, 2, 1); //bottom-far pe(3, 0, 2, 4); //bottom-left pe(0, 4, 4, 0); //left-front pe(1, 5, 0, 5); //front-right pe(2, 6, 5, 1); //right-far pe(3, 7, 1, 4); //far-left pe(4, 5, 0, 3); //front-top pe(5, 6, 5, 3); //right-top pe(6, 7, 1, 3); //far-top pe(7, 4, 4, 3); //left-top #undef pe return Frustum<float>(planes, vertices, edges, vector3f(0, 0, 0)); }
void Frustum::Calculate(float angle, float ratio, float near, float far, Vector3 &camPos, Vector3 &lookAt, Vector3 &up) { Vector3 xVec, yVec, zVec; Vector3 vecN, vecF; Vector3 nearTopLeft, nearTopRight, nearBottomLeft, nearBottomRight; Vector3 farTopLeft, farTopRight, farBottomLeft, farBottomRight; float radians = (float)tan( (angle) ); float nearH = near * radians; float nearW = nearH * ratio; float farH = far * radians; float farW = farH * ratio; zVec = camPos - lookAt; zVec.Normalize(); xVec = up.Cross(zVec); xVec.Normalize(); yVec = zVec.Cross(xVec); vecN = camPos - zVec * near; vecF = camPos - zVec * far; nearTopLeft = vecN + yVec * nearH - xVec * nearW; nearTopRight = vecN + yVec * nearH + xVec * nearW; nearBottomLeft = vecN - yVec * nearH - xVec * nearW; nearBottomRight = vecN - yVec * nearH + xVec * nearW; farTopLeft = vecF + yVec * farH - xVec * farW; farTopRight = vecF + yVec * farH + xVec * farW; farBottomLeft = vecF - yVec * farH - xVec * farW; farBottomRight = vecF - yVec * farH + xVec * farW; //DumpVector3(nearTopLeft); //DumpVector3(nearTopRight); //DumpVector3(nearBottomLeft); //DumpVector3(nearBottomRight); //std::cout<<"------------------------\n"; // Clear the frustrum & add the 6 planes mFrustum.clear(); Plane top(nearTopRight, nearTopLeft, farTopLeft); mFrustum.push_back(top); Plane bottom(nearBottomLeft, nearBottomRight, farBottomRight); mFrustum.push_back(bottom); Plane left(nearTopLeft, nearBottomLeft, farBottomLeft); mFrustum.push_back(left); Plane right(nearBottomRight, nearTopRight, farBottomRight); mFrustum.push_back(right); Plane nearPlane(nearTopLeft, nearTopRight, nearBottomRight); mFrustum.push_back(nearPlane); Plane farPlane(farTopRight, farTopLeft, farBottomLeft); mFrustum.push_back(farPlane); }
//! gets a perspective projection matrix from camera math::matrix4x4<float> geometry::Camera::perspective() const { return math::matrix4x4<float>::projection(nearPlane(), farPlane(), fovH(), fovV()); }
void FrustumProperty::setFarPlane(float farPlane) { Property::setValue(QVariant::fromValue(Frustum(left(), right(), bottom(), top(), nearPlane(), farPlane))); }