PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C++/OpenGL] 2D Canvas auf 3D Szene zeichnen?


WhiteVelvet
2006-07-15, 15:28:16
Kann man mit 3D Befehlen wie LineTo oder Circle auf ein 3D Canvas zeichnen? Ich habe keinen Platz für eine extra Bitmap, auf die ich einen 2D-Graphen zeichnen muss, also müsste ich das irgendwo in einer Ecke der 3D Szene unterbringen. Gibts da einfache Befehle für?

Coda
2006-07-15, 16:13:31
Uhm - du kannst es mit nem OpenGL-Linestrip machen z.B.

WhiteVelvet
2006-07-15, 16:38:21
Das ist aber wieder alles 3D. Ich suche eine Möglichkeit nur auf das 2D Koordinatensystem des Controls zu zeichnen.

Coda
2006-07-15, 16:51:25
Ha? Dann machst dir halt ne entsprechende 2D-Projektionsmatrix. Wo ist das Problem?

WhiteVelvet
2006-07-15, 17:27:51
Ja wenn das so ist, wie dumm von mir... meine Güte, wenn ich sowas wüsste, würde ich nicht fragen.

Coda
2006-07-15, 20:13:27
glOrtho. Machsu left=0, top=0, right=widget_width-1, bottom=widget_height-1

far und near is mal egal, nimmst einfach 1 und 0 und schälst Z-Write und Z-Compare ab.

Dann kannst du z.B. mit glVertex2f ganz normale Bildschirmkoordinaten verwenden (kann aber sein, dass du da +0.5f machen must wegen der OpenGL-Scan-Convention)

Ach so und vergiss nicht die Modelview-Matrix auf Identity zu setzen.

del_4901
2006-07-15, 20:36:12
Coda[/POST]']
Ach so und vergiss nicht die Modelview-Matrix auf Identity zu setzen.

Wohl eher die Projection Matrix?

Expandable
2006-07-15, 22:13:59
AlphaTier[/POST]']Wohl eher die Projection Matrix?

glOrtho setzt doch gerade die Projectionmatrix.

del_4901
2006-07-15, 22:21:20
Expandable[/POST]']glOrtho setzt doch gerade die Projectionmatrix.
Multipliziert die sich ned automatisch mit der alten? Es kann sein, das ich da durcheinanderkomme, weil meine 4x4 Matrix das so handhabt, wenn nicht anders angegeben.

Coda
2006-07-15, 23:56:37
AlphaTier[/POST]']Wohl eher die Projection Matrix?
Ja die vorher natürlich auch.

Expandable
2006-07-16, 00:51:48
Also um's nochmal deutlich zu machen:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(...);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

DAS sollte jetzt aber klar sein ;)

WhiteVelvet
2006-07-16, 12:23:03
Vielen Dank :)

WhiteVelvet
2006-07-16, 12:54:08
Hmmm irgendwie stellt er nun die 3D Szene nicht mehr da, wenn ich den Modus wechsle. Vielleicht wechsle ich an der falschen Stelle, oder ich hab irgendwas vergessen. Am besten geb ich hier mal etwas Code aus meiner COpenGLCtrl Klasse an:

// called upon WM_CREATE
int COpenGLCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;

oglInitialize();

return 0;
}

// called upon WM_DRAW
void COpenGLCtrl::OnDraw(CDC *pDC)
{
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -m_fZoom);
glTranslatef(m_fPosX, m_fPosY, 0.0f);
glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);
glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
}

// called upon WM_PAINT
void COpenGLCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
ValidateRect(NULL);
}

// Timer Event
void COpenGLCtrl::OnTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case 1:
{
// Clear color and depth buffer bits
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Draw OpenGL scene
DrawMesh();
SwapBuffers(hdc);

break;
}

default:
break;
}

CWnd::OnTimer(nIDEvent);
}



// Create OpenGL
void COpenGLCtrl::oglCreate(CRect rect, CWnd *parent)
{
CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL,
(HBRUSH)GetStockObject(BLACK_BRUSH), NULL);

CreateEx(0, className, "OpenGL", WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS, rect, parent, 0);

// Set initial variables' values
m_oldWindow = rect;
m_originalRect = rect;

hWnd = parent;
}

// OpenGL Init
void COpenGLCtrl::oglInitialize(void)
{
// set camera for draw mode 1 (Mesh)
[setting up some camera positions and movements]

static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32, // bit depth
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16, // z-buffer depth
0, 0, 0, 0, 0, 0, 0,
};

// Get device context only once.
hdc = GetDC()->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);

// Basic Setup:
//
// Set color to use when clearing the background.
glClearColor(0.6f, 0.6f, 0.6f, 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);
}

