Sphere/paraboloid image

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

Sphere/paraboloid image

Post by kinkreet »

What I have to do to render a sphere map or a paraboloid map like this?

For a cube map I can do this, but if I do 180*core::DEGTORAD, no resemblance to the image.

Code: Select all

 
        mat.buildProjectionMatrixPerspectiveFovLH(90*core::DEGTORAD, 1, 0, 1000);
        cam->setProjectionMatrix(mat);
 
Image
Foaly
Posts: 142
Joined: Tue Apr 15, 2014 8:45 am
Location: Germany

Re: Sphere/paraboloid image

Post by Foaly »

Do you want to render To a sphere map or From it, so you can use it in your scene?

Rendering to it will be harder, I guess. I'd just render to a cube map and convert it to a sphere map afterwards, if you really have to.
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

Re: Sphere/paraboloid image

Post by kinkreet »

I want a good 180degrees render xD
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Sphere/paraboloid image

Post by Mel »

Oh, well, mine is 360 degrees ^^U

http://irrlicht.sourceforge.net/forum/v ... =9&t=51130

I render cubemap textures into a single sphere map there. I do it in software mode, using IImages, instead of ITextures.

This is the irrlicht's skybox turned into a spheremap

Image
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

Re: Sphere/paraboloid image

Post by kinkreet »

Casualmente estaba mirando tu post xDD, pero tengo problemas para adaptar mi codigo al SVN, me salen mensajes de deprecated en funciones como setRenderTarget, addRenderTargetTexture, etc.... pero bueno.. mola mucho el post :)
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Sphere/paraboloid image

Post by Mel »

Bueno, mi codigo trabaja enteramente en software, así que no creo que setRenderTarget de mucho problema de por si... Hace mucho tiempo que no miro el SVN, así que a lo mejor están adaptando alguna funcionalidad. La verdad es que si quieren mantener Irrlicht y dar soporte a Vulkan/Direct3D12, van a tener que cambiar muchas cosas. Algunas bastante importantes.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

Re: Sphere/paraboloid image

Post by kinkreet »

tu codigo esta way :) se pueden sacar spheremaps de cubemaps que es lo que quería(mas o menos) y ademas hace enviroement mapping jejeje, ahora me ha picado la curiosidad por el SVN, a ver si consigo pasar mi aplicación con multi render targets ahí
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

[SOLVED]Re: Sphere/paraboloid image

Post by kinkreet »

Object version :)

Code: Select all

#ifndef __SPHEREMAP_GENERATOR_H_INCLUDED__
#define __SPHEREMAP_GENERATOR_H_INCLUDED__
 
#include <irrlicht.h>
 
namespace irr
{
namespace scene
{
 
class SpheremapGenerator
{
    irr::video::IImage* Skydome;
    irr::core::array< irr::video::IImage* > imagesCubemap;
    irr::scene::ISceneManager* smgr;
    irr::video::IVideoDriver * driver;
    irr::core::dimension2du skydomeRes;
 
public:
    SpheremapGenerator( irr::scene::ISceneManager * SceneManager , const irr::core::dimension2du skydomeResolution = irr::core::dimension2du( 2048, 2048 ) );
 
    ~SpheremapGenerator()
    {
 
    }
 
    //Generates a skydome out of a cubemap
    void cubemap2skydome( irr::core::array< irr::video::ITexture* > cubemap,  const io::path & relativeRute = L"Skydome.png");
 
    irr::video::IImage* getSkydome(){ return Skydome; }
 
    void setSkyDomeResolution(const irr::core::dimension2du Resolution );
 
private:
    //Max operation
    inline irr::f32 maxi(const irr::f32 a, const irr::f32 b) { return (a >= b ? a : b); }
 
    //maps a 2D texture coordinate into a 3D vector
    irr::core::vector3df uv2xyz(const irr::core::vector2df inTexCoord);
 
    //maps a 3D vector into a texture
    irr::core::vector2df xyz2uv(const irr::core::vector3df vector);
 
    //reads a single pixel from a texture map
    irr::video::SColor readTexturemap(const irr::core::vector2df texCoord, irr::video::IImage* image);
 
