OpenGL-Primtive innerhalb eines Visual C++-Dialogf

ich habe gerade meine ersten Schritte mit OpenGL gemacht.
Das ist schon eine sehr tolle Sache ! Bin nun voll motiviert für weitere Taten auf dem Gebiet.

Leider konnte ich in diversen Tutorials und Foren keine Antwort zu meinem aktuellen OpenGL-Problem finden:

1.)
Man stelle sich einen Haufen von allesamt rechteckigen Packstücken vor, die auf einen Lkw verladen sind. Die Packstücke haben unterschiedliche Farben und sind per OpenGL graphisch in 3D dargestellt (an ihrer jeweiligen Verladeposition).
Als Beispiel stelle man sich ca. 20 Stück in der Breite, 10 in der Höhe und 5 in der Tiefe vor, zusammen also 1000 Stück auf einem Lkw.

Bisher habe ich es nur geschafft, über glPolygonMode die Packstücke entweder komplett ausgefüllt oder im Gittermodus darzustellen. Es gibt in dem Befehl offensichtlich keine mode-Konstante, die beides zusammen, d.h. ausgefüllte Packstücke (in der jeweiligen Farbe) bei denen jeweils die sichtbaren Kanten in schwarz nachgezogen sind, darzustellen.

Ich habe versucht, die Kanten per GL_LINES (zusätzlich zu den separat gezeichneten Packstück-Quads im Fill-Modus) selbst in schwarz zu ziehen. Aber das gibt das totale Chaos bei 1000 Packstücken. Man erkennt dann vor lauter Kanten / schwarzen Linien so gut wie gar nichts mehr.
Insbesondere möchte ich ja nur die jeweils von außen per Draufsicht auf den gesamten Lkw-Inhalt sichtbaren Packstückkanten gezeichnet haben. Bei meiner GL-Lines-Variante sieht man aber auch die Kanten all der Packstücke, die in dem Haufen versteckt liegen, d.h. von außen gar nicht sichtbar sind (da ich mich außerstande sehe, per eigenem Algorithmus die Kanten zu berechnen, die jeweils nur von außen sichtbar sind - das wäre viel zu aufwändig).
Es muss doch in OpenGL auch einen direkten Weg geben, mit dem man rechteckige Flächen (= die Oberflächen von all den Packstücken) und deren Kanten gleichzeitig dargestellt bekommt.

2.)

Ich möchte die Packstück-Gesamtdarstellung möglichst nicht in einem separaten OpenGL-Fenster darstellen (das sich von einem Steuerungs-Dialog aus jeweils öffnet), sondern integriert in einen „Graph-Bereich“ eines bestehenden Visual C+±Dialoges. Den „Graph-Bereich“ innerhab des Dialogs kann man sich optisch, wenn darin angenommen gerade keine Packstücke angezeigt werden, so vorstellen wie ein leeres Listenfeld.

Je nach Steuerungs-Schaltflächen-Druck in dem Dialog, soll sich der Packstück-Haufen in dem Dialog (d.h. in dem dort dann integrierten „Graph-Bereich“) dann bewegen (rotieren, kippen, usw.).
Wie kriege ich also bitte OpenGL-Primitive innerhalb eines Visual-C+±Dialoges angezeigt ?

Hat jemand bitte eine Idee für mich. Danke im voraus.

Hiho

1.)

Dazu hab ich nichts gefunden, aber sollte nicht folgendes gehen (wegen des Überzeichnens):

_You can use glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); to draw as wireframe and glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); to return to solid primitives.

If you first draw a polygon solid and then draw it as wireframe, you can use that to outline your polygon. Just set the appropriate colour and disable texturing.

BTW, GL_LINES isn’t that hard to use. Just draw a line from point A to B, B to C, C to D and D back to A and you have your quad. It takes only twice as many vertices to use lines._

zu

2.)

http://www.codeguru.com/cpp/g-m/opengl/openfaq/artic…

mfg TLF

Hallo,

erstmal danke für deine Hilfe.
die genannte Methode zu 1.) funktioniert zwar. Jedoch führt diese auch dazu, dass alle Kanten sämtlicher Packstücke gezeichnet werden, d.h. auch derjenigen, die von außen gar nicht sichtbar sind. Im Ergebnis habe ich mit der von Snapshot genannten Methode das gleiche wie mit meiner zuvor verwendeten Methode, dass ich alle Kanten selbst mit GL_LINES nachgezogen hatte. Genau das sind dann aber zuviel dargestellte Kanten (das besagte Chaos in der Darstellung). Man sieht vor lauter Kanten-Linien das Wesentliche nicht mehr.
Ich möchte ja wie gesagt nur die von außen (Draufsicht) sichtbaren Packstückkanten zeichnen lassen, nicht diejenigen, die „in dem Haufen drinnen versteckt liegen“.
Das heißt zwar die Oberflächen aller Packstücke (Fillmodus) sollen gezeichnet werden, hinsichtlich der nachgezogenen Kanten aber nur die von den von außen sichtbaren Packstücke.
Ich gehe mal davon aus, dass es in OpenGL irgendeine Option gibt, die das eigentlich unsichtbare in der Darstellung ausblendet.
Nur mache ich das bitte ?

1.)

Dazu hab ich nichts gefunden, aber sollte nicht folgendes
gehen (wegen des Überzeichnens):

_You can use glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); to
draw as wireframe and glPolygonMode (GL_FRONT_AND_BACK,
GL_FILL); to return to solid primitives.

If you first draw a polygon solid and then draw it as
wireframe, you can use that to outline your polygon. Just set
the appropriate colour and disable texturing.

BTW, GL_LINES isn’t that hard to use. Just draw a line from
point A to B, B to C, C to D and D back to A and you have your
quad. It takes only twice as many vertices to use lines._

zu

2.)

http://www.codeguru.com/cpp/g-m/opengl/openfaq/artic…

mfg TLF

Hallo

Ich gehe mal davon aus, dass es in OpenGL irgendeine Option
gibt, die das eigentlich unsichtbare in der Darstellung
ausblendet.

Gibt es nicht, dafür ist der Programmierer da.
Aber vielleicht geht folgendes:
http://glprogramming.com/red/chapter14.html#name16

geht 2.) ?

mfg TLF

Hallo,

meine beiden Ausgangs-Probleme sind im groben gelöst. Ein ganz herzliches Dankeschön für die Hilfe, besonders an TheLordFerada.

Die Sache mit OpenGL-Polygonen innerhalb eines bestehenden Dialogs funktioniert und auch das „Packstück-Tiefenproblem“ ist gelöst.
Anliegender Code ergibt das entsprechende Ergebnis.
Nun sind aber noch ein paar Details dazu zu erledigen. Ich habe mich selbst daran versucht, durch „Ausprobieren“, d.h. durch Verändern mancher Parameter das zu erreichen, aber ohne zufrieden stellenden Erfolg.
Ich bin dafür ganz offensichtlich einfach noch zu sehr Anfänger.
Daher meine Hoffnung, dass von Euch Experten mir jemand genau die Werte bzw. Veränderungen nennen kann, die genau zur gewünschten Darstellung führen.
Ich muss zur Problemschilderung nun notgedungen etwas ausholen:

Man stelle sich das nun bitte nicht mehr als Lkw vor, sondern als „hoher Haufen von rechteckigen Packstücken, die auf eine Palette geladen sind“. Die Abmessungen über alles (des gesamten Haufens bzw. der verwendeten Palette) können je nach Beladung variieren.
Um eine konkretes Beispiel zu haben, nehmen wir hier bitte einmal eine Breite von 120cm, eine Tiefe von 100cm und eine Höhe von 250cm an.
Jedem Interessenten sende ich per email gerne einen Snapshot zu, der visuell das Ergebnis verdeutlicht (den Dialog, in dem die OpenGL-Quads angezeigt werden). Ich kenne bisher keine Möglichkeiten, erläuternde Bilddateien an Forum-Artikel anzuhängen.