// wird von aussen aufgerufen wenn die Fenstergrösse verändert wird, oder WM_PAINT
void COpenGLCtrl::oglAdjustViewport(int x, int y, int w, int h)
{
// Map the OpenGL coordinates.
glViewport(0, 0, w, h);

// Projection view
glMatrixMode(GL_PROJECTION);

glLoadIdentity();

// Set our current view perspective
gluPerspective(45.0f, (float)w / (float)h, 0.001f, 2000.0f);

// Model view
glMatrixMode(GL_MODELVIEW);
}

// ++++++++++++ hier soll die 2D neben die 3D Szene rein ++++++++++++
void COpenGLCtrl::DrawMesh()
{
glPushMatrix();
glRotatef(0.0,0.0,0.0,0.0);
glTranslatef(0.0f,0.0f,0.0f);

int x,y;
double scale=0.05;

InitVisibleArray();
CombineMesh();
CloseGaps();

GLfloat xOffset = XCHIPSIZE/2;
GLfloat yOffset = YCHIPSIZE/2;
glTranslatef(-xOffset*scale,-yOffset*scale,0.0);

[zeichne 3D Szene...]

glPopMatrix();

//in den 2D-Modus schalten
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glOrtho(0,640,0,480, 0,128);
//erneut die Modelviewmatrix "aktivieren"
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;

glPushMatrix();

glBegin(GL_LINE);
glVertex2f(10.0,10.0);
glVertex2f(30.0,70.0);
glEnd();

glPopMatrix();

// auch wenn ich das hier weglasse, wird die 3D Szene nicht mehr gerendert
//in den Perspektivenmodus zurückschalten
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(45.0f, 640 / 480, 0.001f, 2000.0f);
//erneut die Modelviewmatrix "aktivieren"
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
}

Coda
2006-07-16, 14:39:02
gluPerspective(45.0f, (float)w / (float)h, 0.001f, 2000.0f);
Ganz ganz ganz ganz böse. Deine Near-Plane ist viel zu Nahe. So hast du mit Sicherheit 99% der Z-Präzission zwischen 0 und 1.

Expandable
2006-07-16, 14:40:57
Nur kurz überflogen, aber: Bei glLoadIdentity() fehlen die Klammern. Ansonsten... äh... bist Du sicher, dass die Modelviewmatrix für Deine 3D-Szene wieder ordentlich aufgebaut wird bzw. irgendwo gespeichert und wieder geladen wird?

Und Deine Near Clipping Plane solltest Du besser auf 1.0f setzen.

Ansonsten erscheint mir das hier recht sinnfrei (wenn es auch womöglich nichts mit Deinem Problem zu tun hat):

glPushMatrix();

glRotatef(0.0,0.0,0.0,0.0);
glTranslatef(0.0f,0.0f,0.0f);

Rotate und Translate weglassen und einfach glLoadIdentity();

WhiteVelvet
2006-07-16, 14:59:41
Ja, das Rotate und Translate kann weg, ist noch ein altes Überbleibsel. Ich hab das alles mal etwas minimiert und analytisch drangegangen:


void COpenGLCtrl::DrawMesh()
{
glPushMatrix();

[...3D Szene rendern...]

// in den 2D-Modus schalten
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
//glOrtho(0,640,0,480, 0,128);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;

glBegin(GL_QUADS);
glColor3f(1.0,0.0,0.0);
glVertex2f(0.0,0.0);
glVertex2f(0.0,1.0);
glVertex2f(1.0,1.0);
glVertex2f(1.0,0.0);
glColor3f(1.0,1.0,1.0);
glEnd();

// zurück in den 3D Modus
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(45.0f, (float)m_intWidth / (float)m_intHeight, 1.0f, 2000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;

glPopMatrix();
}

Ich habe einfach erstmal nur die Matrizen gewechselt um zu sehen, ob das ohne Probleme geht. Es klappt, dann habe glOrtho und gluPerspective ausgeklammert und ein rotes 3D Viereck gezeichnet. Klappt auch noch. Wenn ich nun aber glOrtho weiterhin draussen lasse und gluPerspective hinzufüge, dann erscheint das rote Viereck ganz kurz und verschwindet plötzlich, als wenn die Kamera sich irgendwohin bewegt. Muss am mehrmaligen Aufruf von gluPerspective liegen. Addiert sich da was auf?

WhiteVelvet
2006-07-16, 15:06:34
So, ok, habs nun hinbekommen. Es waren irgendwie tatsächlich nur die plöden fehlenden Klammern bei LoadIdentity. Wieso gibt er denn dann keinen Compilerfehler? Sowas... ;)

Neomi
2006-07-16, 16:04:28
WhiteVelvet[/POST]']So, ok, habs nun hinbekommen. Es waren irgendwie tatsächlich nur die plöden fehlenden Klammern bei LoadIdentity. Wieso gibt er denn dann keinen Compilerfehler? Sowas... ;)

Der Compiler meldet keinen Fehler, weil das kein Syntaxfehler ist, sondern ein Logikfehler. Ein Funktionsname ohne Klammern ist nämlich kein Aufruf, sondern eine valide Abfrage der Funktionsadresse, um sie z.B. in einem Funktionspointer zu speichern. Da das Ergebnis nicht verwendet wird, wird es verworfen.

Coda
2006-07-16, 16:04:34
Was für nen Compiler benützt du denn eigentlich?

Ach btw. Hungarian-Notation kommt direkt aus der Hölle :tongue:
Aber das ganze sieht eh verdächtig nach MFC aus, was noch viel viel tiefer aus der Hölle kommt.

del_4901
2006-07-16, 16:09:00
Coda[/POST]']Was für nen Compiler benützt du denn eigentlich?

Ach btw. Hungarian-Notation kommt direkt aus der Hölle :tongue:
Aber das ganze sieht eh verdächtig nach MFC aus, was noch viel viel tiefer aus der Hölle kommt.

Da hat er es wenigstens immer schoen warm ^^
Also Hungarian Notation ... wer's mag mir egal.
Aber MFC ... Da kann ich mir auch gleich in's linke Bein schießen um das rechte zu verbinden.

Coda
2006-07-16, 16:12:32
AlphaTier[/POST]']Also Hungarian Notation ... wer's mag mir egal.
Nein nein nein. Dafür ist C++ schön strong typed und man hat eine IDE die einem das sagt wenn man es in 1% der Fälle mal nicht mehr weiß was für ein Typ eine Variable hat ohne den ganzen Code unlesbar zu machen.

.NET hat mit dem Mist ja endlich aufgeräumt.

WhiteVelvet
2006-07-16, 20:45:38
Jo, ist leider MSVC2005 und MFC. Ich muss es leider benutzen...

Coda
2006-07-17, 00:50:54
MS VC++ 2005 ist doch gut - nur MFC ist es nicht ;)

Warum müssen? Wer verlangt denn sowas heute noch? X-D

ScottManDeath
2006-07-17, 02:46:58
Ungaren und VI/Emacs Fetischisten :rolleyes:

WhiteVelvet
2006-07-17, 10:17:21
... und mein Professor. Aber ich höre seit 2 Wochen Gerüchte, dass er auf Qt umsteigen will. Ist für mich aber zu spät, da ich bei 80% mit dem Projekt durch bin.

Gast
2006-07-17, 22:30:35
Coda[/POST]']Nein nein nein. Dafür ist C++ schön strong typed und man hat eine IDE die einem das sagt wenn man es in 1% der Fälle mal nicht mehr weiß was für ein Typ eine Variable hat ohne den ganzen Code unlesbar zu machen.och, das ist nicht sonderlich schwierig, die IDE so weit zu kriegen daß sie in der Hinsicht schweigsam wird wie ein Stockfisch. Da muß man nur mal die Klassen und Sourcefiles was umfangreicher werden lassen, dann passiert das ganz schnell (so zu Hauf gesehen bei VC++ 6). Oder wenn man von jemand anderem dessen Sourcecode zur Verfügung gestellt bekommt, aber nicht als vollständiges compilierfähiges Projekt, sondern nur einzelne Sourcecodefiles oder selbst davon nur Ausschnitte. Oder wenn man Code zwischen verschiedenen IDEs/Klassenbibliotheken portiert, aus eigener Erfahrung kann ich da von MFC -> .NET ein Liedchen singen.

Und was das Nichtmehrwissen von Datentypen angeht: besonders wenn man von Berufs wegen programmiert passiert es recht häufig, daß man einen Datentyp nicht nicht mehr weiß, sondern überhaupt nie zuvor gewußt hat, weil der Code, mit dem man sich gerade beschäftigen muß, gar nicht von einem selbst geschrieben wurde.

Coda
2006-07-17, 22:38:28
Gast[/POST]'](so zu Hauf gesehen bei VC++ 6).
Das benützt man auch nicht. Ich meinte .NET 2005 + Visual Assist z.B.

Gast
2006-07-17, 23:15:06
Coda[/POST]']Das benützt man auch nicht. Ich meinte .NET 2005 + Visual Assist z.B.och, da ist mir das auch schon untergekommen.

del_4901
2006-07-17, 23:33:14
Gast[/POST]']och, da ist mir das auch schon untergekommen.
nich immer allet im Header implementiern, dann klappts auch mit 05 ^^