    //reads a pixel from a cubemap. The images are a vector of 6 images
    irr::video::SColor readCubemap(const irr::core::vector3df vector, irr::core::array< irr::video::IImage* >& images);
 
};
 
 
}
}
 
#endif

Code: Select all

#include "SpheremapGenerator.h"
 
namespace irr
{
namespace scene
{
 
SpheremapGenerator::SpheremapGenerator( irr::scene::ISceneManager * SceneManager , const irr::core::dimension2du skydomeResolution )
        : smgr(SceneManager), driver(SceneManager->getVideoDriver()), skydomeRes(skydomeResolution)
{
    Skydome = driver->createImage( irr::video::ECF_A8R8G8B8, skydomeResolution);
}
 
void SpheremapGenerator::cubemap2skydome( irr::core::array< irr::video::ITexture* > cubemap,  const io::path & relativeRute )
{
 
    for( u32 i=0; i < cubemap.size(); i++ )
    {
            imagesCubemap.push_back( driver->createImage( cubemap[i], irr::core::vector2di(0,0), cubemap[i]->getSize()) );
    }
 
    const irr::core::dimension2du skydomeResolution = Skydome->getDimension();
    f32 i,j;
    irr::video::SColor color;
    irr::core::vector3df vector;
    irr::core::vector2df uv;
 
    for( i = 0; i < skydomeResolution.Width; i++ )
    {
        for( j = 0; j < skydomeResolution.Height; j++ )
        {
            uv.X = i / skydomeResolution.Width + 0.5f / skydomeResolution.Width;
            uv.Y = j / skydomeResolution.Height + 0.5f / skydomeResolution.Height;
            vector = uv2xyz(uv);
            color = readCubemap(vector, imagesCubemap);
 
            Skydome->setPixel( i , j, color);
        }
    }
 
    driver->writeImageToFile(Skydome, relativeRute );
 
    for(u32 i = 0; i < 6; i++ )
    {
        imagesCubemap[i]->drop();
    }
 
    for(u32 i = 0; i < 6; i++ )
    {
        imagesCubemap.erase(0);
    }
}
 
 
void SpheremapGenerator::setSkyDomeResolution(const irr::core::dimension2du Resolution )
{
    Skydome->drop();
    Skydome = driver->createImage( irr::video::ECF_A8R8G8B8, Resolution );
}
 
 
irr::core::vector3df SpheremapGenerator::uv2xyz(const irr::core::vector2df inTexCoord)
{
    irr::core::vector3df vec;
    irr::core::vector2df texCoord;
 
    //texture space normalization
    texCoord.X = inTexCoord.X - floor( inTexCoord.X );
    texCoord.Y = inTexCoord.Y - floor( inTexCoord.Y );
 
    vec.X = -sin( texCoord.X * irr::core::PI * 2.0f ) * sin( texCoord.Y * irr::core::PI );
    vec.Y = cos( texCoord.Y * irr::core::PI );
    vec.Z = cos( texCoord.X * irr::core::PI * 2.0f ) * sin( texCoord.Y * irr::core::PI );
 
    return vec.normalize();
}
 
irr::core::vector2df SpheremapGenerator::xyz2uv(const irr::core::vector3df vector)
{
    irr::core::vector2df texCoords;
    irr::core::vector3df vecSQ = vector;
 
    if( vecSQ.X < 0 )
        vecSQ.X = -vecSQ.X;
    if( vecSQ.Y < 0 )
        vecSQ.Y = -vecSQ.Y;
    if( vecSQ.Z < 0 )
        vecSQ.Z = -vecSQ.Z;
 
    if( vecSQ.X > vecSQ.Y && vecSQ.X > vecSQ.Z )
    {
        if( vector.X >= 0 )
        {
            texCoords.X = vector.Z / vector.X * 0.5f;
            texCoords.Y = -vector.Y / vector.X * 0.5f;
        }
        else
        {
            texCoords.X = vector.Z / vector.X * 0.5f;
            texCoords.Y = vector.Y / vector.X * 0.5f;
        }
    }
    else
    {
        if( vecSQ.Y > vecSQ.X && vecSQ.Y > vecSQ.Z )
        {
            if( vector.Y >= 0 )
            {
                texCoords.X = -vector.Z / vector.Y * 0.5f;
                texCoords.Y = -vector.X / vector.Y * 0.5f;
            }
            else
            {
                texCoords.X = vector.Z / vector.Y * 0.5f;
                texCoords.Y = -vector.X / vector.Y * 0.5f;
            }
        }
        else
        {
            if( vector.Z >= 0 )
            {
                texCoords.X = -vector.X / vector.Z * 0.5f;
                texCoords.Y = -vector.Y / vector.Z * 0.5f;
            }
            else
            {
                texCoords.X = -vector.X / vector.Z * 0.5f;
                texCoords.Y = vector.Y / vector.Z * 0.5f;
            }
        }
    }
 
    texCoords += irr::core::vector2df(0.5f , 0.5f);
 
    return texCoords;
}
 
 
irr::video::SColor SpheremapGenerator::readTexturemap(const irr::core::vector2df texCoord, irr::video::IImage* image)
{
    irr::core::vector2df nTexCoord;
    irr::core::vector2df blend;
    irr::core::vector2di baseCoord;
    f32 height = image->getDimension().Height;
    f32 width = image->getDimension().Width;
    irr::video::SColor color;
 
    nTexCoord.X = texCoord.X - floor( texCoord.X );
    nTexCoord.Y = texCoord.Y - floor( texCoord.Y );
 
    baseCoord.X = floor( width * nTexCoord.X );
    baseCoord.Y = floor( height * nTexCoord.Y );
 
    blend.X = width * nTexCoord.X - width;
    blend.Y = height * nTexCoord.Y - height;
 
    color = image->getPixel( baseCoord.X, baseCoord.Y );
 
    irr::f32 clampedCoord = baseCoord.X + 1 >= width ? width - 1 : baseCoord.X + 1;
 
    color = color.getInterpolated( image->getPixel( clampedCoord , baseCoord.Y ), blend.X);
 
    clampedCoord = baseCoord.Y + 1 >= height ? height - 1 : baseCoord.Y + 1;
 
    color = color.getInterpolated( image->getPixel( baseCoord.X , clampedCoord ), blend.Y );
 
    return color;
}
 
irr::video::SColor SpheremapGenerator::readCubemap(const irr::core::vector3df vector, irr::core::array< irr::video::IImage* >& images)
{
    //Order: 0,1 left,right
    //Order: 2,3 down,up
    //Order: 4:5 front,back
    unsigned int facing;
 
    irr::core::vector3df vecSQ = vector;
    vecSQ.X *= vecSQ.X;
    vecSQ.Y *= vecSQ.Y;
    vecSQ.Z *= vecSQ.Z;
 
    irr::f32 maximal = maxi( vecSQ.X, maxi( vecSQ.Y, vecSQ.Z ) );
 
    if( maximal == vecSQ.X )
    {
            facing = ( vector.X < 0? 0 : 1 );
    }
    else
    {
        if(maximal == vecSQ.Y)
        {
                facing = ( vector.Y < 0? 2 : 3 );
        }
        else
        {
            facing = ( vector.Z < 0? 4 : 5 );
        }
    }
 
    irr::core::vector2df texCoords = xyz2uv( vector );
    return readTexturemap(texCoords,images[facing]);
}
 
}
}
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Sphere/paraboloid image

Post by Mel »

A lo mejor quieres echarle un vistazo a esto,

https://www.youtube.com/watch?v=f9v_XN7Wxh8

Hace lo que yo hago en tiempo real. La idea es por otra parte lógica, pero no se hasta que punto es util, o puede resultar eficiente ;)
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

Re: Sphere/paraboloid image

Post by kinkreet »

:O como mola! xDD yo con reflejos estáticos ya iba servido xddd

En la peli de Gamer, las paredes de la habitación eran pantallas, una proyección así estaría way, seria una alternativa a la VR, sin tener que llevar casco(importante), y sin que las pantallas sean de alta densidad. Y en la VR al final ara falta una habitación entera igualmente así que...

EDITO: ...nah, la VR seguiría siendo mejor
Post Reply