rotating a user-defined shape

Maybe distortion is the wrong word; the far end was not parallel to the front end, and both near end and far end are identical (same cross-section). I was sure there was something wrong with the display of the far end.

I managed to fix this by adjusting the zFar parameter of glOrtho function.

I get lucky sometimes, as I don’t understand why it fixes it.

The length of my beam is 200 units and this is my glOrtho code:

glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,5.0*(GLfloat)h/(GLfloat)w, -5.0, 50.0);

I would have thought only a length of 55 units would have fit properly (50.0 - -5.0) :confused:

Originally posted by mmsgl:
I would have thought only a length of 55 units would have fit properly (50.0 - -5.0)
Well, if you’ve still got this in your code: “glScalef(.05,.05,.05); // scale to 5%” … .

Why don’t you post a picture of the “distortion” problem.

I don’t see how to attach pictures or files using this board.

Originally posted by mmsgl:
I don’t see how to attach pictures or files using this board.
I haven’t seen it done, either. You’d have to post a link.

I don’t know how to do that either; I only know how to post a link to a URL.

Oh well.

Aeluned:

In one of your earlier posts you stated correctly that where the flange and web meet there is a radiused transition from one to the other, and that this could be addressed in the OpenGL representation of my “W” shape.

Could you explain now how this can be done?

(Once I finish this I can then move on to the next step in my project)

Alright, what you need is 4 arcs to place at the meeting points where the web meets the flanges.
The arcs span PI/2.0 (or 90 degrees) and have a depth equal to that of the flanges, you’ll also need caps at the end of the arcs to align with the surface and back face of the beam. This sort of stuff is always so much simpler to demonstrate on paper :frowning:

There are two ways you can approach the problem:

Use OpenGL and procedurally generate the vertices needed to define these arcs (an alternative is to use OpenGL evaluators - glEvalMesh, glMap2f, etc… which will evaluate a Bezier surface patch given a set of control points). You may or may not need to dust off a trig and/or geometry book if taking this approach.

my suggestion is to forget everything above and get familiar with the very basics of a modeling software app (like 3D studio max). You can visually create a beam there (with a radial transition from the web to the flanges) and export it from there. Then load the model into your openGL app. There are libraries available for importing well known file extensions into an OpenGL app.

check out:
http://www.gametutorials.com/Tutorials/opengl/OpenGL_Pg4.htm

there are some object loaders there.

There’s also 3DCafe.com. You’ll see a ‘free stuff’ link toward the top; they have hundreds (maybe thousands) of 3D models there (you might find a beam if you’re lucky).

OK thanks!

I am going to go the OpenGL route,(probably your first option).

Wish me luck (I’ll probably have questions in a few days :smiley: )

OK, I found a number of samples regarding producing circles in OpenGL, and they all work quite well.

When I try to incorprate into my project I am having a few minor difficulties (no errors, just no circle display).

I understand now the OpenGL concept that complex shapes are just a series of basic shapes (quads, triangles, etc) that combine to form the complex shape.

My beam is made up of three quads and now four quarter circles.

In my code which I had previously posted, I do this to define my 3 quads:

glBegin(GL_QUADS);
    //define 3 quads (top flange, btm flange, web)
    glVertex3f(Vertex[0][ 0],Vertex[1][ 0],(Length/2));
    <additional glVertex3f calls here>
glEnd();

The code I am using for the circle uses GL_POLYGON thus:
glBegin(GL_POLYGON);

In trying to combine quads and polygons, I did this:

glBegin(GL_QUADS);
    //define 3 quads (top flange, btm flange, web)
    glVertex3f(Vertex[0][ 0],Vertex[1][ 0],(Length/2));
    <additional glVertex3f calls here>
    
    //define a circle
    glBegin(GL_POLYGON);
        <circle code>
    glEnd();
glEnd();

In other words, I nested one glBegin/End block inside another.

Is this correct?

Got the “caps” working for the 4 radiused flange to web transitions. :smiley:

Now to figure out the “extrusions” for these.

You can’t nest glBegin/glEnd calls; You’ll generate an error.

You’ll need to render your arcs before or after the quads. As far as I can see, the order is of no consequence. depth writes and depth tests should produce proper results regardless of the render order.

Yes, I found this out by trial and error.

I have the “radiused corner” almost working, but I need a little bit of help as the extruded portion is somewhat transparent instead of a solid color.

Here is what I came up with:
(Rotating with the right mouse button seems to work OK except that I am not getting a solid color.)

#include <windows.h>					// must include this before GL/gl.h 
#include <GL/gl.h>						// OpenGL header file 
#include <GL/glu.h>						// OpenGL utilities header file 
#include <stdio.h>
#include <math.h>

#pragma comment(lib, "opengl32.lib")	// This is our basic software OpenGL library
#pragma comment(lib, "glu32.lib")		// This is our glu32 library

enum
{ 
	PAN = 1,							// pan state bit 
    ROTATE,								// rotate state bits 
    ZOOM								// zoom state bit 
};


HDC hDC;								// device context 
HPALETTE	hPalette	= 0;			// custom palette (if needed) 
GLfloat		trans[3];					// current translation 
GLfloat		rot[2];						// current rotation 
bool		keys[256];
GLfloat		zoom		= 0.0f;	



LONG WINAPI WindowProc(HWND, UINT, WPARAM, LPARAM);
HWND CreateOpenGLWindow(char* , int, int, int, int, BYTE, DWORD);
void init();
void display();
void reshape(int, int);
static void update(int, int, int, int, int);

static void drawRadiusedCorner();


int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst,
	LPSTR lpszCmdLine, int nCmdShow)
{
    HGLRC hRC;							// opengl context 
    HWND  hWnd;							// window 
    MSG   msg;							// message 
    DWORD buffer = PFD_DOUBLEBUFFER;	// buffering type 
    BYTE  color  = PFD_TYPE_RGBA;		// color type 

    hWnd = CreateOpenGLWindow("OpenGL", 0, 0, 256, 256, color, buffer);
    if (hWnd == NULL)
	exit(1);

    hDC = GetDC(hWnd);
    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);

    init();

    ShowWindow(hWnd, nCmdShow);

    while(GetMessage(&msg, hWnd, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
    }

    wglMakeCurrent(NULL, NULL);
	ReleaseDC(hWnd,hDC);  
	wglDeleteContext(hRC);
    DestroyWindow(hWnd);
    if (hPalette) DeleteObject(hPalette);

    return msg.wParam;
}

LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ 
    static PAINTSTRUCT ps;
    static GLuint    state   = 0;			// mouse state flag 
    static int omx, omy, mx, my;

    switch(uMsg)
	{
		case WM_PAINT:
			display();
			BeginPaint(hWnd, &ps);
			EndPaint(hWnd, &ps);
			return 0;
		case WM_SIZE:
			reshape(LOWORD(lParam), HIWORD(lParam));
			PostMessage(hWnd, WM_PAINT, 0, 0);
			return 0;
		case WM_CHAR:
			switch (wParam)
			{
				case 27:				// "ESC" key 
					PostQuitMessage(0);	// Quit
					break;
				case 65:				// "A" key
					zoom +=0.05f;		// Zoom In
					PostMessage(hWnd, WM_PAINT, 0, 0);			
					break;
				case 90:				// "Z" key
					zoom -=0.05f;		// Zoom Out   
					PostMessage(hWnd, WM_PAINT, 0, 0);
					break;
			}
			return 0;
		case WM_LBUTTONDOWN:
		case WM_RBUTTONDOWN:
			SetCapture(hWnd);
			mx = LOWORD(lParam);
			my = HIWORD(lParam);
			if (uMsg == WM_LBUTTONDOWN)
				state |= PAN;
			if (uMsg == WM_RBUTTONDOWN)
				state |= ROTATE;
			return 0;
		case WM_LBUTTONUP:
		case WM_RBUTTONUP:
			ReleaseCapture();
			state = 0;
			return 0;
		case WM_MOUSEMOVE:
			if (state)
			{
				omx = mx;
				omy = my;
				mx = LOWORD(lParam);
				my = HIWORD(lParam);
				if(mx & 1 << 15) mx -= (1 << 16);
				if(my & 1 << 15) my -= (1 << 16);
				update(state, omx, mx, omy, my);
				PostMessage(hWnd, WM_PAINT, 0, 0);
			}
			return 0;
		case WM_PALETTECHANGED:
		if (hWnd == (HWND)wParam)
			break;
		case WM_QUERYNEWPALETTE:
			if (hPalette)
			{
				UnrealizeObject(hPalette);
				SelectPalette(hDC, hPalette, FALSE);
				RealizePalette(hDC);
				return TRUE;
			}
			return FALSE;
		case WM_CLOSE:
			PostQuitMessage(0);
			return 0;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam); 
} 



