快速球体结合恒星数据 [英] swift sphere combine star data

查看:21
本文介绍了快速球体结合恒星数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想构建一个观星应用程序.现在我已经建立了一个球体并用星图(基于天体坐标)覆盖它.(

这对于 BSC 星星(D = 几乎 100% 宽度):

alpha 计算为颜色强度 alpha=r+g+b/3.

通过这种方式,视觉和物理二进制文件将混合在一起,增加它们在现实中的视觉大小.这也将避免在任何视图更改期间由于非常接近的恒星之间的混叠而导致的闪烁.

这里是缩放的 GIF 动画(颜色抖动,因此出现绿色噪声),因此您可以感受到它的样子:

[Edit1] 简单的完整 VCL C++ OpenGL 示例

我使用您链接中的深度地图.它们以球面失真渲染,因此球面三角剖分没有意义(不会改善任何东西,因为源数据已经错误).这意味着在极点上使用具有奇点的标准球形网格.JPG 文件无法使用,因为有损压缩伪影将所有内容弄乱(尤其是在极点附近).我使用 TIF 并将所有纹理重新缩放到 4096x2048 分辨率.我觉得较低的分辨率不合适.

这之后只是将球体天空盒与每个纹理混合在一起的问题.结果是这样的:

其中显示了北极区域,因此您可以看到失真并没有那么严重(除非您放大粗略).

在此之后,您可以添加深度图中不存在的星星.但由于深度贴图已经包含 BSC,我认为没有必要再次添加它(除非您想校准渲染器以与创建深度贴图时使用的相同).

此处要求 C++/GL 中的完整示例 它是用 BDS2006 编写的,因此它基于带有单个 20ms 计时器的 VCL 表单应用程序.你可以忽略所有的 VCL 东西(唯一使用的东西是位图加载器,我相信你已经得到了)并且只使用你需要的事件代码.

//---------------------------------------------------------------------#include #include <Math.h>#include #include #pragma hdrstop#include "Unit1.h"//---------------------------------------------------------------------------#pragma 包(smart_init)#pragma 资源*.dfm"TForm1 *Form1;//---------------------------------------------------------------------------//键码(箭头 + 空格),按下状态字 key_left =37;布尔_左=假;字 key_right=39;bool _right=false;字 key_up =38;布尔 _up = 假;字 key_down =40;布尔 _down = 假;WORD key_reset=32;布尔_重置=假;//---------------------------------------------------------------------------GLfloat代表[16],inv[16];//相机矩阵及其伪逆void pseudo_inverse(GLfloat *a,GLfloat *b)//a = inverse(b){//这仅适用于原点为 (0,0,0) 且没有投影的正交矩阵a[0]=b[0];a[4]=b[1];a[8]=b[2];a[12]=b[3];a[1]=b[4];a[5]=b[5];a[9]=b[6];a[13]=b[7];a[2]=b[8];a[6]=b[9];a[10]=b[10];a[14]=b[11];a[3]=b[12];a[7]=b[13];a[11]=b[14];a[15]=b[15];}//---------------------------------------------------------------------------const int nb=64;//切片const int na=nb<<1;//每个赤道点const int _skybox_textures=4;类天空盒{民众:布尔_init;//已启动?GLfloat pos[na][nb][3];//顶点GLfloat txr[na][nb][2];//文本坐标GLuint txrid[_skybox_textures];//纹理 ID天空盒(){_init=false;}~skybox() { if (_init) glDeleteTextures(_skybox_textures,txrid);}无效初始化();//在 OpenGL 已经工作之后调用!!!无效绘制();};void 天空盒::init(){如果 (!_init) { _init=true;glGenTextures(_skybox_textures,txrid);}GLfloat x,y,z,a,b,da,db,r=99.9;GLfloat tx0,tdx,ty0,tdy;//CLAMP_TO_EDGE 不可用时仅进行更正内部, ib;//a,b 到纹理坐标系tx0=0.0;ty0=0.5;tdx=0.5/M_PI;tdy=1.0/M_PI;//将纹理加载到 GPU 内存图形::TBitmap *bmp=新图形::TBitmap;//新的 bmp#ifndef GL_CLAMP_TO_EDGE#define GL_CLAMP_TO_EDGE 0x812F#万一for (int i=0;i<_skybox_textures;i++){字节 q;无符号整数 *pp;int xs,ys,x,y,adr,*txr;union { unsigned int c32;字节 db[4];} C;//从文件加载 bmpif (i==0) bmp->LoadFromFile("skybox_grid.bmp");else if (i==1) bmp->LoadFromFile("skybox_sectors.bmp");else if (i==2) bmp->LoadFromFile("skybox_figures.bmp");else if (i==3) bmp->LoadFromFile("skybox_stars.bmp");否则休息;bmp->HandleType=bmDIB;//允许直接访问像素bmp->PixelFormat=pf32bit;//将像素设置为 32 位,因此 int 与像素大小相同xs=bmp->宽度;//分辨率应该是 2 的幂ys=bmp->高度;txr=new int[xs*ys];//创建一维 txr[] 数组并以 GL 方式在其中存储纹理for(adr=0,y=0;yScanLine[y];for(x=0;xtxr[]c.c32=pp[x];q = c.db[2];c.db[2]=c.db[0];c.db[0]=q;txr[adr]=c.c32;}}glEnable(GL_TEXTURE_2D);//将 txr[] 复制到 GLglBindTexture(GL_TEXTURE_2D,txrid[i]);glPixelStorei(GL_UNPACK_ALIGNMENT, 4);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xs, ys, 0, GL_RGBA, GL_UNSIGNED_BYTE, txr);glDisable(GL_TEXTURE_2D);删除[] txr;//释放内存}删除 bmp;//生成球体网格da=(2.0*M_PI)/GLfloat(na-1);db= M_PI/GLfloat(nb-1);对于 (ib=0,b=-0.5*M_PI;ibHandle);//获取设备上下文像素格式描述符 pfd;ZeroMemory( &pfd, sizeof( pfd ) );//设置DC的像素格式pfd.nSize = sizeof(pfd);pfd.nVersion = 1;pfd.dwFlags = PFD_DRAW_TO_WINDOW |PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER;pfd.iPixelType = PFD_TYPE_RGBA;pfd.cColorBits = 24;pfd.cDepthBits = 24;pfd.iLayerType = PFD_MAIN_PLANE;SetPixelFormat(hdc,ChoosePixelFormat(hdc, &pfd),&pfd);hrc = wglCreateContext(hdc);//创建当前渲染上下文如果(hrc == NULL){ShowMessage("无法初始化 OpenGL 渲染上下文!!!");ogl_incialized=0;返回0;}if(wglMakeCurrent(hdc, hrc) == false){ShowMessage("无法创建当前的 OpenGL 渲染上下文!!!");wglDeleteContext(hrc);//销毁渲染上下文ogl_incialized=0;返回0;}ogl_resize();glEnable(GL_DEPTH_TEST);//ZbufglDisable(GL_CULL_FACE);//vynechavaj odvratene stenyglDisable(GL_TEXTURE_2D);//pouzivaj 纹理,farbu pouzivaj z 纹理glDisable(GL_BLEND);//优先权glShadeModel(GL_SMOOTH);//葫芦阴影glClearColor(0.0f, 0.0f, 0.0f, 1.0f);//背景颜色ogl_incialized=1;返回 1;}//---------------------------------------------------------------------------void TForm1::ogl_exit(){如果(!ogl_incialized)返回;wglMakeCurrent(NULL, NULL);//释放当前渲染上下文wglDeleteContext(hrc);//销毁渲染上下文ogl_incialized=0;}//---------------------------------------------------------------------------void TForm1::ogl_draw(){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);天空.绘制();glFlush();交换缓冲区(hdc);}//---------------------------------------------------------------------------void TForm1::ogl_resize(){xs=客户端宽度;ys=客户端高度;如果 (xs<=0) xs = 1;//防止除以零如果 (ys<=0) ys = 1;如果(!ogl_incialized)返回;glViewport(0,0,xs,ys);//将视口设置为窗口尺寸glMatrixMode(GL_PROJECTION);//歌剧的 projekcnou maticouglLoadIdentity();//jednotkova matica projekciegluPerspective(60,float(xs)/float(ys),0.1,100.0);//matica=perspektiva,120 stupnov premieta z viewsize do 0.1glMatrixMode(GL_TEXTURE);//歌剧的texturovou maticouglLoadIdentity();//jednotkova matica 纹理glMatrixMode(GL_MODELVIEW);//歌剧模型glLoadIdentity();//jednotkova matica modelu (objektu)ogl_draw();}//---------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner){ogl_incialized=0;hdc=NULL;人力资源中心=空;ogl_init();天空.init();国际我;//开始时的单位矩阵对于 (i=0;i<16;i++) rep[i]=0.0;对于 (i=0;i<16;i+=5) rep[i]=1.0;对于 (i=0;i<16;i++) inv[i]=rep[i];}//---------------------------------------------------------------------------void __fastcall TForm1::FormDestroy(TObject *Sender) { ogl_exit();}void __fastcall TForm1::FormResize(TObject *Sender) { ogl_resize();}void __fastcall TForm1::Splitter1Moved(TObject *Sender){ ogl_resize();}void __fastcall TForm1::FormPaint(TObject *Sender) { ogl_draw();}//---------------------------------------------------------------------------void __fastcall TForm1::Timer1Timer(TObject *Sender){GLfloat da=5.0;//[deg/timer_iteration] 中的角转向速度伪逆(inv,rep);glMatrixMode(GL_MODELVIEW);glPushMatrix();glLoadMatrixf(rep);布尔_重绘=假;如果(_left){_redraw=true;glRotatef(+da,0.0,1.0,0.0);}如果 (_right) { _redraw=true;glRotatef(-da,0.0,1.0,0.0);}如果(_up){_redraw=true;glRotatef(+da,1.0,0.0,0.0);}如果(_down){_redraw=true;glRotatef(-da,1.0,0.0,0.0);}如果(_reset){_redraw=true;glLoadIdentity();}如果(_redraw){glGetFloatv(GL_MODELVIEW_MATRIX,rep);伪逆(inv,rep);}glPopMatrix();如果(_redraw)ogl_draw();}//---------------------------------------------------------------------------void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift){if (Key==key_left ) _left =false;if (Key==key_right) _right=false;if (Key==key_up) _up =false;if (Key==key_down ) _down =false;if (Key==key_reset) _reset=false;密钥=0;//键被处理}//---------------------------------------------------------------------------void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift){//按键按下事件if (Key==key_left ) _left =true;if (Key==key_right) _right=true;if (Key==key_up ) _up =true;if (Key==key_down) _down =true;if (Key==key_reset) _reset=true;密钥=0;//键被处理}//---------------------------------------------------------------------------void __fastcall TForm1::FormActivate(TObject *Sender){_left = 假;//焦点改变后清除关键标志_right=假;//只是为了避免不断按下"键_up = 假;//在按键期间窗口焦点交换之后_down = 假;//许多游戏都忽略了这一点,你需要_重置=假;//再次按下并松开卡住的键以停止移动...}//---------------------------------------------------------------------------

这里是编译好的Demo和包含纹理的完整源

通过键盘箭头和空格进行控制.现在只需要处理颜色、混合函数等问题.示例只使用 OpenGL 1.0,没有扩展(CLAMP_TO_EDGE 除外).

您可以使用具有适当组合功能的 MultiTexturing 将多次渲染交换为单次渲染,但我很长时间不使用该功能(因为我改用 GLSL),所以我不是有信心为此添加代码.

玩得开心.

i want to build a stargazing app. And now i already built a sphere and cover it with a star map (based on celestial coordinates). ( https://svs.gsfc.nasa.gov/cgi-bin/details.cgi?aid=3895 )

now i have a json file which has the star catalog from YBS. (also based on celestial coordinates). ( http://tdc-www.harvard.edu/catalogs/bsc5.html )

i want to combine the data with star map, wishing the map to show the name of Constellation whenever my camera node turn to that place. but i don't know how to combine data and sphere. since the sphere will rotate due to user's latitude and time. The star data's coordinates also have to change.

Does anyone has suggestions?

解决方案

Not sure in your environment but in your case I would:

  1. render textured sphere (with the deep map)

    The sphere must be centered in your camera position and have big radius covering whole view area. To avoid seems in polar regions you can use this:

  2. then render the BSC

    Start with dots (Points). How ever if you want to have (un)zoom and or better visualize the magnitude of stars then you need Blending capabilities and render the stars as semi-transparent disc facing camera (billboards) with radius and intensity dependent on zoom and magnitude.

    I usually use this texture for local star (D=1/3 width, rest is corona):

    And this for the BSC stars (D = almost 100% width):

    The alpha is computed as color intensity alpha=r+g+b/3.

    This way visual and physical binaries will blend together adding their visual magnitude as in reality. This will also avoid the flickering during any view change due to aliasing between very close stars.

    Here GIF animation of zoom (colors are dithered hence the greenish noise) so you got feeling how it looks like:

[Edit1] simple full VCL C++ OpenGL example

I use the deep maps from your link. They are rendered with spherical distortion so Sphere triangulation has no point (will not improve anything as the source data is already wrong). That implies the use of standard spherical mesh with singularities on poles. The JPG files are unusable due to lossy compression artifacts messing everything up (especially near poles). I use the TIF and rescale all textures to 4096x2048 resolution. Lower resolution does not feel right to me.

After this is is just a matter of blending the sphere skybox with each texture together. The result is like this:

Which shows North pole area so you can see the distortions are not that bad (unless you zoom of coarse).

After this you can add the stars that are not present in the deep map. But as the deep map already has the BSC included I see no point of adding it again (unless you want to calibrate your renderer to be the same as the deep map was created with).

As requested here Complete example in C++/GL It was written in BDS2006 so it is based on VCL Form application with single 20ms Timer on it. You can ignore all the VCL stuff (the only thing that is used form it is bitmap loader and I am confident you got yours already) and use only event code you need.

//---------------------------------------------------------------------------
#include <vcl.h>
#include <Math.h>
#include <gl/gl.h>
#include <gl/glu.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
// key codes (Arrows + Space), pressed state
WORD key_left =37; bool _left =false;
WORD key_right=39; bool _right=false;
WORD key_up   =38; bool _up   =false;
WORD key_down =40; bool _down =false;
WORD key_reset=32; bool _reset=false;
//---------------------------------------------------------------------------
GLfloat rep[16],inv[16]; // camera matrix and its pseudo inverse
void pseudo_inverse(GLfloat *a,GLfloat *b)  // a = inverse(b)
    {
    // this works only for orthonormal matrices with origin (0,0,0) and no projections
    a[ 0]=b[ 0]; a[ 4]=b[ 1]; a[ 8]=b[ 2]; a[12]=b[ 3];
    a[ 1]=b[ 4]; a[ 5]=b[ 5]; a[ 9]=b[ 6]; a[13]=b[ 7];
    a[ 2]=b[ 8]; a[ 6]=b[ 9]; a[10]=b[10]; a[14]=b[11];
    a[ 3]=b[12]; a[ 7]=b[13]; a[11]=b[14]; a[15]=b[15];
    }
//---------------------------------------------------------------------------
const int nb=64;        // slices
const int na=nb<<1;     // points per equator
const int _skybox_textures=4;
class skybox
    {
public:
    bool _init;             // has been initiated ?
    GLfloat pos[na][nb][3]; // vertex
    GLfloat txr[na][nb][2]; // texcoord
    GLuint  txrid[_skybox_textures]; // texture ids
    skybox() { _init=false; }
    ~skybox() { if (_init) glDeleteTextures(_skybox_textures,txrid); }
    void init();        // call after OpenGL is already working !!!
    void draw();
    };
void skybox::init()
    {
    if (!_init) { _init=true; glGenTextures(_skybox_textures,txrid); }
    GLfloat x,y,z,a,b,da,db,r=99.9;
    GLfloat tx0,tdx,ty0,tdy;// just correction if CLAMP_TO_EDGE is not available
    int ia,ib;

    // a,b to texture coordinate system
    tx0=0.0;
    ty0=0.5;
    tdx=0.5/M_PI;
    tdy=1.0/M_PI;

    // load textures to GPU memory
    Graphics::TBitmap *bmp=new Graphics::TBitmap;   // new bmp
    #ifndef GL_CLAMP_TO_EDGE
    #define GL_CLAMP_TO_EDGE 0x812F
    #endif
    for (int i=0;i<_skybox_textures;i++)
        {
        Byte q;
        unsigned int *pp;
        int xs,ys,x,y,adr,*txr;
        union { unsigned int c32; Byte db[4]; } c;
        // load bmp from file
             if (i==0) bmp->LoadFromFile("skybox_grid.bmp");
        else if (i==1) bmp->LoadFromFile("skybox_sectors.bmp");
        else if (i==2) bmp->LoadFromFile("skybox_figures.bmp");
        else if (i==3) bmp->LoadFromFile("skybox_stars.bmp");
        else break;
        bmp->HandleType=bmDIB;      // allow direct access to pixels
        bmp->PixelFormat=pf32bit;   // set pixel to 32bit so int is the same size as pixel
        xs=bmp->Width;              // resolution should be power of 2
        ys=bmp->Height;
        txr=new int[xs*ys];         // create 1D txr[] array and store texture in it in GL manner
        for(adr=0,y=0;y<ys;y++)
            {
            pp=(unsigned int*)bmp->ScanLine[y];
            for(x=0;x<xs;x++,adr++)
                {
                // rgb2bgr and copy bmp -> txr[]
                c.c32=pp[x];
                q      =c.db[2];
                c.db[2]=c.db[0];
                c.db[0]=q;
                txr[adr]=c.c32;
                }
            }
        glEnable(GL_TEXTURE_2D);    // copy txr[] to GL
        glBindTexture(GL_TEXTURE_2D,txrid[i]);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xs, ys, 0, GL_RGBA, GL_UNSIGNED_BYTE, txr);
        glDisable(GL_TEXTURE_2D);
        delete[] txr;               // release memory
        }
    delete bmp;
    // generate sphere mesh
    da=(2.0*M_PI)/GLfloat(na-1);
    db=     M_PI /GLfloat(nb-1);
    for (ib=0,b=-0.5*M_PI;ib<nb;ib++,b+=db)
    for (ia=0,a= 0.0     ;ia<na;ia++,a+=da)
        {
        x=cos(b)*cos(a);
        y=cos(b)*sin(a);
        z=sin(b);
        pos[ia][ib][0]=r*x;
        pos[ia][ib][1]=r*y;
        pos[ia][ib][2]=r*z;
        txr[ia][ib][0]=tx0+(a*tdx);
        txr[ia][ib][1]=ty0+(b*tdy);
        }
    }
void skybox::draw()
    {
    if (!_init) return;
    int i,ia,ib0,ib1;
    // color table
    GLfloat col[_skybox_textures][3]=
        {
        // R   G   B
        { 0.3,0.2,0.4 },    // Ra,Dec grid
        { 0.0,0.2,0.3 },    // sectors
        { 0.0,0.3,0.4 },    // figures
        { 1.0,1.0,1.0 },    // stars
        };
    // modlevie = inverse of camera matrix to allow local coordinate system rotations
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadMatrixf(inv);
    // set rendering pipeline
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
    // render mesh once per each texture layer (stars are last)
    for (i=0;i<_skybox_textures;i++)
        {
        glBindTexture(GL_TEXTURE_2D,txrid[i]);
        glColor3fv(col[i]);
        for (ib0=0,ib1=1;ib1<nb;ib0=ib1,ib1++)
            {
            glBegin(GL_QUAD_STRIP);
            for (ia=0;ia<na;ia++)
                {
                glTexCoord2fv(txr[ia][ib0]);
                glVertex3fv  (pos[ia][ib0]);
                glTexCoord2fv(txr[ia][ib1]);
                glVertex3fv  (pos[ia][ib1]);
                }
            glEnd();
            }
        }
    // restore states ...
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
    }
//---------------------------------------------------------------------------
skybox sky;
//---------------------------------------------------------------------------
int TForm1::ogl_init()
    {
    if (ogl_inicialized) return 1;
    hdc = GetDC(Form1->Handle);             // get device context
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory( &pfd, sizeof( pfd ) );      // set the pixel format for the DC
    pfd.nSize = sizeof( pfd );
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;
    SetPixelFormat(hdc,ChoosePixelFormat(hdc, &pfd),&pfd);
    hrc = wglCreateContext(hdc);            // create current rendering context
    if(hrc == NULL)
            {
            ShowMessage("Could not initialize OpenGL Rendering context !!!");
            ogl_inicialized=0;
            return 0;
            }
    if(wglMakeCurrent(hdc, hrc) == false)
            {
            ShowMessage("Could not make current OpenGL Rendering context !!!");
            wglDeleteContext(hrc);          // destroy rendering context
            ogl_inicialized=0;
            return 0;
            }
    ogl_resize();
    glEnable(GL_DEPTH_TEST);                // Zbuf
    glDisable(GL_CULL_FACE);                // vynechavaj odvratene steny
    glDisable(GL_TEXTURE_2D);               // pouzivaj textury, farbu pouzivaj z textury
    glDisable(GL_BLEND);                    // priehladnost
    glShadeModel(GL_SMOOTH);                // gourard shading
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);   // background color
    ogl_inicialized=1;

    return 1;
    }
//---------------------------------------------------------------------------
void TForm1::ogl_exit()
    {
    if (!ogl_inicialized) return;
    wglMakeCurrent(NULL, NULL);     // release current rendering context
    wglDeleteContext(hrc);          // destroy rendering context
    ogl_inicialized=0;
    }
//---------------------------------------------------------------------------
void TForm1::ogl_draw()
    {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    sky.draw();

    glFlush();
    SwapBuffers(hdc);
    }
//---------------------------------------------------------------------------
void TForm1::ogl_resize()
    {
    xs=ClientWidth;
    ys=ClientHeight;
    if (xs<=0) xs = 1;                  // Prevent a divide by zero
    if (ys<=0) ys = 1;
    if (!ogl_inicialized) return;
    glViewport(0,0,xs,ys);              // Set Viewport to window dimensions
    glMatrixMode(GL_PROJECTION);        // operacie s projekcnou maticou
    glLoadIdentity();                   // jednotkova matica projekcie
    gluPerspective(60,float(xs)/float(ys),0.1,100.0); // matica=perspektiva,120 stupnov premieta z viewsize do 0.1
    glMatrixMode(GL_TEXTURE);           // operacie s texturovou maticou
    glLoadIdentity();                   // jednotkova matica textury
    glMatrixMode(GL_MODELVIEW);         // operacie s modelovou maticou
    glLoadIdentity();                   // jednotkova matica modelu (objektu)
    ogl_draw();
    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
    {
    ogl_inicialized=0;
    hdc=NULL;
    hrc=NULL;
    ogl_init();
    sky.init();
    int i;  // unit matrices at start
    for (i=0;i<16;i++) rep[i]=0.0;
    for (i=0;i<16;i+=5) rep[i]=1.0;
    for (i=0;i<16;i++) inv[i]=rep[i];
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)   { ogl_exit(); }
void __fastcall TForm1::FormResize(TObject *Sender)    { ogl_resize(); }
void __fastcall TForm1::Splitter1Moved(TObject *Sender){ ogl_resize(); }
void __fastcall TForm1::FormPaint(TObject *Sender)     { ogl_draw(); }
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    GLfloat da=5.0; // angular turn speed in [deg/timer_iteration]
    pseudo_inverse(inv,rep);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadMatrixf(rep);
    bool _redraw=false;
    if (_left ) { _redraw=true; glRotatef(+da,0.0,1.0,0.0); }
    if (_right) { _redraw=true; glRotatef(-da,0.0,1.0,0.0); }
    if (_up   ) { _redraw=true; glRotatef(+da,1.0,0.0,0.0); }
    if (_down ) { _redraw=true; glRotatef(-da,1.0,0.0,0.0); }
    if (_reset) { _redraw=true; glLoadIdentity(); }
    if (_redraw)
        {
        glGetFloatv(GL_MODELVIEW_MATRIX,rep);
        pseudo_inverse(inv,rep);
        }
    glPopMatrix();
    if (_redraw) ogl_draw();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
    {
    if (Key==key_left ) _left =false;
    if (Key==key_right) _right=false;
    if (Key==key_up   ) _up   =false;
    if (Key==key_down ) _down =false;
    if (Key==key_reset) _reset=false;
    Key=0;  // key is handled
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
    {
    // on key down event
    if (Key==key_left ) _left =true;
    if (Key==key_right) _right=true;
    if (Key==key_up   ) _up   =true;
    if (Key==key_down ) _down =true;
    if (Key==key_reset) _reset=true;
    Key=0;  // key is handled
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormActivate(TObject *Sender)
    {
    _left =false; // clear key flags after focus change
    _right=false; // just to avoid constantly "pressed" keys
    _up   =false; // after window focus swaping during key press
    _down =false; // many games are ignoring this and you need to
    _reset=false; // press&release the stuck key again to stop movement ...
    }
//---------------------------------------------------------------------------

Here compiled Demo and full source with the textures included

Control is via keyboard arrows and space. Now it is just a matter of playing with colors,blend functions etc. Example does use only OpenGL 1.0 without extension (except the CLAMP_TO_EDGE).

You can exchange the multiple times rendering to single pass with MultiTexturing with the proper combination functions but I do not use that feature for a long time (as I switch to GLSL instead) so I am not confident to add a code for that.

Have fun.

这篇关于快速球体结合恒星数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