void SphericalXZ::ToCartesian( Matrix4* out ) { Matrix4 roty; // theta Matrix4 rotz; // rho Matrix4 trans; roty.SetYRotation( theta ); rotz.SetZRotation( rho ); trans.SetTranslation( r, 0.f, 0.f ); *out = roty * rotz * trans; }
void DecalMesh::SetPosV( const Vector3F& newPos, const Matrix4& _newRot ) { float zRot = _newRot.CalcRotationAroundAxis(2); zRot = NormalizeAngleDegrees( zRot ); Matrix4 newRot; newRot.SetZRotation( zRot ); // We don't need to ask the container (the TerrainMesh) where we // will be, since the decal is patched to the terrain. if ( newPos.x != pos.x || newPos.y != pos.y || newRot != rotation || !InList() ) { pos = newPos; rotation = newRot; Rectangle3F base; base.Set( -size / 2.0f, -size / 2.0f, (TERRAIN_MIN+0.01f), size / 2.0f, size / 2.0f, (TERRAIN_MAX-0.01f) ); if ( InList() ) ListRemove(); ComputeTransform(); CalcAABB( base ); Lilith3D::Instance()->GetQuadTree()->AddMesh( this ); // Compute the texture matrix for this decal. Matrix4 center, inverse, scale; Transform().Invert( &inverse ); // position the texture with the mesh center.SetTranslation( 0.5f, 0.5f, 0.5f ); // center the decal scale.SetScale( 1.0f / size ); texMat = center * scale * inverse; } }
void Screenport::SetPerspective( const grinliz::Rectangle2I* clip ) { uiMode = false; if ( clip && clip->Area() > 1 ) { clipInUI3D = Rectangle2F( (float)clip->min.x, (float)clip->min.y, (float)clip->max.x, (float)clip->max.y ); } else { clipInUI3D = Rectangle2F( 0, 0, UIWidth(), UIHeight() ); } GLASSERT( clipInUI3D.IsValid() ); GLASSERT( clipInUI3D.min.x >= 0 && clipInUI3D.max.x <= UIWidth() ); GLASSERT( clipInUI3D.min.y >= 0 && clipInUI3D.max.y <= UIHeight() ); Rectangle2F scissor; UIToWindow( clipInUI3D, &scissor ); Rectangle2I clean; CleanScissor( scissor, &clean ); GPUShader::SetScissor( clean.min.x, clean.min.y, clean.Width(), clean.Height() ); GLASSERT( uiMode == false ); GLASSERT( EL_NEAR > 0.0f ); GLASSERT( EL_FAR > EL_NEAR ); frustum.zNear = EL_NEAR; frustum.zFar = EL_FAR; // Convert from the FOV to the half angle. float theta = ToRadian( EL_FOV * 0.5f ); float tanTheta = tanf( theta ); float halfLongSide = tanTheta * frustum.zNear; // left, right, top, & bottom are on the near clipping // plane. (Not an obvious point to my mind.) // Also, the 3D camera applies the rotation. if ( Rotation() & 1 ) { float ratio = (float)clipInUI3D.Height() / (float)clipInUI3D.Width(); // frustum is in original screen coordinates. frustum.top = halfLongSide; frustum.bottom = -halfLongSide; frustum.left = -ratio * halfLongSide; frustum.right = ratio * halfLongSide; } else { // Since FOV is specified as the 1/2 width, the ratio // is the height/width (different than gluPerspective) float ratio = (float)clipInUI3D.Height() / (float)clipInUI3D.Width(); frustum.top = ratio * halfLongSide; frustum.bottom = -frustum.top; frustum.left = -halfLongSide; frustum.right = halfLongSide; } Matrix4 rot; rot.SetZRotation( (float)(-90 * Rotation()) ); // In normalized coordinates. projection3D.SetFrustum( frustum.left, frustum.right, frustum.bottom, frustum.top, frustum.zNear, frustum.zFar ); projection3D = projection3D * rot; GPUShader::SetPerspectiveTransform( frustum.left, frustum.right, frustum.bottom, frustum.top, frustum.zNear, frustum.zFar, (90*Rotation()) ); }
void Mesh::SetPos( const grinliz::Vector3F& p, float z ) { Matrix4 r; r.SetZRotation( z ); SetPos( p, r ); }