HWND
CreateOpenGLWindow(char* title, int x, int y, int width, int height, 
		   BYTE type, DWORD flags)
{
    int         n, pf;
    HWND        hWnd;
    WNDCLASS    wc;
    LOGPALETTE* lpPal;
    PIXELFORMATDESCRIPTOR pfd;
    static HINSTANCE hInstance = 0;

    if (!hInstance)
	{
		hInstance = GetModuleHandle(NULL);
		wc.style         = CS_OWNDC;
		wc.lpfnWndProc   = (WNDPROC)WindowProc;
		wc.cbClsExtra    = 0;
		wc.cbWndExtra    = 0;
		wc.hInstance     = hInstance;
		wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
		wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
		wc.hbrBackground = NULL;
		wc.lpszMenuName  = NULL;
		wc.lpszClassName = "OpenGL";

		if (!RegisterClass(&wc))
		{
			MessageBox(NULL, "RegisterClass() failed:  "
				"Cannot register window class.", "Error", MB_OK);
			return NULL;
		}
    }

    hWnd = CreateWindow("OpenGL", title, WS_OVERLAPPEDWINDOW |
			WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
			x, y, width, height, NULL, NULL, hInstance, NULL);

    if (hWnd == NULL)
	{
		MessageBox(NULL, "CreateWindow() failed:  Cannot create a window.",
			"Error", MB_OK);
		return NULL;
    }

    hDC = GetDC(hWnd);

    memset(&pfd, 0, sizeof(pfd));
    pfd.nSize        = sizeof(pfd);
    pfd.nVersion     = 1;
    pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | flags;
    pfd.iPixelType   = type;
    pfd.cDepthBits   = 32;
    pfd.cColorBits   = 32;

    pf = ChoosePixelFormat(hDC, &pfd);
    if (pf == 0)
	{
		MessageBox(NULL, "ChoosePixelFormat() failed:  "
			"Cannot find a suitable pixel format.", "Error", MB_OK); 
		return 0;
    } 
 
    if (SetPixelFormat(hDC, pf, &pfd) == FALSE)
	{
		MessageBox(NULL, "SetPixelFormat() failed:  "
			"Cannot set format specified.", "Error", MB_OK);
		return 0;
    } 

    DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);

	ReleaseDC(hWnd,hDC);
    return hWnd;
}    


void init()
{
	glEnable(GL_DEPTH_TEST);
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushMatrix();
    glTranslatef(trans[0], trans[1], trans[2]);
	glRotatef(rot[0], 1.0f, 0.0f, 0.0f);
    glRotatef(rot[1], 0.0f, 1.0f, 0.0f);
	//glScalef(.05,.05,.05);    // scale to 5%
	glTranslatef(0.0f, -0.0f, zoom);  

	drawRadiusedCorner();  
	
	glPopMatrix();
    glFlush();
    SwapBuffers(hDC);    // nop if singlebuffered
}

void reshape(int width, int height)
{

	glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
		MessageBox(NULL, "Pause!", "Debug", MB_OK);    
	//gluPerspective(60.0, (float)width/height, 0.001, 100.0);
	
		//glOrtho  ( left , right , bottom , top , zNear , zFar ) 
	if (width <= height)
	{	
		glOrtho(-5.0, 5.0, -5.0*(GLfloat)height/(GLfloat)width, 
			5.0*(GLfloat)height/(GLfloat)width, -5.0, 50.0);
	}
	else
	{
		glOrtho(-5.0*(GLfloat)width/(GLfloat)height, 
			5.0*(GLfloat)width/(GLfloat)height, -5.0, 5.0, -5.0, 50.0);
	}



	glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -3.0f);
}


