/** Handles populating PVRShaman-specific content and delegates remainder to the standard population mechanisms. */ bool CC3PVRShamanShaderSemantics::populateUniform( CC3GLSLUniform* uniform, CC3NodeDrawingVisitor* visitor ) { //LogTrace(@"%@ retrieving semantic value for %@", self, uniform.fullDescription); GLenum semantic = uniform->getSemantic(); GLuint semanticIndex = uniform->getSemanticIndex(); GLint uniformSize = uniform->getSize(); CC3Viewport vp; if ( super::populateUniform( uniform, visitor ) ) return true; switch (semantic) { // Sets a vec2, specific to PVRShaman, that combines the falloff angle (in degrees) and exponent case kCC3PVRShamanSemanticLightSpotFalloff: for (GLint i = 0; i < uniformSize; i++) { CC3Light* light = visitor->getLightAt( semanticIndex + i ); uniform->setPoint( ccp(light->getSpotCutoffAngle(), light->getSpotExponent()), i ); } return true; case kCC3PVRShamanSemanticElapsedTimeLastFrame: // Time of last frame. Just subtract frame time from current time uniform->setFloat( visitor->getScene()->getElapsedTimeSinceOpened() - visitor->getDeltaTime() ); return true; case kCC3PVRShamanSemanticViewportSize: vp = visitor->getRenderSurface()->getViewport(); uniform->setPoint( ccp(vp.w, vp.h) ); return true; case kCC3PVRShamanSemanticViewportClipping: { // Applies the field of view angle to the narrower aspect. vp = visitor->getRenderSurface()->getViewport(); GLfloat aspect = (GLfloat) vp.w / (GLfloat) vp.h; CC3Camera* cam = visitor->getCamera(); GLfloat fovWidth, fovHeight; if (aspect >= 1.0f) { // Landscape fovHeight = CC3DegToRad(cam->getEffectiveFieldOfView()); fovWidth = fovHeight * aspect; } else { // Portrait fovWidth = CC3DegToRad(cam->getEffectiveFieldOfView()); fovHeight = fovWidth / aspect; } uniform->setVector4( CC3Vector4(cam->getNearClippingDistance(), cam->getFarClippingDistance(), fovWidth, fovHeight) ); return true; } default: return false; } }
void CC3Frustum::populateFrom( GLfloat fieldOfView, GLfloat aspect, GLfloat nearClip, GLfloat farClip ) { GLfloat rightClip, topClip; GLfloat halfFOV = fieldOfView / 2.0f; // Apply the field of view angle to the narrower aspect. if ( aspect >= 1.0f ) { // Landscape topClip = nearClip * tanf(CC3DegToRad(halfFOV)); rightClip = topClip * aspect; } else { // Portrait rightClip = nearClip * tanf(CC3DegToRad(halfFOV)); topClip = rightClip / aspect; } populateRight( rightClip, topClip, nearClip, farClip ); }
/** * Returns a point representing the top-right corner of the near clipping plane, * expressed as a proportional multiple of the nearClippingDistance. * * The returned point will have the same aspect ratio as the viewport. The component * values of the point are calculated taking into consideration the effectiveFieldOfView, * fieldOfViewOrientation, and fieldOfViewAspectOrientation properties. */ CCPoint CC3Camera::getOrientedFieldOfViewAspect() { GLfloat halfFOV = getEffectiveFieldOfView() / 2.0f; GLfloat aspect = ((GLfloat) _viewport.w / (GLfloat) _viewport.h); GLfloat right, top, diag, orientationCorrection; switch (_fieldOfViewOrientation) { case CC3FieldOfViewOrientationVertical: top = tanf(CC3DegToRad(halfFOV)); right = top * aspect; orientationCorrection = 1.0f / aspect; break; case CC3FieldOfViewOrientationDiagonal: diag = tanf(CC3DegToRad(halfFOV)); top = diag / sqrtf((aspect * aspect) + 1.0f); right = top * aspect; orientationCorrection = 1.0f; break; case CC3FieldOfViewOrientationHorizontal: default: right = tanf(CC3DegToRad(halfFOV)); top = right / aspect; orientationCorrection = aspect; break; } // If the aspect doesn't match the intended orientation, // bring them in alignment by scaling by the orientation correction. if ((isDeviceOrientationLandscape(_fieldOfViewAspectOrientation) && (aspect < 1.0f)) || (isDeviceOrientationPortrait(_fieldOfViewAspectOrientation ) && (aspect > 1.0f))) { right *= orientationCorrection; top *= orientationCorrection; } return ccp(right, top); }