Es bestehen noch folgende offene Probleme:

Wie kann ich erreichen, dass ein jeweiliger Packstück-Haufen mit seinen Abmessungen über alles, beim Öffnen des Dialogs in der Größe dargestellt wird, dass er ideal in den Graph-Bereich passt (d.h. dass an den Rändern nur ca. 10% Rand verbleibt) ?

Hierbei kommt hinzu, dass der Haufen derzeit immer nur in der oberen Hälfte angezeigt wird, da der Ursprung ja in die Mitte des Graphen gelegt ist.
Ich habe versucht, den mittleren Wert von glTranslatef(-0.0f, -0.0f, -m_fZoom) in InDraw mit einem negativen Wert zu belegen, aber ohne brauchbare Ergebnisse. Zwar rutscht dann das Gebilde nach unten, aber nie in die ideale Position wie es soll. Es fehlt mir an der genauen Abstimmung aller Parameter untereinander, die mir mangels ausreichender Kenntnisse bisher nicht gelingen will.

Wie man sieht, werden die Ergebnis-Werte von meinem Berechnungs-Algorithmus in integer-Werten geliefert (nämlich genau in Zentimetern).
Die Werte (jeweils in integers) befinden sich in folgenden Variablen:

pLength, pHeight, pWidth: Abmessungen des jeweiligen Packstücks
&xi, &yi, &zi: Lage-Koordinate der unteren linken Ecke des jeweiligen Packstücks
pallength, pallwidth, palheight: Abmessungen der Palette, auf welche die Packstücke verladen sind (= Abmessungen über alles des „Packstück-Haufens“).

Bei der Umrechnung in float (hier einfach salopp per /100 von mir realisiert) gibt es wohl gelegentlich üble Rundungsfehler, so dass in der Darstellung manchmal Packstücke sich im Volumen überlappen (was nicht sein darf). Die Berechnungsergebnisse meines Algorithmus sind stets korrekt, das habe ich geprüft.

Zudem bin ich im Zweifel immer „Performance-Fetischist“. Das heißt es ist mir an sich ein Dorn im Auge, dass überhaupt in float umgerechnet werden muss.
Viel schöner wäre es, einfach bei den Vertex-Deklarationen im int-Bereich zu bleiben.

Ich habe es per glVertex3i anstatt glVertex3d versucht, allerdings ohne die Packstück-Ergebnis-Werte des Berechnungs-Algorithmus per Division zu verkleinern (die Kanten-Längen der Packstücke liegen stets so zwischen 30 und 70 cm).

Das hatte zum Ergebnis, dass die Werte für die Anzeige so groß waren, dass man vom Gesamtgebilde (Haufen) gar nichts erkennen konnte, sondern nur noch den Oberflächen-Ausschnitt irgendeines Packstücks.

Das liegt wiederum daran, dass die anderen Werte (ich vermute die in OnSize und oglInitialize) nicht auf diese int-Werte von der Größenordnung her abgestimmt sind (im Prinzip das gleiche Grundproblem wie unter 1. und 2.).

Ich bin mir sicher, dass man die in OnSize und oglInitialize nur entsprechend geschickt verändern muss, nur eben bitte wie ? Auf das Zusammenspiel kommt es hier an und ich bin zugegebenermaßen derzeit noch „zu doof“ bzw. zu „Betriebsblind“ um das hinzubekommen.

Welcher „OpenGL-Volldurchblicker“ kann mir am besten gleich den Parameter-technisch überarbeiteten Code nennen ?


#include „stdafx.h“
#include „palletdefinition.h“
#include „OpenGLControl.h“
#include „.\openglcontrol.h“

