📄 gsphereimage.cpp
字号:
/* Copyright (C) 2006, Mike Gashler This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. see http://www.gnu.org/copyleft/lesser.html*/#include "GSphereImage.h"#include "GImage.h"GSphereImage::GSphereImage(int nQuarterGirth){ m_nQuarterGirth = nQuarterGirth; m_nWidth = m_nQuarterGirth * 4 + 2; m_nHeight = m_nQuarterGirth * 2 + 1; m_dHalfGirth = (double)(2 * nQuarterGirth); m_dRadius = m_dHalfGirth / PI; m_dTheta = atan(1 / m_dRadius);}GSphereImage::~GSphereImage(){}void GSphereImage::GetFlattenedCoords(double yaw, double pitch, double* pdX, double* pdY){ GAssert(yaw >= -PI / 2 && yaw <= (PI * 3) / 2, "out of range (712)"); GAssert(pitch >= -PI / 2 && pitch <= PI / 2, "out of range (713)"); bool bBack = false; if(yaw >= (PI / 2)) { yaw -= PI; bBack = true; } ToFlat(yaw, pitch, pdX, pdY); (*pdX) += m_nQuarterGirth; (*pdY) += m_nQuarterGirth; if(bBack) (*pdX) += (m_nQuarterGirth * 2 + 1); GAssert((*pdX) >= 0 && (*pdX) < m_nWidth, "out of range (714)"); GAssert((*pdY) >= 0 && (*pdY) < m_nHeight, "out of range (715)");}void GSphereImage::SafeGetFlattenedCoords(double yaw, double pitch, double* pdX, double* pdY){ bool vertFlip; GSphereImage::WrapRadians(yaw, pitch, &vertFlip); GetFlattenedCoords(yaw, pitch, pdX, pdY);}void GSphereImage::GetSphereCoords(int nX, int nY, double* pyaw, double* ppitch){ GAssert(nX >= 0 && nX < m_nWidth, "out of range (716)"); GAssert(nY >= 0 && nY < m_nHeight, "out of range (717)"); bool bBack = false; if(nX > m_nQuarterGirth + m_nQuarterGirth) { nX -= (m_nQuarterGirth + m_nQuarterGirth + 1); bBack = true; } nX -= m_nQuarterGirth; nY -= m_nQuarterGirth; ToSphere(nX, nY, pyaw, ppitch); if(bBack) (*pyaw) += PI; //GAssert(*pyaw >= -PI / 2 && *pyaw <= (PI * 3) / 2, "out of range (718)"); //GAssert(*ppitch >= -PI / 2 && *ppitch <= PI / 2, "out of range (719)");}// ---------------------------------------------------------------------------inline int RoundDoubleDown(double d){ return (int)d;}inline int RoundDoubleUp(double d){ int n = (int)d; if(d - (double)n > 0) n++; return n;}void GSphereImagePixelEnumerator::RecalculateBounds(){ double yaw, pitch; double dX, dY; m_pSphere->GetSphereCoords(0, m_nY, &yaw, &pitch); m_pSphere->GetFlattenedCoords(-PI / 2, pitch, &dX, &dY); m_nFrontLeft = RoundDoubleDown(dX); m_pSphere->GetFlattenedCoords((PI / 2) - .000001, pitch, &dX, &dY); m_nFrontRight = RoundDoubleUp(dX); GAssert(m_nFrontRight >= m_nFrontLeft, "bad math"); m_pSphere->GetFlattenedCoords(PI / 2, pitch, &dX, &dY); m_nBackLeft = RoundDoubleDown(dX); GAssert(m_nBackLeft >= m_nFrontRight, "bad math"); m_pSphere->GetFlattenedCoords((PI * 3) / 2, pitch, &dX, &dY); m_nBackRight = RoundDoubleUp(dX); GAssert(m_nBackRight >= m_nBackLeft, "bad math");}bool GSphereImagePixelEnumerator::GetNext(int* pnX, int* pnY){ if(m_nY >= m_pSphere->m_nQuarterGirth * 2 + 1) return false; *pnX = m_nX; *pnY = m_nY; m_nX++; if(m_nX > m_nBackRight) { m_nY++; m_nX = 0; if(m_nY >= m_pSphere->m_nQuarterGirth * 2 + 1) return false; RecalculateBounds(); } if(m_nX > m_nFrontRight && m_nX < m_nBackLeft) m_nX = m_nBackLeft; if(m_nX < m_nFrontLeft) m_nX = m_nFrontLeft; return true;}// ------------------------------------------------------------------------GPreRendered3DScreen::GPreRendered3DScreen(int nSize) : GSphereImage(nSize){ m_pImage = new GImage(); m_pImage->SetSize(GetWidth(), GetHeight()); m_pDepthMap = new float[GetWidth() * GetHeight()]; GAssert(m_pDepthMap, "out of memory"); Transform t; SetCameraAngle(&t, true);}GPreRendered3DScreen::~GPreRendered3DScreen(){ delete [] m_pDepthMap; delete(m_pImage);}void GPreRendered3DScreen::SetCameraAngle(const struct Transform* pCamera, bool bFlatScreen){ m_camera = *pCamera; m_dZoom = pCamera->dScale * m_dRadius; m_camera.dScale = 1; m_bFlatScreen = bFlatScreen;}void GPreRendered3DScreen::ScreenPixelToSphereCoords(int x, int y, double* pyaw, double* ppitch){ // Zoom Point3D point; if(m_bFlatScreen) { point.m_vals[0] = (double)x / m_dZoom; point.m_vals[1] = (double)y / m_dZoom; point.m_vals[2] = m_dRadius; } else { point.m_vals[0] = m_dRadius * tan((double)x / m_dZoom); point.m_vals[1] = m_dRadius * tan((double)y / m_dZoom); point.m_vals[2] = m_dRadius; } point.Transform(&m_camera); // Convert to sphere coords point.GetLatLon(ppitch, pyaw); GAssert(*ppitch <= PI / (double)2 && *ppitch >= -PI / (double)2, "out of range (710)"); GAssert(*pyaw <= 3 * PI / (double)2 && *pyaw >= -PI / (double)2, "out of range (711)");}unsigned int GPreRendered3DScreen::GetPixel(int x, int y, float* pDepth){ double yaw, pitch; ScreenPixelToSphereCoords(x, y, &yaw, &pitch); double dX, dY; GetFlattenedCoords(yaw, pitch, &dX, &dY); // todo: interpolate the pixel int nImageX = (int)(dX + .5); int nImageY = (int)(dY + .5); *pDepth = m_pDepthMap[nImageY * m_nWidth + nImageX]; return m_pImage->GetPixel(nImageX, nImageY);}// ---------------------------------------------------------------------GPreRendered3DSprite::GPreRendered3DSprite(int nSize, int nImageSize) : GSphereImage(nSize){ // Initialize the array that indexes into the images m_nImageSize = nImageSize; m_nArraySize = m_nWidth * m_nHeight; m_pArray = new int[m_nArraySize]; memset(m_pArray, '\0', m_nArraySize * sizeof(void*)); GSphereImagePixelEnumerator enumerator(this); int nFlattenedX, nFlattenedY; int nOffset = 0; while(enumerator.GetNext(&nFlattenedX, &nFlattenedY)) { int nElement = nFlattenedY * m_nWidth + nFlattenedX; m_pArray[nElement] = nOffset; nOffset += nImageSize; } m_pImages = new GImage(); m_pImages->SetSize(m_nImageSize, nOffset); m_pDepthMap = new float[m_nImageSize * nOffset]; GAssert(m_pDepthMap, "out of memory");}GPreRendered3DSprite::~GPreRendered3DSprite(){ delete[] m_pDepthMap; delete(m_pImages); delete(m_pArray);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -