/ / esfera rápida combina datos de estrellas: rápida, astronomía

esfera rápida combina datos de estrellas: rápida, astronomía

Quiero construir una aplicación de observación de estrellas. Y ahora ya construí una esfera y la cubrí con un mapa estelar (basado en coordenadas celestes). ( https://svs.gsfc.nasa.gov/cgi-bin/details.cgi?aid=3895 )

ahora tengo un archivo json que tiene el catálogo de estrellas de YBS. (también basado en coordenadas celestes). ( http://tdc-www.harvard.edu/catalogs/bsc5.html )

Quiero combinar los datos con el mapa estelar, deseandoel mapa para mostrar el nombre de Constellation cada vez que mi nodo de cámara gira hacia ese lugar. pero no sé cómo combinar datos y esfera, ya que la esfera girará debido a la latitud y el tiempo del usuario. Las coordenadas de los datos de la estrella también tienen que cambiar.

¿Alguien tiene sugerencias?

Respuestas

1 para la respuesta № 1

No estoy seguro en su entorno, pero en su caso yo haría:

  1. renderizar esfera texturizada (con el mapa profundo)

    La esfera debe estar centrada en la posición de su cámara y tener un radio grande que cubra toda el área de la vista. Para evitar parecer en regiones polares puede usar esto:

  2. luego renderice el BSC

    Comience con puntos (puntos). Sin embargo, si desea tener (des) zoom y, o mejor, visualizar la magnitud de las estrellas, entonces necesita capacidades de fusión y renderizar las estrellas como una cámara (vallas publicitarias) semitransparente con radio e intensidad que dependen del zoom y la magnitud.

    Usualmente uso esta textura para la estrella local (D = 1/3 de ancho, el resto es corona):

    estrella local

    Y esto para las estrellas BSC (D = casi 100% de ancho):

    estrella distante

    los alpha se calcula como intensidad de color alpha=r+g+b/3.

    De esta forma, los binarios físicos y visuales se combinarán.juntos sumando su magnitud visual como en la realidad. Esto también evitará el parpadeo durante cualquier cambio de vista debido al alias entre estrellas muy cercanas.

    Aquí la animación GIF de zoom (los colores se atenúan, por lo tanto, el ruido verdoso) para que sienta cómo se ve:

    zoom de estrella distante

[Editar1] ejemplo simple completo de VGL C ++ OpenGL

Yo uso los mapas profundos de su enlace. Se representan con distorsión esférica, por lo que la triangulación de Esfera no tiene ningún punto (no mejorará nada ya que los datos de origen ya están equivocados). Eso implica el uso de una malla esférica estándar con singularidades en los polos. los JPG los archivos son inutilizables debido a los artefactos de compresión con pérdida que estropean todo (especialmente cerca de los polos). Yo uso la TIF y reescalar todas las texturas a 4096x2048 resolución. Una resolución más baja no me parece correcta.

Después de esto, solo es cuestión de mezclar el skybox de la esfera con cada textura. El resultado es así:

visión general

Que muestra el área del polo norte para que pueda ver que las distorsiones no son tan malas (a menos que haga un zoom de grueso).

Después de esto, puede agregar las estrellas que no están presentes en el mapa profundo. Pero como el mapa profundo ya tiene BSC incluido No veo el punto de agregarlo nuevamente (a menos que desee calibrar su renderizador para que sea el mismo con el que se creó el mapa profundo).

Como se solicita aquí Ejemplo completo en C ++ / GL Fue escrito en BDS2006 por lo que se basa en la aplicación del formulario VCL consolo temporizador de 20 ms en él. Puede ignorar todas las cosas de VCL (lo único que se usa de él es el cargador de mapas de bits y estoy seguro de que ya tiene el suyo) y usar solo el código de evento que necesita.

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

Aquí compilado Demo y fuente completa con las texturas incluidas

El control es a través de las flechas del teclado y el espacio. Ahora es solo cuestión de jugar con colores, combinar funciones, etc. El ejemplo solo usa OpenGL 1.0 sin extensión (excepto el CLAMP_TO_EDGE)

Puede intercambiar el renderizado de múltiples veces en una sola pasada con MultiTexturing con las funciones de combinación adecuadas, pero no uso esa función durante mucho tiempo (cuando cambio a GLSL en cambio), así que no estoy seguro de agregar un código para eso.

Que te diviertas.