COpenGLControl::COpenGLControl(void)
{
m_fZoom = 10.0f;
m_fRotX = 45.0f;
m_fRotY = 45.0f;
palnr = 0;
pallength = 0;
palwidth = 0;
palheight = 0;
gitterfill = TRUE;
packerg = NULL;
paldef = NULL;
}

COpenGLControl::~COpenGLControl(void)
{
}

BEGIN_MESSAGE_MAP(COpenGLControl, CWnd)
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

void COpenGLControl::open_mouth:nPaint()
{
ValidateRect(NULL);
}

void COpenGLControl::open_mouth:nSize(UINT nType, int cx, int cy)
{
CWnd::open_mouth:nSize(nType, cx, cy);

if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;

// Map the OpenGL coordinates.
glViewport(0, 0, cx, cy);

// Projection view
glMatrixMode(GL_PROJECTION);

glLoadIdentity();

// Set our current view perspective
gluPerspective(35.0f, (float)cx / (float)cy, 0.1f, 2000.0f);

// Model view
glMatrixMode(GL_MODELVIEW);
}

int COpenGLControl::open_mouth:nCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::open_mouth:nCreate(lpCreateStruct) == -1) return -1;

oglInitialize();

return 0;
}

void COpenGLControl::open_mouth:nDraw(CDC *pDC)
{
// If the current view is perspective…
glLoadIdentity();

glTranslatef(-0.0f, -0.0f, -m_fZoom);
glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);
glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
}

void COpenGLControl::open_mouth:nTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case 1:
{
// Clear color and depth buffer bits
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Draw OpenGL scene
oglDrawScene();

// Swap buffers
SwapBuffers(hdc);

break;
}

default:
break;
}

CWnd::open_mouth:nTimer(nIDEvent);
}

