2016-10-21 3 views
0

Ich mag eine stargazing App bauen. Und jetzt habe ich bereits eine Kugel gebaut und bedecke sie mit einer Sternkarte (basierend auf Himmelskoordinaten). (https://svs.gsfc.nasa.gov/cgi-bin/details.cgi?aid=3895)schnelle Kugel kombiniert Stern Daten

jetzt habe ich eine JSON-Datei, die den Sternkatalog von YBS hat. (auch basierend auf Himmelskoordinaten).

Ich möchte die Daten mit einer Sternkarte kombinieren und möchte, dass die Karte den Namen Constellation anzeigt, wenn sich mein Kameraknoten an diesen Ort wendet. aber ich weiß nicht, wie man Daten und Sphäre kombiniert. da die Kugel sich aufgrund des Breitengrades und der Zeit des Benutzers dreht. Die Koordinaten der Sterndaten müssen sich ebenfalls ändern.

Hat jemand Vorschläge hat?

+0

hinzugefügt [Edit1] mit angeforderten GL Beispiel kann es kann Ihnen auch helfen – Spektre

Antwort

1

Nicht sicher in Ihrer Umgebung, aber in Ihrem Fall würde ich:

  1. texturierten Kugel machen (mit der tiefen Karte)

    Die Kugel muss in der Kameraposition zentriert werden und haben große Radius, der den gesamten Sichtbereich abdeckt. scheint in den Polarregionen vermeiden Sie diese verwenden können:

  2. machen dann die BSC

    beginnen mit Punkten (Punkte). Wie auch immer, wenn Sie (un) Zoom haben wollen und oder besser die Größe der Sterne sichtbar machen, dann müssen Sie Blending-Funktionen und machen die Sterne als halbtransparente Scheibe gerichtete Kamera (Plakatwänden) mit Radius und Intensität abhängig von Zoom und Größe.

    ich in der Regel diese Textur für lokalen Stern verwende (D = 03.01 Breite, Rest ist Korona):

    local star

    Und dies für die BSC-Sterne (D = 100% Breite):

    distant star

    Die alpha wird als Farbintensität alpha=r+g+b/3 berechnet.

    Auf diese Weise visuelle und physische Binärdateien mischen zusammen, um ihre visuelle Helligkeit wie in der Realität hinzuzufügen. Dies verhindert auch das Flackern während einer Änderung der Ansicht aufgrund von Aliasing zwischen sehr nahen Sternen.

    Hier GIF-Animation von Zoom (Farben sind daher die grünlich Rauschen Dithering), so dass Sie bekam das Gefühl, wie es aussieht:

    distant star zoom

[Edit1] einfach voll VCL C++ OpenGL Beispiel

ich die tiefen Karten von Ihrem Link.Sie werden mit sphärischer Verzerrung gerendert, daher hat die Sphere-Triangulation keinen Sinn (wird nichts verbessern, da die Quelldaten bereits falsch sind). Dies beinhaltet die Verwendung von Standard-Kugelmaschen mit Singularitäten an Polen. Die JPG Dateien sind aufgrund verlustreicher Kompressionsartefakte unbrauchbar, die alles kaputt machen (besonders in der Nähe von Polen). Ich verwende die TIF und rescale alle Texturen auf 4096x2048 Auflösung. Niedrigere Auflösung fühlt sich nicht richtig an.

Danach ist es nur eine Frage der Mischung der Sphäre skybox mit jeder Textur zusammen. Das Ergebnis ist wie folgt aus:

overview

Welche zeigt Bereich Nordpol, so dass Sie die Verzerrungen sehen können, sind nicht so schlecht (es sei denn, Sie von groben zoom).

Danach können Sie die Sterne hinzufügen, die nicht in der tiefen Karte vorhanden sind. Aber da die tiefe Karte bereits die BSC enthalten hat, sehe ich keinen Sinn, sie wieder hinzuzufügen (es sei denn, Sie möchten Ihren Renderer so kalibrieren, dass er derselbe ist, mit dem die tiefe Karte erstellt wurde).

Wie hier Komplettes Beispiel angefordert in C++/GL Es wurde geschrieben in BDS2006 so ist es auf VCL-Formularanwendung mit einzelnen 20ms Timer drauf. Sie können alle VCL-Sachen ignorieren (das Einzige, was verwendet wird, ist Bitmap-Loader und ich bin zuversichtlich, dass Sie schon Ihr haben) und verwenden nur den von Ihnen benötigten Event-Code.

//--------------------------------------------------------------------------- 
#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 ... 
    } 
//--------------------------------------------------------------------------- 

Hier zusammengestellt Demo und Voll Quelle mit den Texturen enthalten

Die Steuerung erfolgt über Tastatur Pfeile und Raum. Jetzt ist es nur eine Frage des Spielens mit Farben, Mischfunktionen usw. Beispiel verwendet nur OpenGL 1.0 ohne Erweiterung (außer CLAMP_TO_EDGE).

Sie können die mehrfach austauschen zu Single-Pass-Rendering mit Multitexturing mit den richtigen Kombination Funktionen, aber ich nicht, dass die Funktion für eine lange Zeit (wie ich zu GLSL wechseln statt), so bin ich nicht sicher, ein hinzufügen Code dafür.

Viel Spaß.

+0

@Unheilig btw wenn youre interessiert werfen Sie einen Blick auf die letzten 3 Links hier [Ist es möglich, realistische N-Körper-Solarsystem-Simulation in Materie von Größe und Masse?] (http://stackoverflow.com/a/28020934/2521214) besonders die ** Die Farben der Sterne ** – Spektre

+0

So, hier bin ich mit meinen Fragen: '1': warum hast du benutzt 'GL_CLAMP_TO_EDGE 0x812F'? '2': Können Sie für den Teil, der das Netz erzeugt, mehr über' ... = r * x; .. = r * y; r * z; .. = tx0 + (a * tdx); .. = (b * tdy); 'mathematisch, und schließlich der folgende Teil, wo Sie in der BMP einlesen:' c.c32 = pp [x]; q = c.db [2]; c.db [2] = c.db [0]; c.db [0] = q; txr [adr] = c.c32; '? Wo sind deine Shader? Vielen Dank. – Unheilig

+0

@Unheilig # 1 Um das einfach zu halten und keine zusätzlichen Sachen zu benötigen, habe ich nur OpenGL 1.0 benutzt, also keine Shader, keine Erweiterungen. Die einzige Erweiterung ist 'GL_CLAMP_TO_EDGE', die Texturkoordinaten in den Bereich' <0,1> 'anstatt' (0,1) 'abbildet. Da ich keinen Extension Loader wie GLEW benutzt habe und diese Erweiterung auf allen GL fähigen HW vorhanden ist, musste ich den Wert definieren ...Ich könnte auch "const GLuint" verwenden, wenn Sie Extension Loader haben, dann müssen Sie es überhaupt nicht definieren. # 3 Aus den gleichen Gründen habe ich keine Shader verwendet, stattdessen wurde eine feste Pipeline verwendet. – Spektre