Kstars

skyglpainter.cpp
1/*
2 SPDX-FileCopyrightText: 2010 Henry de Valence <hdevalence@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#ifdef _WIN32
8#include <windows.h>
9#endif
10#include "skyglpainter.h"
11
12#include <cstddef>
13#include <Eigen/Geometry>
14
15#include <GL/gl.h>
16#include <QGLWidget>
17
18#include "skymap.h"
19#include "kstarsdata.h"
20#include "Options.h"
21
22#include "texturemanager.h"
23
24#include "skycomponents/linelist.h"
25#include "skycomponents/skiphashlist.h"
26#include "skycomponents/linelistlabel.h"
27#include "skycomponents/skymapcomposite.h"
28#include "skycomponents/flagcomponent.h"
29#include "skycomponents/satellitescomponent.h"
30#include "skycomponents/supernovaecomponent.h"
31#include "skycomponents/constellationartcomponent.h"
32#include "skyobjects/kscomet.h"
33#include "skyobjects/ksasteroid.h"
34#include "skyobjects/trailobject.h"
35#include "skyobjects/satellite.h"
36#include "skyobjects/supernova.h"
37#include "skyobjects/constellationsart.h"
38
39Eigen::Vector2f SkyGLPainter::m_vertex[NUMTYPES][6 * BUFSIZE];
40Eigen::Vector2f SkyGLPainter::m_texcoord[NUMTYPES][6 * BUFSIZE];
41Eigen::Vector3f SkyGLPainter::m_color[NUMTYPES][6 * BUFSIZE];
42int SkyGLPainter::m_idx[NUMTYPES];
43bool SkyGLPainter::m_init = false;
44
45SkyGLPainter::SkyGLPainter(QGLWidget *widget) : SkyPainter()
46{
47 m_widget = widget;
48 if (!m_init)
49 {
50 qDebug() << "Initializing texcoord arrays...\n";
51 for (int i = 0; i < NUMTYPES; ++i)
52 {
53 m_idx[i] = 0;
54 for (int j = 0; j < BUFSIZE; ++j)
55 {
56 m_texcoord[i][6 * j + 0] = Eigen::Vector2f(0, 0);
57 m_texcoord[i][6 * j + 1] = Eigen::Vector2f(1, 0);
58 m_texcoord[i][6 * j + 2] = Eigen::Vector2f(0, 1);
59 m_texcoord[i][6 * j + 3] = Eigen::Vector2f(0, 1);
60 m_texcoord[i][6 * j + 4] = Eigen::Vector2f(1, 0);
61 m_texcoord[i][6 * j + 5] = Eigen::Vector2f(1, 1);
62 }
63 }
64 //Generate textures that were loaded before the SkyMap was
65 m_init = true;
66 }
67}
68
69void SkyGLPainter::drawBuffer(int type)
70{
71 // Prevent crash if type > UNKNOWN
72 if (type > SkyObject::TYPE_UNKNOWN)
73 type = SkyObject::TYPE_UNKNOWN;
74
75 //printf("Drawing buffer for type %d, has %d objects\n", type, m_idx[type]);
76 if (m_idx[type] == 0)
77 return;
78
79 glEnable(GL_TEXTURE_2D);
80 switch (type)
81 {
82 case 3:
83 case 13:
84 TextureManager::bindTexture("open-cluster", m_widget);
85 break;
86 case 4:
87 TextureManager::bindTexture("globular-cluster", m_widget);
88 break;
89 case 6:
90 TextureManager::bindTexture("planetary-nebula", m_widget);
91 break;
92 case 5:
93 case 7:
94 case 15:
95 TextureManager::bindTexture("gaseous-nebula", m_widget);
96 break;
97 case 8:
98 case 16:
99 TextureManager::bindTexture("galaxy", m_widget);
100 break;
101 case 14:
102 TextureManager::bindTexture("galaxy-cluster", m_widget);
103 break;
104 case 0:
105 case 1:
106 default:
107 TextureManager::bindTexture("star", m_widget);
108 break;
109 }
110
111 glEnable(GL_BLEND);
112 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
113 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
114 glEnableClientState(GL_VERTEX_ARRAY);
115 glEnableClientState(GL_COLOR_ARRAY);
116 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
117
118 glVertexPointer(2, GL_FLOAT, 0, &m_vertex[type]);
119 glTexCoordPointer(2, GL_FLOAT, 0, &m_texcoord[type]);
120 glColorPointer(3, GL_FLOAT, 0, &m_color[type]);
121
122 glDrawArrays(GL_TRIANGLES, 0, 6 * m_idx[type]);
123 m_idx[type] = 0;
124
125 glDisableClientState(GL_VERTEX_ARRAY);
126 glDisableClientState(GL_COLOR_ARRAY);
127 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
128}
129
130bool SkyGLPainter::addItem(SkyPoint *p, int type, float width, char sp)
131{
132 bool visible = false;
133 Eigen::Vector2f vec = m_proj->toScreenVec(p, true, &visible);
134 if (!visible)
135 return false;
136
137 // Prevent crash if type > UNKNOWN
138 if (type > SkyObject::TYPE_UNKNOWN)
139 type = SkyObject::TYPE_UNKNOWN;
140
141 //If the buffer is full, flush it
142 if (m_idx[type] == BUFSIZE)
143 {
144 drawBuffer(type);
145 }
146
147 int i = 6 * m_idx[type];
148 float w = width / 2.;
149
150 m_vertex[type][i + 0] = vec + Eigen::Vector2f(-w, -w);
151 m_vertex[type][i + 1] = vec + Eigen::Vector2f(w, -w);
152 m_vertex[type][i + 2] = vec + Eigen::Vector2f(-w, w);
153 m_vertex[type][i + 3] = vec + Eigen::Vector2f(-w, w);
154 m_vertex[type][i + 4] = vec + Eigen::Vector2f(w, -w);
155 m_vertex[type][i + 5] = vec + Eigen::Vector2f(w, w);
156
157 Eigen::Vector3f c(1., 1., 1.);
158 if (sp != 'x' && Options::starColorMode() != 0)
159 {
160 // We have a star and aren't drawing real star colors
161 switch (Options::starColorMode())
162 {
163 case 1: // solid red
164 c = Eigen::Vector3f(255. / 255., 0., 0.);
165 break;
166 case 2: // solid black
167 c = Eigen::Vector3f(0., 0., 0.);
168 break;
169 case 3: // Solid white
170 c = Eigen::Vector3f(1., 1., 1.);
171 break;
172 }
173 }
174 else
175 {
176 QColor starColor;
177
178 // Set RGB values into QColor
179 switch (sp)
180 {
181 case 'o':
182 case 'O':
183 starColor.setRgb(153, 153, 255);
184 break;
185 case 'b':
186 case 'B':
187 starColor.setRgb(151, 233, 255);
188 break;
189 case 'a':
190 case 'A':
191 starColor.setRgb(153, 255, 255);
192 break;
193 case 'f':
194 case 'F':
195 starColor.setRgb(219, 255, 135);
196 break;
197 case 'g':
198 case 'G':
199 starColor.setRgb(255, 255, 153);
200 break;
201 case 'k':
202 case 'K':
203 starColor.setRgb(255, 193, 153);
204 break;
205 case 'm':
206 case 'M':
207 starColor.setRgb(255, 153, 153);
208 break;
209 case 'x':
210 starColor.setRgb(m_pen[0] * 255, m_pen[1] * 255, m_pen[2] * 255);
211 break;
212 default:
213 starColor.setRgb(153, 255, 255);
214 break; // If we don't know what spectral type, we use the same as 'A' (See SkyQPainter)
215 }
216
217 // Convert to HSV space using QColor's methods and adjust saturation.
218 int h, s, v;
219 starColor.getHsv(&h, &s, &v);
220 s = (Options::starColorIntensity() / 10.) *
221 200.; // Rewrite the saturation based on the star color intensity setting, 200 is the hard-wired max saturation, just to approximately match up with QPainter mode.
222 starColor.setHsv(h, s, v);
223
224 // Get RGB ratios and put them in 'c'
225 c = Eigen::Vector3f(starColor.redF(), starColor.greenF(), starColor.blueF());
226 }
227 for (int j = 0; j < 6; ++j)
228 {
229 m_color[type][i + j] = c;
230 }
231
232 ++m_idx[type];
233 return true;
234}
235
236void SkyGLPainter::drawTexturedRectangle(const QImage &img, const Eigen::Vector2f &pos, const float angle, const float sizeX,
237 const float sizeY)
238{
239 // Set up texture
240 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
241 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
242 glEnable(GL_TEXTURE_2D);
243 TextureManager::bindFromImage(img, m_widget);
244
245 // Render rectangle
246 glPushMatrix();
247 glTranslatef(pos.x(), pos.y(), 0);
248 glRotatef(angle, 0, 0, 1);
249 glScalef(sizeX, sizeY, 1);
250
251 glBegin(GL_QUADS);
252 // Note! Y coordinate of texture is mirrored w.r.t. to
253 // vertex coordinates to account for difference between
254 // OpenGL and QPainter coordinate system.
255 // Otherwise image would appear mirrored
256 glTexCoord2f(0, 1);
257 glVertex2f(-0.5, -0.5);
258
259 glTexCoord2f(1, 1);
260 glVertex2f(0.5, -0.5);
261
262 glTexCoord2f(1, 0);
263 glVertex2f(0.5, 0.5);
264
265 glTexCoord2f(0, 0);
266 glVertex2f(-0.5, 0.5);
267 glEnd();
268
269 glPopMatrix();
270}
271
272bool SkyGLPainter::drawPlanet(KSPlanetBase *planet)
273{
274 //If it's surely not visible, just stop now
275 if (!m_proj->checkVisibility(planet))
276 return false;
277
278 float zoom = Options::zoomFactor();
279 float fakeStarSize = (10.0 + log10(zoom) - log10(MINZOOM)) * (10 - planet->mag()) / 10;
280 fakeStarSize = qMin(fakeStarSize, 20.f);
281
282 float size = planet->angSize() * dms::PI * zoom / 10800.0;
283 if (size < fakeStarSize || planet->image().isNull())
284 {
285 // Draw them as bright stars of appropriate color instead of images
286 char spType;
287 //FIXME: do these need i18n?
288 if (planet->name() == xi18n("Sun"))
289 {
290 spType = 'G';
291 }
292 else if (planet->name() == xi18n("Mars"))
293 {
294 spType = 'K';
295 }
296 else if (planet->name() == xi18n("Jupiter") || planet->name() == xi18n("Mercury") ||
297 planet->name() == xi18n("Saturn"))
298 {
299 spType = 'F';
300 }
301 else
302 {
303 spType = 'B';
304 }
305 return addItem(planet, planet->type(), qMin(fakeStarSize, (float)20.), spType);
306 }
307 else
308 {
309 // Draw them as textures
310 bool visible = false;
311 Eigen::Vector2f pos = m_proj->toScreenVec(planet, true, &visible);
312 if (!visible)
313 return false;
314
315 //Because Saturn has rings, we inflate its image size by a factor 2.5
316 if (planet->name() == "Saturn")
317 size *= 2.5;
318
319 drawTexturedRectangle(planet->image(), pos, m_proj->findPA(planet, pos.x(), pos.y()), size, size);
320 return true;
321 }
322}
323
324bool SkyGLPainter::drawPointSource(const SkyPoint *loc, float mag, char sp)
325{
326 //If it's surely not visible, just stop now
327 if (!m_proj->checkVisibility(loc))
328 return false;
329 return addItem(loc, SkyObject::STAR, starWidth(mag), sp);
330}
331
332void SkyGLPainter::drawSkyPolygon(LineList *list)
333{
334 SkyList *points = list->points();
335 bool isVisible, isVisibleLast;
336 SkyPoint *pLast = points->last();
337 Eigen::Vector2f oLast = m_proj->toScreenVec(pLast, true, &isVisibleLast);
338 // & with the result of checkVisibility to clip away things below horizon
339 isVisibleLast &= m_proj->checkVisibility(pLast);
340
341 //Guess that we will require around the same number of items as in points.
343 polygon.reserve(points->size());
344 for (int i = 0; i < points->size(); ++i)
345 {
346 SkyPoint *pThis = points->at(i);
347 Eigen::Vector2f oThis = m_proj->toScreenVec(pThis, true, &isVisible);
348 // & with the result of checkVisibility to clip away things below horizon
349 isVisible &= m_proj->checkVisibility(pThis);
350
351 if (isVisible && isVisibleLast)
352 {
353 polygon << oThis;
354 }
355 else if (isVisibleLast)
356 {
357 Eigen::Vector2f oMid = m_proj->clipLineVec(pLast, pThis);
358 polygon << oMid;
359 }
360 else if (isVisible)
361 {
362 Eigen::Vector2f oMid = m_proj->clipLineVec(pThis, pLast);
363 polygon << oMid;
364 polygon << oThis;
365 }
366
367 pLast = pThis;
368 oLast = oThis;
369 isVisibleLast = isVisible;
370 }
371
372// false -> makes kstars slower but is always accurate
373// true -> faster but potentially results in incorrect rendering
374#define KSTARS_ASSUME_CONVEXITY false
375 if (polygon.size())
376 {
377 drawPolygon(polygon, KSTARS_ASSUME_CONVEXITY);
378 }
379}
380
381void SkyGLPainter::drawPolygon(const QVector<Eigen::Vector2f> &polygon, bool convex, bool flush_buffers)
382{
383 //Flush all buffers
384 if (flush_buffers)
385 {
386 for (int i = 0; i < NUMTYPES; ++i)
387 {
388 drawBuffer(i);
389 }
390 }
391 glDisable(GL_TEXTURE_2D);
392 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
393 if (!convex)
394 {
395 //Set up the stencil buffer and disable the color buffer
396 glClear(GL_STENCIL_BUFFER_BIT);
397 glColorMask(0, 0, 0, 0);
398 glEnable(GL_STENCIL_TEST);
399 glStencilFunc(GL_ALWAYS, 0, 0);
400 glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
401 //Now draw a triangle fan. Because of the GL_INVERT,
402 //this will fill the stencil buffer with odd-even fill.
403 glEnableClientState(GL_VERTEX_ARRAY);
404 glVertexPointer(2, GL_FLOAT, 0, polygon.data());
405 glDrawArrays(GL_TRIANGLE_FAN, 0, polygon.size());
406 glDisableClientState(GL_VERTEX_ARRAY);
407
408 //Now draw the stencil:
409 glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff);
410 glColorMask(1, 1, 1, 1);
411 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
412 glBegin(GL_QUADS);
413 glVertex2f(0, 0);
414 glVertex2f(0, m_widget->height());
415 glVertex2f(m_widget->width(), m_widget->height());
416 glVertex2f(m_widget->width(), 0);
417 glEnd();
418 glDisable(GL_STENCIL_TEST);
419 }
420 else
421 {
422 glEnableClientState(GL_VERTEX_ARRAY);
423 glVertexPointer(2, GL_FLOAT, 0, polygon.data());
424 glDrawArrays(GL_POLYGON, 0, polygon.size());
425 glDisableClientState(GL_VERTEX_ARRAY);
426 }
427}
428
429void SkyGLPainter::drawHorizon(bool filled, SkyPoint *labelPoint, bool *drawLabel)
430{
431 QVector<Eigen::Vector2f> ground = m_proj->groundPoly(labelPoint, drawLabel);
432
433 if (ground.size())
434 {
435 if (filled)
436 {
437 glDisableClientState(GL_COLOR_ARRAY);
438 drawPolygon(ground, false, false);
439 }
440 else
441 {
442 glDisable(GL_TEXTURE_2D);
443 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
444 glEnableClientState(GL_VERTEX_ARRAY);
445 glVertexPointer(2, GL_FLOAT, 0, ground.data());
446 glDrawArrays(GL_LINE_LOOP, 0, ground.size());
447 glDisableClientState(GL_VERTEX_ARRAY);
448 }
449 }
450}
451
452//This implementation is *correct* but slow.
453void SkyGLPainter::drawSkyPolyline(LineList *list, SkipHashList *skipList, LineListLabel *label)
454{
455 glDisable(GL_TEXTURE_2D);
456 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
457 glBegin(GL_LINE_STRIP);
458 SkyList *points = list->points();
459 bool isVisible, isVisibleLast;
460 Eigen::Vector2f oLast = m_proj->toScreenVec(points->first(), true, &isVisibleLast);
461 // & with the result of checkVisibility to clip away things below horizon
462 isVisibleLast &= m_proj->checkVisibility(points->first());
463 if (isVisibleLast)
464 {
465 glVertex2fv(oLast.data());
466 }
467
468 for (int i = 1; i < points->size(); ++i)
469 {
470 Eigen::Vector2f oThis = m_proj->toScreenVec(points->at(i), true, &isVisible);
471 // & with the result of checkVisibility to clip away things below horizon
472 isVisible &= m_proj->checkVisibility(points->at(i));
473
474 bool doSkip = (skipList ? skipList->skip(i) : false);
475 //This tells us whether we need to end the current line or whether we
476 //are to keep drawing into it. If we skip, then we are going to have to end.
477 bool shouldEnd = doSkip;
478
479 if (!doSkip)
480 {
481 if (isVisible && isVisibleLast)
482 {
483 glVertex2fv(oThis.data());
484 if (label)
485 {
486 label->updateLabelCandidates(oThis.x(), oThis.y(), list, i);
487 }
488 }
489 else if (isVisibleLast)
490 {
491 Eigen::Vector2f oMid = m_proj->clipLineVec(points->at(i - 1), points->at(i));
492 glVertex2fv(oMid.data());
493 //If the last point was visible but this one isn't we are at
494 //the end of a strip, so we need to end
495 shouldEnd = true;
496 }
497 else if (isVisible)
498 {
499 Eigen::Vector2f oMid = m_proj->clipLineVec(points->at(i), points->at(i - 1));
500 glVertex2fv(oMid.data());
501 glVertex2fv(oThis.data());
502 }
503 }
504
505 if (shouldEnd)
506 {
507 glEnd();
508 glBegin(GL_LINE_STRIP);
509 if (isVisible)
510 {
511 glVertex2fv(oThis.data());
512 }
513 }
514
515 isVisibleLast = isVisible;
516 }
517 glEnd();
518}
519
520//FIXME: implement these two
521
522void SkyGLPainter::drawObservingList(const QList<SkyObject *> &obs)
523{
524 // TODO: Generalize to drawTargetList or something like that. Make
525 // texture changeable etc.
526 // TODO: Draw labels when required
527
528 foreach (SkyObject *obj, obs)
529 {
530 if (!m_proj->checkVisibility(obj))
531 continue;
532 bool visible;
533 Eigen::Vector2f vec = m_proj->toScreenVec(obj, true, &visible);
534 if (!visible || !m_proj->onScreen(vec))
535 continue;
536 const float size = 30.;
537 QImage obsmarker = TextureManager::getImage("obslistsymbol");
538 drawTexturedRectangle(obsmarker, vec, 0, size, size);
539 }
540}
541
542void SkyGLPainter::drawFlags()
543{
544 KStarsData *data = KStarsData::Instance();
545 SkyPoint *point;
546 QImage image;
547 const QString label;
548 bool visible = false;
549 Eigen::Vector2f vec;
550 int i;
551
552 for (i = 0; i < data->skyComposite()->flags()->size(); i++)
553 {
554 point = data->skyComposite()->flags()->pointList().at(i);
555 image = data->skyComposite()->flags()->image(i);
556
557 // Set Horizontal coordinates
558 point->EquatorialToHorizontal(data->lst(), data->geo()->lat());
559
560 // Get flag position on screen
561 vec = m_proj->toScreenVec(point, true, &visible);
562
563 // Return if flag is not visible
564 if (!visible || !m_proj->onScreen(vec))
565 continue;
566
567 const QImage &img =
568 data->skyComposite()->flags()->imageName(i) == "Default" ? TextureManager::getImage("defaultflag") : image;
569
570 drawTexturedRectangle(img, vec, 0, img.width(), img.height());
571 drawText(vec.x(), vec.y(), data->skyComposite()->flags()->label(i), QFont("Courier New", 10, QFont::Bold),
572 data->skyComposite()->flags()->labelColor(i));
573 }
574}
575
576void SkyGLPainter::drawText(int x, int y, const QString text, QFont font, QColor color)
577{
578 // Return if text is empty
579 if (text.isEmpty())
580 return;
581
582 int longest, tex_size = 2;
583
584 // Get size of text
585 QFontMetrics fm(font);
586 const QRect bounding_rect = fm.boundingRect(text);
587
588 // Compute texture size
589 if (bounding_rect.width() > bounding_rect.height())
590 longest = bounding_rect.width();
591 else
592 longest = bounding_rect.height();
593
594 while (tex_size < longest)
595 {
596 tex_size *= 2;
597 }
598
599 // Create image of text
600 QImage text_image(tex_size, tex_size, QImage::Format_ARGB32);
601 text_image.fill(Qt::transparent);
602 QPainter p(&text_image);
603 p.setFont(font);
604 p.setPen(color);
605 p.drawText(0, tex_size / 2, text);
606 p.end();
607
608 // Create texture
609 float w = text_image.width();
610 float h = text_image.height();
611 float vx = x + 0.5 * w + 10;
612 float vy = y - 10;
613 drawTexturedRectangle(text_image, Eigen::Vector2f(vx, vy), 0, w, h);
614}
615
616bool SkyGLPainter::drawConstellationArtImage(ConstellationsArt *obj)
617{
618}
619
620void SkyGLPainter::drawSkyLine(SkyPoint *a, SkyPoint *b)
621{
622 bool aVisible, bVisible;
623 Eigen::Vector2f aScreen = m_proj->toScreenVec(a, true, &aVisible);
624 Eigen::Vector2f bScreen = m_proj->toScreenVec(b, true, &bVisible);
625
626 glDisable(GL_TEXTURE_2D);
627 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
628 glBegin(GL_LINE_STRIP);
629
630 //THREE CASES:
631 if (aVisible && bVisible)
632 {
633 //Both a,b visible, so paint the line normally:
634 glVertex2fv(aScreen.data());
635 glVertex2fv(bScreen.data());
636 }
637 else if (aVisible)
638 {
639 //a is visible but b isn't:
640 glVertex2fv(aScreen.data());
641 glVertex2fv(m_proj->clipLineVec(a, b).data());
642 }
643 else if (bVisible)
644 {
645 //b is visible but a isn't:
646 glVertex2fv(bScreen.data());
647 glVertex2fv(m_proj->clipLineVec(b, a).data());
648 } //FIXME: what if both are offscreen but the line isn't?
649
650 glEnd();
651}
652
653void SkyGLPainter::drawSkyBackground()
654{
655 glDisable(GL_TEXTURE_2D);
656 QColor bg = KStarsData::Instance()->colorScheme()->colorNamed("SkyColor");
657 glClearColor(bg.redF(), bg.greenF(), bg.blueF(), bg.alphaF());
658 glClear(GL_COLOR_BUFFER_BIT);
659}
660
661void SkyGLPainter::end()
662{
663 for (int i = 0; i < NUMTYPES; ++i)
664 {
665 drawBuffer(i);
666 }
667}
668
669void SkyGLPainter::begin()
670{
671 m_proj = m_sm->projector();
672
673 //Load ortho projection
674 glViewport(0, 0, m_widget->width(), m_widget->height());
675 glMatrixMode(GL_PROJECTION);
676 glLoadIdentity();
677 glOrtho(0, m_widget->width(), m_widget->height(), 0, -1, 1);
678
679 //reset modelview matrix
680 glMatrixMode(GL_MODELVIEW);
681 glLoadIdentity();
682
683 //Set various parameters
684 glDisable(GL_LIGHTING);
685 glDisable(GL_COLOR_MATERIAL);
686 glDisable(GL_CULL_FACE);
687 glDisable(GL_DEPTH_TEST);
688 glDepthMask(GL_FALSE);
689 glPointSize(1.);
690 glEnable(GL_POINT_SMOOTH);
691 glEnable(GL_LINE_SMOOTH);
692 glEnable(GL_POLYGON_SMOOTH);
693 glLineStipple(1, 0xCCCC);
694 glEnable(GL_BLEND);
695
696 glClearStencil(0);
697}
698
699void SkyGLPainter::setBrush(const QBrush &brush)
700{
701 Q_UNUSED(brush);
702 /*
703 QColor c = brush.color();
704 m_pen = Eigen::Vector4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
705 glColor4fv( m_pen.data() );
706 */
707}
708
709void SkyGLPainter::setPen(const QPen &pen)
710{
711 QColor c = pen.color();
712 m_pen = Eigen::Vector4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
713 glColor4fv(m_pen.data());
714 glLineWidth(pen.widthF());
715 if (pen.style() != Qt::SolidLine)
716 {
717 glEnable(GL_LINE_STIPPLE);
718 }
719 else
720 {
721 glDisable(GL_LINE_STIPPLE);
722 }
723}
724
725void SkyGLPainter::drawSatellite(Satellite *sat)
726{
727 KStarsData *data = KStarsData::Instance();
728 bool visible = false;
729 Eigen::Vector2f pos, vertex;
730
731 sat->HorizontalToEquatorial(data->lst(), data->geo()->lat());
732
733 pos = m_proj->toScreenVec(sat, true, &visible);
734
735 if (!visible || !m_proj->onScreen(pos))
736 return;
737
738 if (Options::drawSatellitesLikeStars())
739 {
740 drawPointSource(sat, 3.5, 'B');
741 }
742 else
743 {
744 if (sat->isVisible())
745 setPen(data->colorScheme()->colorNamed("VisibleSatColor"));
746 else
747 setPen(data->colorScheme()->colorNamed("SatColor"));
748
749 glDisable(GL_TEXTURE_2D);
750 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
751 glBegin(GL_QUADS);
752
753 vertex = pos + Eigen::Vector2f(-1.0, -1.0);
754 glVertex2fv(vertex.data());
755 vertex = pos + Eigen::Vector2f(1.0, -1.0);
756 glVertex2fv(vertex.data());
757 vertex = pos + Eigen::Vector2f(1.0, 1.0);
758 glVertex2fv(vertex.data());
759 vertex = pos + Eigen::Vector2f(-1.0, 1.0);
760 glVertex2fv(vertex.data());
761
762 glEnd();
763 }
764
765 if (Options::showSatellitesLabels())
766 data->skyComposite()->satellites()->drawLabel(sat, QPointF(pos.x(), pos.y()));
767}
768
769bool SkyGLPainter::drawSupernova(Supernova *sup)
770{
771 KStarsData *data = KStarsData::Instance();
772 bool visible = false;
773 Eigen::Vector2f pos, vertex;
774
775 sup->HorizontalToEquatorial(data->lst(), data->geo()->lat());
776
777 pos = m_proj->toScreenVec(sup, true, &visible);
778
779 if (!visible || !m_proj->onScreen(pos))
780 return false;
781 setPen(data->colorScheme()->colorNamed("SupernovaColor"));
782
783 glDisable(GL_TEXTURE_2D);
784 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
785
786 glBegin(GL_LINES);
787 vertex = pos + Eigen::Vector2f(2.0, 0.0);
788 glVertex2fv(vertex.data());
789 vertex = pos + Eigen::Vector2f(-2.0, 0.0);
790 glVertex2fv(vertex.data());
791 glEnd();
792
793 glBegin(GL_LINES);
794 vertex = pos + Eigen::Vector2f(0.0, 2.0);
795 glVertex2fv(vertex.data());
796 vertex = pos + Eigen::Vector2f(0.0, -2.0);
797 glVertex2fv(vertex.data());
798 glEnd();
799
800 return true;
801}
QColor colorNamed(const QString &name) const
Retrieve a color by name.
Information about a ConstellationsArt object.
QColor labelColor(int index)
Get label color.
QString label(int index)
Get label.
QString imageName(int index)
Get image name.
QImage image(int index)
Get image.
const CachingDms * lat() const
Definition geolocation.h:70
A subclass of TrailObject that provides additional information needed for most solar system objects.
const QImage & image() const
double angSize() const
KStarsData is the backbone of KStars.
Definition kstarsdata.h:74
CachingDms * lst()
Definition kstarsdata.h:226
ColorScheme * colorScheme()
Definition kstarsdata.h:174
GeoLocation * geo()
Definition kstarsdata.h:232
SkyMapComposite * skyComposite()
Definition kstarsdata.h:168
A simple data container used by LineListIndex.
Definition linelist.h:25
double findPA(const SkyObject *o, float x, float y) const
Determine the on-screen position angle of a SkyObject.
bool onScreen(const QPointF &p) const
Check whether the projected point is on-screen.
Definition projector.cpp:98
virtual Eigen::Vector2f toScreenVec(const SkyPoint *o, bool oRefract=true, bool *onVisibleHemisphere=nullptr) const
Given the coordinates of the SkyPoint argument, determine the pixel coordinates in the SkyMap.
Eigen::Vector2f clipLineVec(SkyPoint *p1, SkyPoint *p2) const
ASSUMES *p1 did not clip but *p2 did.
bool checkVisibility(const SkyPoint *p) const
Determine if the skypoint p is likely to be visible in the display window.
virtual QVector< Eigen::Vector2f > groundPoly(SkyPoint *labelpoint=nullptr, bool *drawLabel=nullptr) const
Get the ground polygon.
Represents an artificial satellites.
Definition satellite.h:23
bool isVisible()
void drawLabel(Satellite *sat, const QPointF &pos)
Draw label of a satellite.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:42
virtual QString name(void) const
Definition skyobject.h:146
int type(void) const
Definition skyobject.h:189
float mag() const
Definition skyobject.h:207
Draws things on the sky, without regard to backend.
Definition skypainter.h:40
float starWidth(float mag) const
Get the width of a star of magnitude mag.
The sky coordinates of a point in the sky.
Definition skypoint.h:45
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
Definition skypoint.cpp:77
void HorizontalToEquatorial(const dms *LST, const dms *lat)
Determine the (RA, Dec) coordinates of the SkyPoint from its (Altitude, Azimuth) coordinates,...
Definition skypoint.cpp:143
Represents the supernova object.
Definition supernova.h:34
static const QImage & getImage(const QString &name)
Return texture image.
static constexpr double PI
PI is a const static member; it's public so that it can be used anywhere, as long as dms....
Definition dms.h:385
QString xi18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
QString label(StandardShortcut id)
float alphaF() const const
float blueF() const const
void getHsv(int *h, int *s, int *v, int *a) const const
float greenF() const const
float redF() const const
void setHsv(int h, int s, int v, int a)
void setRgb(QRgb rgb)
int height() const const
int width() const const
const_reference at(qsizetype i) const const
pointer data()
void reserve(qsizetype size)
qsizetype size() const const
QColor color() const const
Qt::PenStyle style() const const
qreal widthF() const const
int height() const const
int width() const const
bool isEmpty() const const
transparent
SolidLine
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.