void COpenGLControl::open_mouth:nMouseMove(UINT nFlags, CPoint point)
{
int diffX = (int)(point.x - m_fLastX);
int diffY = (int)(point.y - m_fLastY);
m_fLastX = (float)point.x;
m_fLastY = (float)point.y;

// Left mouse button
if (nFlags & MK_LBUTTON)
{
m_fRotX += (float)0.5f * diffY;

if ((m_fRotX > 360.0f) || (m_fRotX 360.0f) || (m_fRotY m_hDC;

// Pixel format
m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, m_nPixelFormat, &pfd);

// Create the OpenGL Rendering Context
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);

// Set color to use when clearing the background
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClearDepth(1.0f);

// Turn on backface culling
glFrontFace(GL_CCW);
glCullFace(GL_BACK);

// Turn on depth testing
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

// Send draw request
OnDraw(NULL);
}

void COpenGLControl::oglDrawScene(void)
{
float x, y, z, packLength, packWidth, packHeight;
unsigned short xi, yi, zi, packnr;
unsigned short pLength, pWidth, pHeight;
CString str;
int i = 0;

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(2.0);
glColor3f(0, 0, 0);

int palnr_view = packerg->GetOriginNumberOfPals() - palnr - 1;

for (i=0; i GetOriginNumberOfPacksOnPal(palnr_view); ++i)
{
packerg->GetPackPosition(palnr_view, i, &xi, &yi, &zi, &packnr);
x = ((float)xi) / 100;
y = ((float)zi) / 100;
z = ((float)yi) / 100;
packerg->GetOriginPacks(0, &str, &pLength, &pHeight, &pWidth, &xi, &yi);
packLength = ((float)pLength) / 100;
packWidth = ((float)pWidth) / 100;
packHeight = ((float)pHeight) / 100;

glBegin(GL_QUADS);

// Boden
glVertex3d(x, y, z);
glVertex3d(x, packWidth+y, z);
glVertex3d(packLength+x, packWidth+y, z);
glVertex3d(packLength+x, y, z);

// Deckel
glVertex3d(x, y, packHeight+z);
glVertex3d(packLength+x, y, packHeight+z);
glVertex3d(packLength+x, packWidth+y, packHeight+z);
glVertex3d(x, packWidth+y, packHeight+z);

// Mantel

glVertex3d(x, y, z);
glVertex3d(packLength+x, y, z);
glVertex3d(packLength+x, y, packHeight+z);
glVertex3d(x, y, packHeight+z);

glVertex3d(x, y, z);
glVertex3d(x, packWidth+y, z);
glVertex3d(x, packWidth+y, packHeight+z);
glVertex3d(x, y, packHeight+z);

glVertex3d(x, packWidth+y, z);
glVertex3d(x, packWidth+y, packHeight+z);
glVertex3d(packLength+x, packWidth+y, packHeight+z);
glVertex3d(packLength+x, packWidth+y, z);

glVertex3d(packLength+x, packWidth+y, z);
glVertex3d(packLength+x, packWidth+y, packHeight+z);
glVertex3d(packLength+x, y, packHeight+z);
glVertex3d(packLength+x, y, z);

glEnd();
}

if (gitterfill)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1.0);

for (i=0; i GetOriginNumberOfPacksOnPal(palnr_view); ++i)
{
packerg->GetPackPosition(palnr_view, i, &xi, &yi, &zi, &packnr);
x = ((float)xi) / 100;
y = ((float)zi) / 100;
z = ((float)yi) / 100;
packerg->GetOriginPacks(0, &str, &pLength, &pHeight, &pWidth, &xi, &yi);
packLength = ((float)pLength) / 100;
packWidth = ((float)pWidth) / 100;
packHeight = ((float)pHeight) / 100;

glColor3f(paldef->GetRGB1(yi),
paldef->GetRGB2(yi),
paldef->GetRGB3(yi));

glBegin(GL_QUADS);

// Boden
glVertex3d(x, y, z);
glVertex3d(x, packWidth+y, z);
glVertex3d(packLength+x, packWidth+y, z);
glVertex3d(packLength+x, y, z);

// Deckel
glVertex3d(x, y, packHeight+z);
glVertex3d(packLength+x, y, packHeight+z);
glVertex3d(packLength+x, packWidth+y, packHeight+z);
glVertex3d(x, packWidth+y, packHeight+z);

// Mantel
glVertex3d(x, y, z);
glVertex3d(packLength+x, y, z);
glVertex3d(packLength+x, y, packHeight+z);
glVertex3d(x, y, packHeight+z);

glVertex3d(x, y, z);
glVertex3d(x, packWidth+y, z);
glVertex3d(x, packWidth+y, packHeight+z);
glVertex3d(x, y, packHeight+z);

glVertex3d(x, packWidth+y, z);
glVertex3d(x, packWidth+y, packHeight+z);
glVertex3d(packLength+x, packWidth+y, packHeight+z);
glVertex3d(packLength+x, packWidth+y, z);

glVertex3d(packLength+x, packWidth+y, z);
glVertex3d(packLength+x, packWidth+y, packHeight+z);
glVertex3d(packLength+x, y, packHeight+z);
glVertex3d(packLength+x, y, z);

glEnd();
}
}
glDisable(GL_POLYGON_OFFSET_FILL);
}

void COpenGLControl::Up()
{
m_fRotX -= (float)10;
if (m_fRotX 360.0f)
{
m_fRotX = 0.0f;
}
OnDraw(NULL);
}

void COpenGLControl::Left()
{
m_fRotY -= (float)10;
if (m_fRotY 360.0f)
{
m_fRotY = 0.0f;
}
OnDraw(NULL);
}

void COpenGLControl::stuck_out_tongue:lus()
{
if (m_fZoom > 4.5)
{
m_fZoom -= (float)1;
}
OnDraw(NULL);
}

void COpenGLControl::Minus()
{
if (m_fZoom