/ / Swift Sfera łączy dane gwiazd - Swift, astronomia

swift sphere łączy dane gwiazdowe - swift, astronomia

chcę zbudować aplikację do obserwacji gwiazd. A teraz zbudowałem już kulę i pokryłem ją mapą nieba (opartą na współrzędnych niebieskich). ( https://svs.gsfc.nasa.gov/cgi-bin/details.cgi?aid=3895 )

teraz mam plik json, który zawiera katalog gwiazd z YBS. (również na podstawie współrzędnych niebieskich). ( http://tdc-www.harvard.edu/catalogs/bsc5.html )

chcę połączyć dane z mapą gwiazd, życzęmapę, aby pokazać nazwę Constellation za każdym razem, gdy mój węzeł kamery zwróci się w to miejsce. ale nie wiem, jak łączyć dane i sferę.Ponieważ sfera będzie się obracać ze względu na szerokość i czas użytkownika. Współrzędne danych gwiazdy również muszą się zmienić.

Czy ktoś ma jakieś sugestie?

Odpowiedzi:

1 dla odpowiedzi № 1

Nie jestem pewien w Twoim środowisku, ale w Twoim przypadku chciałbym:

  1. renderuj sferę teksturowaną (z głęboką mapą)

    Kula musi być wyśrodkowana w pozycji kamery i mieć duży promień obejmujący cały obszar widzenia. Aby uniknąć pozorów w regionach polarnych, możesz użyć tego:

  2. następnie wyrenderuj BSC

    Zacznij od kropek (punktów).Jednakże, jeśli chcesz (nie)zoomować i lub lepiej zwizualizować jasność gwiazd, potrzebujesz możliwości mieszania i renderowania gwiazd jako półprzezroczystej kamery skierowanej do tarczy (bilbordy) z promieniem i intensywnością zależną od zoomu i jasności.

    Zwykle używam tej tekstury dla gwiazdy lokalnej (D=1/3 szerokości, reszta to korona):

    lokalna gwiazda

    A to dla gwiazd BSC (D = prawie 100% szerokości):

    odległa gwiazda

    The alpha jest obliczana jako intensywność koloru alpha=r+g+b/3.

    W ten sposób wizualne i fizyczne pliki binarne połączą sięrazem dodając ich wizualną wielkość jak w rzeczywistości. Pozwoli to również uniknąć migotania podczas jakiejkolwiek zmiany widoku z powodu aliasingu między bardzo bliskimi gwiazdami.

    Tutaj animacja GIF powiększenia (kolory są rozmyte, stąd zielonkawy szum), więc masz wrażenie, jak to wygląda:

    odległa gwiazda zoom

[Edycja1] prosty pełny przykład VCL C++ OpenGL

Korzystam z głębokich map z twojego linku.Są one renderowane z zniekształceniem sferycznym, więc triangulacja Sphere nie ma sensu (nie poprawi niczego, ponieważ dane źródłowe są już błędne). Oznacza to użycie standardowej siatki sferycznej z osobliwościami na biegunach. JPG pliki są bezużyteczne z powodu stratnych artefaktów kompresji, które wszystko psują (szczególnie w pobliżu biegunów). używam TIF i przeskaluj wszystkie tekstury do 4096x2048 rozkład. Niższa rozdzielczość nie wydaje mi się odpowiednia.

Potem jest już tylko kwestia zmieszania sferycznego skyboxa z każdą teksturą. Wynik jest taki:

Przegląd

Który pokazuje obszar bieguna północnego, dzięki czemu można zobaczyć, że zniekształcenia nie są takie złe (chyba że przybliżasz zgrubne).

Następnie możesz dodać gwiazdy, których nie ma na głębokiej mapie. Ale ponieważ głęboka mapa ma już BSC w tym nie widzę sensu dodawania go ponownie (chyba że chcesz skalibrować swój renderer, aby był taki sam, jak utworzono głęboką mapę).

Zgodnie z prośbą tutaj Kompletny przykład w C++/GL Został napisany w BDS2006 więc opiera się na aplikacji VCL Form zpojedynczy 20ms Timer na nim. Możesz zignorować wszystkie rzeczy VCL (jedyną rzeczą, która jest używana, ponieważ jest to loader bitmap i jestem pewien, że masz już swój) i używaj tylko kodu zdarzenia, którego potrzebujesz.

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

Tutaj skompilowane Demo i pełne źródła z dołączonymi teksturami

Sterowanie odbywa się za pomocą strzałek na klawiaturze i spacji. Teraz to tylko kwestia zabawy kolorami, funkcjami mieszania itp. Przykład używa tylko OpenGL 1.0 bez rozszerzenia (z wyjątkiem CLAMP_TO_EDGE).

Możesz zamienić wielokrotne renderowanie na jednoprzebiegowe z MultiTexturing z odpowiednimi funkcjami kombinacji, ale nie używam tej funkcji przez długi czas (ponieważ przełączam się na GLSL zamiast tego), więc nie jestem pewien, czy dodać kod do tego.

Baw się dobrze.