static void update(int state, int ox, int nx, int oy, int ny)
{
    int dx = ox - nx;
    int dy = ny - oy;

    switch(state)
	{
		case PAN:
			trans[0] -= dx / 100.0f;
			trans[1] -= dy / 100.0f;
			break;
		case ROTATE:
			rot[0] += (dy * 180.0f) / 500.0f;
			rot[1] -= (dx * 180.0f) / 500.0f;
			#define clamp(x) x = x > 360.0f ? x-360.0f : x < -360.0f ? x+=360.0f : x
			clamp(rot[0]);
			clamp(rot[1]);
			break;
		case ZOOM:
			trans[2] -= (dx+dy) / 100.0f;
			break;
    }
}


static void drawRadiusedCorner()
{
	GLint i;
    GLfloat cosine, sine;
    GLfloat cosine2, sine2;
   
	//front cap
	glBegin(GL_POLYGON);
	glColor3f(0.0f,1.0f,0.0f);				// green    
	glVertex3f(1,1,1);  
	for(i=0;i<25;i++)
	{
		cosine=cos(i*2*3.14159/100.0);
		sine=sin(i*2*3.14159/100.0);
		glVertex3f(cosine,sine,1);
    }
	glEnd();

    //rear cap
    glBegin(GL_POLYGON);
	glColor3f(0.0f,0.0f,1.0f);				// blue
    glVertex3f(1,1,-1);  
	for(i=0;i<25;i++)
	{
		cosine=cos(i*2*3.14159/100.0);
		sine=sin(i*2*3.14159/100.0);
		glVertex3f(cosine,sine,-1);
    }
    glEnd();

    //extrusion
	glBegin(GL_QUADS);
	glColor3f(1.0f,1.0f,0.0f);				// yellow	
	for(i=0;i<25;i=i+2)
	{
		cosine=cos(i*2*3.14159/100.0);
		sine=sin(i*2*3.14159/100.0);
		cosine2=cos((i+1)*2*3.14159/100.0);
		sine2=sin((i+1)*2*3.14159/100.0);         
		glVertex3f(cosine,sine,1);
		glVertex3f(cosine,sine,-1);
		glVertex3f(cosine2,sine2,-1);
		glVertex3f(cosine2,sine2,1);
	}
    glEnd();
}

If anyone could spot my error, I would appreciate the help.

I got the “radiused corner” working (caps and curved extrusion) and it looks good. :smiley:

I need now to figure out how to position these
quarter circles in each of the four cartesian plane quadrants.

This should be trivial, but nothing I try works.

If anybody knows how to do this, and can save me hours of work, I’d appreciate some guidance.

Aeluned was right when he said I’d have to dust off some old trig books. :smiley:

There are two ways to position these rounded welds.

you can either explicitely define the vertices to match some set of the vertices on the beam OR you can position them using a series of:

 
glPushMatrix();
glRotate();
glTranslate();
glScale();
DrawWeld();
glPopMatrix();
 

you may not need some or all of the given transformations above, depending on where your weld arc is defined in world space.

It’s difficult to give you definitive methods because I’m not sure exactly how you’ve implemented this.

This is what I ended up doing:

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | L_DEPTH_BUFFER_BIT);
    glPushMatrix();
    glTranslatef(trans[0], trans[1], trans[2]);
    glRotatef(rot[0], 1.0f, 0.0f, 0.0f);
    glRotatef(rot[1], 0.0f, 1.0f, 0.0f);
    glScalef(.5,.5,.5);// scale to 50%
    glTranslatef(0.0f, -0.0f, zoom); 
 

    drawRadiusedCornerQuadrant1(); //top left
    drawRadiusedCornerQuadrant2(); //top right
    drawRadiusedCornerQuadrant3(); //btm right
    drawRadiusedCornerQuadrant4(); //btm left
    
    glPopMatrix();
    glFlush();
    SwapBuffers(hDC);
}

I needed a separate function for each of the 4 positions, as I couldn’t figure out how to rotate the one generated figure in the other 3 positions.

I have these 4 corners in a separte project, and I now have to combine this in my existing “beam” code.

This is proving to be lots of work; still enjoying the challenge however.