I'm working on my litlle solar system simulaion, where I use some icospheres to generate planets.
i use icospheres because i want to create dynamicly updateing planet surface, so in this case icospheres are better than UVspheres
As you probaly know when you try to appy uv's on sphere you will see very big seam on 180 degree. To solve it, firstly i try to create a shader but the seam become only smaller.
Eventualy i found a solution. I called it IcoSphereCubeMapCreator. The idea my was very simple, you must create uvsphere and apply texture on it (on uvsphere there are any seams )
Next you put 6 camera( each of them in difrent direction) inside this sphere and take a picture. I'm posting this because i didn't find any working solutions.
It looks nice.
http://zapodaj.net/c4892ac01b1be.jpg.html
SphereCubeMapCreator.h
Code: Select all
#pragma once
#include <Ogre.h>
using namespace Ogre;
class SphereCubeMapCreator : public Singleton<SphereCubeMapCreator>
{
private:
SphereCubeMapCreator();
~SphereCubeMapCreator();
public:
String ConvertToCubeMap(String TexName, String dotFormat);
void createSphere(const std::string& strName, const float r, const int nRings, const int nSegments);
static SphereCubeMapCreator* create();
static SphereCubeMapCreator& getSingleton(void);
static SphereCubeMapCreator* getSingletonPtr(void);
std::map<int,TexturePtr> mCubeMapTextures;
int texNumber;
SceneManager* mSceneManager;
Camera* mCameras[6];
std::map<std::string,int> mRenderTargetIndexes;
void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
};
Code: Select all
#include "SphereCubeMapCreator.h"
template<> SphereCubeMapCreator* Ogre::Singleton<SphereCubeMapCreator>::msSingleton = 0;
SphereCubeMapCreator* SphereCubeMapCreator::getSingletonPtr(void)
{
return msSingleton;
}
SphereCubeMapCreator& SphereCubeMapCreator::getSingleton(void)
{
assert(msSingleton); return (*msSingleton);
}
//------------------------------------------------------------------------------------------------------------------------------------
SphereCubeMapCreator::SphereCubeMapCreator() :texNumber(0)
{
mSceneManager = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC, "SphereCubeMapCreator");
for (int i = 0; i < 6; i++)
{
mCameras[i] = mSceneManager->createCamera("CameraCubeMap" + Ogre::StringConverter::toString(i));
mCameras[i]->setNearClipDistance(0.1);
mCameras[i]->setAspectRatio(1);
mCameras[i]->setFOVy(Ogre::Radian(Ogre::Math::PI / 2));
mCameras[i]->setDirection(1, 0, 0);
}
createSphere("Sphere", 10, 64, 64);
Ogre::MaterialPtr mat =
Ogre::MaterialManager::getSingleton().create(
"SphereUV", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
mat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
Entity* sphereEntity = mSceneManager->createEntity("mySphereEntity", "Sphere");
SceneNode* sphereNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
sphereEntity->setMaterialName("SphereUV");
sphereNode->attachObject(sphereEntity);
}
//------------------------------------------------------------------------------------------------------------------------------------
SphereCubeMapCreator* SphereCubeMapCreator::create()
{
if (!msSingleton)
msSingleton = new SphereCubeMapCreator;
return msSingleton;
}
SphereCubeMapCreator::~SphereCubeMapCreator()
{
}
String SphereCubeMapCreator::ConvertToCubeMap(String TexName,String dotFormat)
{
Image img;
img.load(TexName + dotFormat, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
//img.flipAroundX();
img.flipAroundY();
TexturePtr tex1 = Ogre::TextureManager::getSingleton().createManual(TexName,
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, img.getWidth(), img.getHeight(), 0, 0, Ogre::PF_A8R8G8B8, Ogre::TU_RENDERTARGET);
tex1->loadImage(img);
auto tex = Ogre::TextureManager::getSingleton().createManual(TexName + "CubeMap",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_CUBE_MAP, 512, 512, 0, 0, Ogre::PF_A8R8G8B8, Ogre::TU_RENDERTARGET);
Ogre::MaterialManager::getSingleton().getByName("SphereUV")->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
Ogre::MaterialManager::getSingleton().getByName("SphereUV")->getTechnique(0)->getPass(0)->createTextureUnitState(TexName);
mCubeMapTextures[++texNumber] = tex;
for (int i = 0; i < 6; i++)
{
Ogre::RenderTarget *renderTarget = mCubeMapTextures[texNumber]->getBuffer(i)->getRenderTarget();
renderTarget->setAutoUpdated(false);
switch (i)
{
case 0:
mCameras[i]->yaw(Ogre::Radian(-Ogre::Math::PI / 2)); //right
break;
case 1:
mCameras[i]->yaw(Ogre::Radian(Ogre::Math::PI / 2)); //left
break;
case 2:
mCameras[i]->pitch(Ogre::Radian(Ogre::Math::PI / 2)); //up
break;
case 3:
mCameras[i]->pitch(Ogre::Radian(-Ogre::Math::PI / 2)); //down
break;
case 4:
break;//back
case 5:
mCameras[i]->yaw(Ogre::Radian(Ogre::Math::PI)); //front
break;
}
Ogre::Viewport *viewport = renderTarget->addViewport(mCameras[i]);
viewport->setOverlaysEnabled(false);
viewport->setClearEveryFrame(true);
viewport->setBackgroundColour(ColourValue(1,0.8,0.8,1));
renderTarget->update();
mCameras[i]->setDirection(1, 0, 0);
}
return TexName + " CubeMap";
}
void SphereCubeMapCreator::createSphere(const std::string& strName, const float r, const int nRings = 16, const int nSegments = 16)
{
MeshPtr pSphere = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
SubMesh *pSphereVertex = pSphere->createSubMesh();
pSphere->sharedVertexData = new VertexData();
VertexData* vertexData = pSphere->sharedVertexData;
// define the vertex format
VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
size_t currOffset = 0;
// positions
vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION);
currOffset += VertexElement::getTypeSize(VET_FLOAT3);
// normals
vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL);
currOffset += VertexElement::getTypeSize(VET_FLOAT3);
// two dimensional texture coordinates
vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
currOffset += VertexElement::getTypeSize(VET_FLOAT2);
// allocate the vertex buffer
vertexData->vertexCount = (nRings + 1) * (nSegments + 1);
HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
VertexBufferBinding* binding = vertexData->vertexBufferBinding;
binding->setBinding(0, vBuf);
float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD));
// allocate index buffer
pSphereVertex->indexData->indexCount = 6 * nRings * (nSegments + 1);
pSphereVertex->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, pSphereVertex->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
HardwareIndexBufferSharedPtr iBuf = pSphereVertex->indexData->indexBuffer;
unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD));
float fDeltaRingAngle = (Math::PI / nRings);
float fDeltaSegAngle = (2 * Math::PI / nSegments);
unsigned short wVerticeIndex = 0;
// Generate the group of rings for the sphere
for (int ring = 0; ring <= nRings; ring++) {
float r0 = r * sinf(ring * fDeltaRingAngle);
float y0 = r * cosf(ring * fDeltaRingAngle);
// Generate the group of segments for the current ring
for (int seg = 0; seg <= nSegments; seg++) {
float x0 = r0 * sinf(seg * fDeltaSegAngle);
float z0 = r0 * cosf(seg * fDeltaSegAngle);
// Add one vertex to the strip which makes up the sphere
*pVertex++ = x0;
*pVertex++ = y0;
*pVertex++ = z0;
Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy();
*pVertex++ = -vNormal.x;
*pVertex++ = -vNormal.y;
*pVertex++ = -vNormal.z;
*pVertex++ = (float)seg / (float)nSegments;
*pVertex++ = (float)ring / (float)nRings;
if (ring != nRings) {
// each vertex (except the last) has six indices pointing to it
*pIndices++ = wVerticeIndex + nSegments + 1;
*pIndices++ = wVerticeIndex + nSegments;
*pIndices++ = wVerticeIndex;
*pIndices++ = wVerticeIndex + nSegments + 1;
*pIndices++ = wVerticeIndex;
*pIndices++ = wVerticeIndex + 1;
wVerticeIndex++;
}
}; // end for seg
} // end for ring
// Unlock
vBuf->unlock();
iBuf->unlock();
// Generate face list
pSphereVertex->useSharedVertices = true;
// the original code was missing this line:
pSphere->_setBounds(AxisAlignedBox(Vector3(-r, -r, -r), Vector3(r, r, r)), false);
pSphere->_setBoundingSphereRadius(r);
// this line makes clear the mesh is loaded (avoids memory leaks)
pSphere->load();
}
//------------------------------------------------------------------------------------------------------------------------------------
Code: Select all
SphereCubeMapCreator* sph = SphereCubeMapCreator::create();
// ....... // next use
SphereCubeMapCreator::getSingleton().ConvertToCubeMap("textureName",".png"); // this create Cube texture called "texturenNameCubeMap"