?? gsphereimage.h
字號:
/* 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*/#ifndef __GSPHEREIMAGE_H__#define __GSPHEREIMAGE_H__#include "GMacros.h"#include <math.h>#include "GBezier.h"#include "GImage.h"#include "GRayTrace.h"
class GSphereImagePixelEnumerator;class QImage;class GImage;class G3DObject;class GRayTraceVector;
// Represents a spherical image with pixels evenly distributed on the surface of the sphereclass GSphereImage{friend class GSphereImagePixelEnumerator;protected: int m_nQuarterGirth; double m_dHalfGirth; double m_dRadius; double m_dTheta; int m_nWidth; int m_nHeight;public: GSphereImage(int nQuarterGirth); // nQuarterGirth is one fourth the circumference of the sphere virtual ~GSphereImage(); // returns one fourth the circumference of the sphere int GetQuarterGirth() { return m_nQuarterGirth; } // Returns the width of the flattened image that textures the sphere int GetWidth() { return m_nWidth; } // Returns the height of the flattened image that textures the sphere int GetHeight() { return m_nHeight; } // Returns the radius of the sphere double GetRadius() { return m_dRadius; } // Returns the angle between ajacent pixels double GetTheta() { return m_dTheta; } inline static void WrapRadians(double& yaw, double& pitch, bool* pbVertFlip) { if(pitch >= 3 * PI / 2) pitch -= ((2 * PI) * (int)((pitch + PI / 2) / (2 * PI))); if(pitch < -PI / 2) pitch += ((2 * PI) * (int)((3 * PI / 2 - pitch) / (2 * PI))); if(pitch > PI / 2) { pitch = PI - pitch; yaw += PI; *pbVertFlip = true; } else *pbVertFlip = false; if(yaw >= 3 * PI / 2) yaw -= ((2 * PI) * (int)((yaw + PI / 2) / (2 * PI))); if(yaw < -PI / 2) yaw += ((2 * PI) * (int)((3 * PI / 2 - yaw) / (2 * PI))); } // This expects pitch to be between -PI/2 and PI/2 (inclusively), and yaw to be between -PI/2 to 3*PI/2 (inclusively) void GetFlattenedCoords(double yaw, double pitch, double* pdX, double* pdY); void SafeGetFlattenedCoords(double yaw, double pitch, double* pdX, double* pdY); // This expects nX and nY to be somewhere on the flat image void GetSphereCoords(int nX, int nY, double* pyaw, double* ppitch);protected: inline void ToFlat(double yaw, double pitch, double* pdX, double* pdY) { *pdY = (pitch * m_dHalfGirth) / PI; *pdX = (cos(pitch) * yaw * m_dHalfGirth) / PI; } inline void ToSphere(int nX, int nY, double* pyaw, double* ppitch) { *ppitch = (PI * (double)nY) / m_dHalfGirth; *pyaw = (PI * (double)nX) / (cos(*ppitch) * m_dHalfGirth); }};// This class iterates through the pixels in a GSphereImageclass GSphereImagePixelEnumerator{protected: GSphereImage* m_pSphere; int m_nX; int m_nY; int m_nFrontLeft; int m_nFrontRight; int m_nBackLeft; int m_nBackRight;public: GSphereImagePixelEnumerator(GSphereImage* pSphere) { m_pSphere = pSphere; Reset(); } void Reset() { m_nX = 0; m_nY = 0; RecalculateBounds(); } bool GetNext(int* pnX, int* pnY);protected: void RecalculateBounds();};class GPreRendered3DScreen : public GSphereImage{protected: GImage* m_pImage; float* m_pDepthMap; struct Transform m_camera; double m_dZoom; bool m_bFlatScreen;public: GPreRendered3DScreen(int nSize); virtual ~GPreRendered3DScreen(); GImage* GetFlatImage() { return m_pImage; } float* GetDepthMap() { return m_pDepthMap; } // These values are expressed in radians and can be in any range void SetCameraAngle(const struct Transform* pCamera, bool bFlatScreen); // x, and y are relative to the center of the screen void ScreenPixelToSphereCoords(int x, int y, double* pyaw, double* ppitch); // x, and y are relative to the center of the screen unsigned int GetPixel(int x, int y, float* pDepth);};class GPreRendered3DSprite : public GSphereImage{protected: GImage* m_pImages; float* m_pDepthMap; int m_nArraySize; int* m_pArray; int m_nImageSize;public: // Note: This will allocate a GImage, but it will not resize it. It is your // job to call GetImages and resize the object it returns as appropriate // before you put pixels in it. I realize that makes this a wierd class, // but it suits my purposes for now. GPreRendered3DSprite(int nSize, int nImageSize); virtual ~GPreRendered3DSprite(); GImage* GetImages() { return m_pImages; } float* GetDepthMap() { return m_pDepthMap; } int GetArraySize() { return m_nArraySize; } // Returns the width or height of a single image (they're always square) int GetImageSize() { return m_nImageSize; } // Pass in coordinates on the flattened sphere image and this will return // the horizontal offset where the corresponding frame begins in m_pImages. int GetVertOffset(int nX, int nY) { int nIndex = nY * m_nWidth + nX; GAssert(nIndex >= 0 && nIndex < m_nArraySize, "out of range"); return m_pArray[nIndex]; } int GetVertOffset(double yaw, double pitch) { double nX, nY; GetFlattenedCoords(yaw, pitch, &nX, &nY); return GetVertOffset((int)nX, (int)nY); } int SafeGetVertOffset(double yaw, double pitch, bool* pbVertFlip) { WrapRadians(yaw, pitch, pbVertFlip); double nX, nY; GetFlattenedCoords(yaw, pitch, &nX, &nY); return GetVertOffset((int)nX, (int)nY); }};class GBoxScene{protected: GImage m_image; float* m_pDepthMap;public: GBoxScene(int nWidth) { m_image.SetSize(nWidth, 6 * nWidth); m_pDepthMap = new float[nWidth * 6 * nWidth]; } ~GBoxScene() { delete[] m_pDepthMap; } GImage* GetImage() { return &m_image; } float* GetDepthMap() { return m_pDepthMap; } void RayToPoint(float* pnOutX, float* pnOutY, GRayTraceVector* pRay) { int nFrame, u, v; GRayTraceReal xx = pRay->m_vals[0] * pRay->m_vals[0]; GRayTraceReal yy = pRay->m_vals[1] * pRay->m_vals[1]; GRayTraceReal zz = pRay->m_vals[2] * pRay->m_vals[2]; if(xx >= yy && xx >= zz) { nFrame = 0; u = 2; v = 1; } else if(yy >= zz) { u = 2; nFrame = 1; v = 0; } else { u = 0; v = 1; nFrame = 2; } int halfWidth = m_image.GetWidth() / 2; float t = (float)halfWidth / pRay->m_vals[nFrame]; *pnOutX = t * pRay->m_vals[u] + halfWidth; *pnOutY = t * pRay->m_vals[v] + halfWidth; if(pRay->m_vals[nFrame] < 0) nFrame += 3; (*pnOutY) += m_image.GetWidth() * nFrame; } // The ray this returns is NOT normalized void PointToRay(GRayTraceVector* pRay, int x, int y) { int nFrame = y / m_image.GetWidth(); y = y % m_image.GetWidth(); if(nFrame >= 3) { nFrame -= 3; pRay->m_vals[nFrame] = -1; x = m_image.GetWidth() - x; y = m_image.GetWidth() - y; } else pRay->m_vals[nFrame] = 1; int u = (nFrame == 2 ? 0 : 2); int v = (nFrame == 1 ? 0 : 1); pRay->m_vals[u] = (float)(x * 2) / m_image.GetWidth() - 1; pRay->m_vals[v] = (float)(y * 2) / m_image.GetWidth() - 1; }};#endif // __GSPHEREIMAGE_H__
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -