2016-10-21 2 views
0

Je veux construire une application d'observation des étoiles. Et maintenant j'ai déjà construit une sphère et la recouvre d'une carte d'étoiles (basée sur les coordonnées célestes). (https://svs.gsfc.nasa.gov/cgi-bin/details.cgi?aid=3895)swift sphere combiner des données d'étoile

maintenant j'ai un fichier json qui a le catalogue d'étoiles de YBS. (également basé sur les coordonnées célestes). Je veux combiner les données avec la carte stellaire, souhaitant que la carte affiche le nom de Constellation chaque fois que mon nœud de caméra tourne à cet endroit. mais je ne sais pas comment combiner les données et la sphère. puisque la sphère tournera en raison de la latitude et du temps de l'utilisateur. Les coordonnées des données de l'étoile doivent également changer.

Est-ce que quelqu'un a des suggestions?

+0

ajouté [Edit1] avec l'exemple GL demandé peut être il peut vous aider aussi – Spektre

Répondre

1

Je ne sais pas dans votre environnement, mais dans votre cas, je:

  1. render sphère texturé (avec la carte profonde)

    La sphère doit être centrée sur votre position de la caméra et ont de gros rayon couvrant toute la zone de vue. Pour éviter Semble dans les régions polaires, vous pouvez utiliser ceci:

  2. puis le BSC render

    Commencez par points (Points). Cependant, si vous voulez avoir (dé) zoomer et/ou mieux visualiser la magnitude des étoiles, vous avez besoin de capacités de mélange et de rendre les étoiles comme des disques semi-transparents avec des rayons et des intensités dépendant du zoom et de la magnitude.

    J'utilise généralement cette texture pour la star locale (D = 1/3 de la largeur, le repos est corona):

    local star

    Et ceci pour les étoiles BSC (D = largeur de près de 100%):

    distant star

    Le alpha est calculé comme l'intensité de la couleur alpha=r+g+b/3. De cette façon, les binaires visuels et physiques vont se fondre en ajoutant leur magnitude visuelle comme dans la réalité. Cela évitera également le scintillement lors d'un changement de vue dû à un aliasing entre des étoiles très proches.

    Ici animation GIF de zoom (les couleurs sont tramées par conséquent le bruit vert) si vous avez obtenu le sentiment à quoi ça ressemble:

    distant star zoom

[Edit1] simple et pleine VCL C++ OpenGL exemple J'utilise les cartes en profondeur à partir de votre lien.Ils sont rendus avec une distorsion sphérique donc la triangulation de Sphère n'a aucun point (n'améliorera rien car les données sources sont déjà fausses). Cela implique l'utilisation d'un maillage sphérique standard avec des singularités sur les pôles. Les fichiers JPG sont inutilisables en raison d'artefacts de compression avec perte qui gâchent tout (en particulier près des pôles). J'utilise le TIF et redimensionner toutes les textures à la résolution 4096x2048. Une résolution plus basse ne me semble pas juste. Après cela, il suffit de mélanger la sphère skybox avec chaque texture ensemble. Le résultat est comme ceci:

overview

Ce qui montre la zone pôle nord afin que vous puissiez voir les distorsions ne sont pas si mal que ça (sauf si vous effectuez un zoom de gros). Après cela, vous pouvez ajouter les étoiles qui ne sont pas présentes dans la carte profonde. Mais comme la carte profonde a déjà le BSC inclus, je ne vois pas l'intérêt de l'ajouter à nouveau (sauf si vous voulez calibrer votre rendu pour être le même que la carte profonde a été créée avec).

Comme l'a demandé ici Exemple complet dans C++/GL Il a été écrit dans BDS2006 il est basé sur l'application de formulaire VCL avec un seul 20ms minuterie sur elle. Vous pouvez ignorer toutes les choses VCL (la seule chose qui est utilisée est le chargeur bitmap et je suis sûr que vous avez déjà le vôtre) et utilisez uniquement le code d'événement dont vous avez besoin.

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

compilé ici la source de démonstration et complète avec les textures inclus

contrôle se fait par les flèches du clavier et de l'espace. Maintenant, il s'agit juste de jouer avec les couleurs, de fusionner les fonctions, etc. L'exemple n'utilise que OpenGL 1.0 sans extension (sauf le CLAMP_TO_EDGE).

Vous pouvez échanger les multiples temps de rendu à une seule passe avec multitexturing avec les fonctions de bonne combinaison mais je ne pas utiliser cette fonction depuis longtemps (comme je passe à GLSL à la place), donc je ne suis pas sûr d'ajouter une code pour cela.

Amusez-vous.

+0

@Unheilig si vous êtes intéressé jeter un oeil à la 3 derniers liens ici [Est-il possible de faire réaliste simulation de système solaire à n corps dans la matière de la taille et de la masse?] (http://stackoverflow.com/a/28020934/2521214) en particulier le ** Les Couleurs des Etoiles ** – Spektre

+0

Ainsi, ici je suis avec mes questions: '1': pourquoi avez-vous utilisé 'GL_CLAMP_TO_EDGE 0x812F'? '2': pour la partie qui génère le maillage, pouvez-vous en dire plus sur' ... = r * x; .. = r * y; r * z; .. = tx0 + (a * tdx); .. = (b * tdy); 'mathématiquement, et enfin la partie suivante où vous scannez dans le bmp:' c.c32 = pp [x]; q = c.db [2]; c.db [2] = c.db [0]; c.db [0] = q; txr [adr] = c.c32; '? De plus, où sont tes shaders? Merci. – Unheilig

+0

@Unheilig # 1 Pour garder cela simple et ne pas avoir besoin de choses supplémentaires, j'ai utilisé seulement OpenGL 1.0 donc pas de shaders pas d'extensions. La seule extension utilisée est 'GL_CLAMP_TO_EDGE' qui mappe les coordonnées de texture à la plage' <0,1> 'au lieu de' (0,1) '. Comme je n'ai pas utilisé de chargeur d'extension comme GLEW et que cette extension est présente sur tous les HW capable de GL, je devais définir la valeur ...Je pourrais également utiliser 'const GLuint' innstead si vous avez un chargeur d'extension alors vous n'avez pas besoin de le définir du tout. # 3 pour les mêmes raisons que je n'ai pas utilisé de shaders au lieu de pipeline fixe est utilisé. – Spektre