Click to See Complete Forum and Search --> : solid 3d cube (problem, haha)


Calculator
November 3rd, 2006, 05:45 PM
I have an object I defined as a cube which is for quadrilaterals as the faces,I couldn't figure out a cleverway to make it use a quad_strip with the vertices. Whatever. So, then I have a draw routine for it.

void cube::draw(void)
{
glLoadIdentity();

glTranslatef(0.0f, 0.0f, -0.2f);
glRotatef(rotate / 2, 0, 1, 0);
glRotatef(rotate, 1, 0, 0);

glBegin(GL_QUADS);

for(int i = 0; i < 6; ++i)
{
glColor3f(colors[i].x, colors[i].y, colors[i].z);

for(int k = 0; k < 4; ++k)
{
glVertex3f(faces[i][k].x, faces[i][k].y, faces[i][k].z);
}
}

glEnd();
}

And it does some wierd stuff. Dude! Like, so the thing is all rotating around n stuff. And then it seems like when some face is facing us, it may be drawn earlier than the one that is the back face, and then the backfaceappears to be the front. It's kind of hard to describe, it looks like that wierd figure-ground illusion with the wire cube with things jumping to the front and all. Here's a screenshot of it.

http://img.photobucket.com/albums/v221/Tonto1/untitled-1.jpg

I want to figure out how to make it just look like a solid cube instead of sometimes being able to 'see through it' or the illusion of that because things are drawn in front. Or, that'smy wierd hypothesis. Any ideas?

macklin01
November 3rd, 2006, 06:22 PM
You need to define normal vectors for each vertex; that's probably the cause of the strange rendering. Another thing that may be contributing is whether or not each face is being traced out in a righthand, counterclockwise way. (i.e., lower left, lower right, upper right, upper left). If you mistakenly order the vertices, the faces will become "twisted". Also, IIRC, since you haven't manually specified the normal vectors, OpenGL will try to calculate them based upon the ordering of your vertices. (Again, misordered vertices will have a negative impact here.)

I'd write a single DrawCube() routine to put a single cube at the origin with edge length 1, and then use transformations to give it the proper location and orientation. (I thought about QUAD_STRIP, but the problem is that you really want two normals for each vertex: once as a part of one face, then once as a part of the next face. Then, you need end caps as well.)

Something like this:

void DrawCube( void )
{
glBegin( GL_QUADS );
glNormal3f( 1,0,0 ); // OpenGL is a state machine
glVertex3f( .5, .5 , .5 );
glVertex3f( .5, -.5 , .5 );
glVertex3f( .5, -.5 , -.5 );
glVertex3f( .5, .5 , -.5 );

glNormal3f( 0,0,-1 );
glVertex3f( -.5, .5 , -.5 );
glVertex3f( .5, .5 , -.5 );
glVertex3f( .5, -.5 , -.5 );
glVertex3f( -.5, -.5 , -.5 );

glNormal3f( -1,0,0 );
glVertex3f( -.5, .5 , .5 );
glVertex3f( -.5, .5 , -.5 );
glVertex3f( -.5, -.5 , -.5 );
glVertex3f( -.5, -.5 , .5 );

glNormal3f( 0,0,1 );
glVertex3f( .5, -.5 , .5 );
glVertex3f( .5, .5 , .5 );
glVertex3f( -.5, .5 , .5 );
glVertex3f( -.5, -.5 , .5 );

glNormal3f( 0,1,0 );
glVertex3f( -.5, .5 , .5 );
glVertex3f( .5, .5 , .5 );
glVertex3f( .5, .5 , -.5 );
glVertex3f( -.5, .5 , -.5 );
glEnd();
}

I see that you're building a cube class, so you'll want to do this accordingly. But this will give you the basic idea. You can use your edges to determine the proper axis and angle of rotation, however, and greatly simplify your normal vector calculations. Otherwise, you can write a cross-product routine and calculate them for each face. If you choose to do that, you might consider adding the six normal vectors as data members of your class so that you don't have to re-compute them every single time you plot. (Much more efficient.) -- Paul

Calculator
November 3rd, 2006, 07:10 PM
Wow. Awesome information, thank you.

Just off-topic, I'm a senior in high school and was in California recently and I was touring some of the UC's and visited UC Irvine. I really liked the school, I just walked around campus and whatever, and was very impressed, and will probably apply there (though I don't expect to get in being an out-of-stater with low grades relying on test scores).

Also, I looked at your easybmp stuff, and I just opened the data file PHIcsv in notepad for the DataPlotter sample you made and my monitor (some dell flatscreen) totally started making a noticable high pitched noise like a TV being on. And I could flip back and forth from notepad and the sound will go on and off. It's so wierd!

macklin01
November 3rd, 2006, 07:48 PM
Hey, not a problem.

I can't guarantee that it's 100% correct, but hopefully it'll point you in the right direction. ;) OpenGL is a lot of fun, and I hope you keep working with it. (I'm actually toying with OpenGL this afternoon because I want to make some cool 3D animations for a PowerPoint presentation.)

On the off-topics:
I'm glad you gave EasyBMP a try. I hope you like it. Be on the lookout for an update to the extension package, which includes OpenGL routines. In particular, I wrote routines for screenshots and generating sequentially-ordered movie frames at a constant framerate. (i.e., turn a camera on during an OpenGL animation to record it.) I'll probably release that next week.

It's strange to hear about the DataPlotter and Monitor noise, especially because it's just a command-line program that doesn't do any screen output. Is the noise generated when you run the program, or when you view the output image?

One thing you'll notice when watching TV late at night in a quiet house is that the sound from the TV can change when you go from a black screen to a white screen, or otherwise suddenly change the picture, as between commercials. I can only guess that the plentitude of bright colors in the output plot may be causing some of the electronics in the monitor to vibrate.

Strangely enough, I've gotten flat panel noise when viewing certain images if the power supply happens to be just wrong. I found that unpluggin the monitor from my UPS (same circuit at computer) and plugging it into another surge protector eliminated the noise. Electronics are strange, and I suppose if you happen to get just the right signals to sync with the power in just the right way, you can get vibrations.

Regarding UCI, best of luck! I've really enjoyed my time here, and it's a great place to be. They're really booming here with a lot of infrastructural improvements, and they're building up good programs like crazy! Best of luck as you apply.

And nice to meet you. :) -- Paul

Calculator
November 3rd, 2006, 10:18 PM
I realized one more problem with the program, which is that the diagonal of the cube is 3^1/2 yet the corner that it's rotating around is only -1 deep into the page. So, I think that's what the screen shot captures which is a corner of the cube coming out of the screen. I believe the problem that I was thinking of with the faces is more due to what you described and gave solutions for, and what I will still try to implement.

And that noise occured when I viewed the data file for the dataplotter (out of curiosity for what was making that crazy image) and then it made the little squeal. It was viewed in notepad. This monitor has a notoriously bad power supply and the little box on the cable always gets crazy hot. So that could be the problem.

Calculator
November 9th, 2006, 05:47 PM
It still does not seem to be working completely. I made all the vertices oriented counter-clockwise, and normal calculations and stuff, but it seems to no effect on the cube. I fill up the cube in this way.

// Backface
faces[5][0] = point(b.x, a.y, b.z);
faces[5][1] = point(a.x, a.y, b.z);
faces[5][2] = point(a.x, b.y, b.z);
faces[5][3] = point(b.x, b.y, b.z);

// Rightsideface
faces[4][0] = point(b.x, a.y, b.z);
faces[4][1] = point(b.x, a.y, a.z);
faces[4][2] = point(b.x, b.y, a.z);
faces[4][3] = point(b.x, b.y, b.z);

//Leftsideface
faces[3][0] = point(a.x, a.y, a.z);
faces[3][1] = point(a.x, a.y, b.z);
faces[3][2] = point(a.x, b.y, b.z);
faces[3][3] = point(a.x, b.y, a.z);

// Frontface
faces[2][0] = point(b.x, a.y, a.z);
faces[2][1] = point(a.x, a.y, a.z);
faces[2][2] = point(a.x, b.y, a.z);
faces[2][3] = point(b.x, b.y, a.z);

// Topface
faces[1][0] = point(b.x, a.y, b.z);
faces[1][1] = point(a.x, a.y, b.z);
faces[1][2] = point(a.x, a.y, a.z);
faces[1][3] = point(b.x, a.y, a.z);

// Bottomface
faces[0][0] = point(b.x, b.y, b.z);
faces[0][1] = point(a.x, b.y, b.z);
faces[0][2] = point(a.x, b.y, a.z);
faces[0][3] = point(b.x, b.y, a.z);

// Colors dude
colors[0] = point(1.0f, 0.0f, 0.0f);
colors[1] = point(0.0f, 1.0f, 0.0f);
colors[2] = point(0.0f, 0.0f, 1.0f);
colors[3] = point(0.5f, 0.0f, 0.0f);
colors[4] = point(0.0f, 0.6f, 0.0f);
colors[5] = point(0.0f, 0.0f, 0.5f);

cnormals();

int cube::cnormals()
{
normals[5] = point(0, 0, -1);
normals[4] = point(1, 0, 0);
normals[3] = point(-1, 0, 0);
normals[2] = point(0, 0, 1);
normals[1] = point(0, 1, 0);
normals[0] = point(0, -1, 0);

/*for(int i = 0; i < 6; ++i)
{
point
f1 = faces[i][0],
f2 = faces[i][1],
f3 = faces[i][2];

point p, q;

q.x = f2.x - f1.x;
q.y = f2.y - f1.y;
q.z = f2.z - f1.z;

p.x = f3.x - f1.x;
p.y = f3.y - f1.y;
p.z = f3.z - f1.z;

normals[i].x = p.y * q.z - p.z * q.y;
normals[i].y = p.z * q.x - p.x * q.z;
normals[i].z = p.x * q.y - p.y * q.x;

char buf[256];
sprintf(buf, "%d, %d, %d\n", normals[i].x, normals[i].y, normals[i].z);
OutputDebugString(buf);
}*/



return 0;
}

Still wierd overlaps. Clipping plane issue is resolved though.

Calculator
November 30th, 2006, 03:52 AM
Just thought I'd post my final implementation of these cube's as planets.

class CPlanet : public CThing
{

public:

CPlanet( const CPoint & center, const CVector & velocity, double radius, double mass );
CPlanet( double x, double y, double z, double radius, double mass );
virtual ~CPlanet( void );

virtual void draw( void ) const;
virtual void update( double dt );



private:

void initialize( const CPoint & center, double radius );

CPoint _faces[6][4];
CPoint _normals[6];

};

CPlanet::CPlanet( const CPoint & center, const CVector & velocity, double radius, double mass )
: CThing( center, velocity, mass )
{
initialize( center, radius );
}

CPlanet::CPlanet( double x, double y, double z, double radius, double mass )
: CThing( x, y, z, mass )
{
initialize( CPoint(x, y, z), radius );
}

void CPlanet::initialize( const CPoint & center, double radius )
{
double hs = radius * std::sqrt( 2.0 ) / 2;

// Frontsideface
_faces[0][0] = CPoint( center.x - hs, center.y + hs, center.z + hs );
_faces[0][1] = CPoint( center.x - hs, center.y - hs, center.z + hs );
_faces[0][2] = CPoint( center.x + hs, center.y - hs, center.z + hs );
_faces[0][3] = CPoint( center.x + hs, center.y + hs, center.z + hs );

// Backsideface
_faces[1][0] = CPoint( center.x + hs, center.y + hs, center.z - hs );
_faces[1][1] = CPoint( center.x + hs, center.y - hs, center.z - hs );
_faces[1][2] = CPoint( center.x - hs, center.y - hs, center.z - hs );
_faces[1][3] = CPoint( center.x - hs, center.y + hs, center.z - hs );

// Leftsideface
_faces[2][0] = CPoint( center.x - hs, center.y + hs, center.z - hs );
_faces[2][1] = CPoint( center.x - hs, center.y - hs, center.z - hs );
_faces[2][2] = CPoint( center.x - hs, center.y - hs, center.z + hs );
_faces[2][3] = CPoint( center.x - hs, center.y + hs, center.z + hs );

// Rightsideface
_faces[3][0] = CPoint( center.x + hs, center.y + hs, center.z + hs );
_faces[3][1] = CPoint( center.x + hs, center.y - hs, center.z + hs );
_faces[3][2] = CPoint( center.x + hs, center.y - hs, center.z - hs );
_faces[3][3] = CPoint( center.x + hs, center.y + hs, center.z - hs );

// Topsideface
_faces[4][0] = CPoint( center.x + hs, center.y + hs, center.z - hs );
_faces[4][1] = CPoint( center.x + hs, center.y + hs, center.z + hs );
_faces[4][2] = CPoint( center.x - hs, center.y + hs, center.z + hs );
_faces[4][3] = CPoint( center.x - hs, center.y + hs, center.z - hs );

// Bottomsideface
_faces[5][0] = CPoint( center.x - hs, center.y - hs, center.z + hs );
_faces[5][1] = CPoint( center.x - hs, center.y - hs, center.z - hs );
_faces[5][2] = CPoint( center.x + hs, center.y - hs, center.z - hs );
_faces[5][3] = CPoint( center.x + hs, center.y - hs, center.z + hs );
}

CPlanet::~CPlanet( void )
{
}

void CPlanet::draw( void ) const
{
glTranslated( _displacement.x, _displacement.y, _displacement.z );
glBegin( GL_QUADS );

for( int i = 0; i < 6; ++i )
{
glColor3d( 1, 1, 1 );
for( int j = 0; j < 4; ++j )
{
glVertex3d( _faces[i][j].x, _faces[i][j].y, _faces[i][j].z );
}
}

glEnd();
}

void CPlanet::update( double dt )
{
_velocity += _acceleration * dt;
_displacement += _velocity * dt;
}

Pretty simple. I optimally, I want to learn to make my point class that's essentially like class p { double x, y, z; }; able to be converted to an array to be used in the [v] dealio's of the gl functions.