I have an array that contains 0's and 1's and based on the value of the array I want to draw a square and fill it with a color. I have the follow code below, but it only makes 1 square in the middle of the screen. I feel like there is something I need to do with glVertex2f() but I'm kind of stumped.
The end result is something like this
but my code is just one square colored.
for (int i = 0; i < Width; i++) {
for (int j = 0; j < Height; i++) {
if (myArray[i][j] == 0) {
glColor(1.1, 1.1, 1.1);
} else {
glColor(2.2, 2.2, 2.2);
}
glBegin(GL_QUADS);
glVertex2f(-0.2, 0.2);
glVertex2f(0.2, 0.2);
glVertex2f(0.2, 0.2);
glVertex2f(-0.2, 0.2);
glEnd;
}
}
You are drawing all of your squares in the same spot - you need to space them out.
Try adding a translate in front of each draw. Something like:
glPushMatrix();
glTranslatef(2. * i, 2. * j, 0.0) ;
glBegin(GL_QUADS) ;
...
glPopMatrix() ;
Related
I am using OpenGL in WinAPI to create a 2D line graph. My points are plotted in point size 8, and I want to adjust the height of the plotted points (and the line connecting them) so that the bottom of the point is at the proper y-position (i.e., so that a point at 0 isn't split by the x-axis).
I had an adjustment hard-coded, but I would rather have it scale with the plotted point size, so that when it's plotted in a different size window, it works the same.
Here is my method for plotting the points and the line connecting them:
void plotScores() {
if (samples > 1) { //if this is at least the second score, connect the scores with a line
glLineWidth(12.0);
GLdouble lineXPos = 0, lineYPos = 0;
glColor3d(0.3, 0.3, 0.3);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < scores.size(); i++) {
lineXPos = (i * 0.05) - 0.88;
lineYPos = ((scores[i] - 0.5) * 1.6); //need to adjust this for line y-position...
glVertex2d(lineXPos, lineYPos);
}
glEnd();
}
for (int i = 0; i < scores.size(); i++) {
GLdouble pointXPos = (i * 0.05) - 0.88;
GLdouble pointYPos = ((scores[i] - 0.5) * 1.6); //...and this for point y-position
if (scores[i] >= threshold) {
glColor3d(0.0, 1.0, 0.2);
}
else {
glColor3d(1.0, 0.2, 0.0);
}
glBegin(GL_POINTS);
glVertex2d(pointXPos, pointYPos);
glEnd();
}
}
You set the point size with glPointSize, so you should know that value. If you want to query it afterwards for some reason, it can be done with glGet and GL_POINT_SIZE enum.
I had drawn a circle in opengl using lines.But it shows a pattern of holes at outer edges.
I want to fill this holes without reducing the radius and increasing the number of samples.
This is my code:
void drawcirc(float xi,float yj,float r1,int num1)
{
glClear(GL_COLOR_BUFFER_BIT);
//glBegin(GL_LINES);
glVertex2f(0,0);
for (int i=0;i<=num1;i++)
{
float theta=2.0f*3.141592f*float(i)/float(num1);
float x1=r1*cosf(theta);
float y1=r1*sinf(theta);
glBegin(GL_LINES);
glVertex2f(0,0);
glVertex2f(xi+x1,yj+y1);
glEnd();
sleep(5000);
glFlush();
}
}
then function call drawcirc(0, 0, 0.6, 1250);
what to do? this is my o/p with holes at outer edges.
Okay, well you're not really drawing a circle. GL_LINES will go from point to point until the primitive ends
You draw a line from 0,0 to a point on the rim of the circle + the offset you give the function.
So you're drawing the spokes of a wheel essentially, the holes at the edge are the gaps between the spokes.
AlecTeal already answered what is going on. I give you the fix:
#include <math.h>
void drawFilledCircle(float xi,float yj,float r1,int num1)
{
glBegin(GL_TRIANGLE_FAN);
glVertex2f(0,0);
for(int i = 0; i <= num1; i++)
{
float theta = 2.0f*M_PI * float(i)/float(num1);
float x1 = r1*cosf(theta);
float y1 = r1*sinf(theta);
glVertex2f(xi+x1,yj+y1);
}
glEnd();
}
void drawCircle(float xi,float yj,float r1,int num1)
{
glBegin(GL_LINE_LOOP);
for(int i = 0; i < num1; i++)
{
float theta = 2.0f*M_PI * float(i)/float(num1);
float x1 = r1*cosf(theta);
float y1 = r1*sinf(theta);
glVertex2f(xi+x1,yj+y1);
}
glEnd();
}
A few hints:
Never put glFlush, glClear, sleep or similar into function intended to draw a geometrical shape. You want to be able to call such functions from higher level drawing code and such calls are highly disruptive.
glBegin and glEnd are deprecated, their use has been discouraged for well over 15 years now. Better use vertex arrays.
If you must use glBegin/glEnd put them outside of the loop, not inside it.
Update
It appears as though my normals are working fine, and it's something with how I'm drawing my faces (only half are being drawn), and I can't figure out why -
If you could take a look at my code from before (shown below)
Original post
I'm currently working on a parser/renderer for .obj file types. I'm running into an issue with displaying the normal vectors:
Without normals:
With normals:
For some reason, I cannot figure out why only half of the normal vectors are having an effect, while the other half act as if there isn't a face at all.
Here is my code for loading in the obj file:
void ObjModel::Load(string filename){
ifstream file(filename.c_str());
if(!file) return;
stringstream ss;
string param, line;
float nparam, cur;
vector<vector<float> > coords;
vector<float> point;
while(getline(file, line)){
ss.clear();
ss.str(line);
ss >> param;
//vertex
if(param == "v"){
for(int i = 0; i < 3; i++){
ss >> nparam;
this->vertices.push_back(nparam);
}
}
//face
else if(param == "f"){
coords.clear();
point.clear();
for(int i = 0; i < 3; i++){
ss >> nparam;
nparam--;
for(int j = 0; j < 3; j++){
cur = this->vertices[nparam * 3 + j];
this->faces.push_back(cur);
point.push_back(cur);
}
coords.push_back(point);
}
point = this->ComputeNormal(coords[0], coords[1], coords[2]);
for(int i = 0; i < 3; i++) this->normals.push_back(point[i]);
}
else continue;
}
}
void ObjModel::Render(){
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &this->faces[0]);
glNormalPointer(GL_FLOAT, 0, &this->normals[0]);
glDrawArrays(GL_TRIANGLES, 0, this->faces.size() / 3);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
And here is the function to calculate the normal vector:
vector<float> ObjModel::ComputeNormal(vector<float> v1, vector<float> v2, vector<float> v3){
vector<float> vA, vB, vX;
float mag;
vA.push_back(v1[0] - v2[0]);
vA.push_back(v1[1] - v2[1]);
vA.push_back(v1[2] - v2[2]);
vB.push_back(v1[0] - v3[0]);
vB.push_back(v1[1] - v3[1]);
vB.push_back(v1[2] - v3[2]);
vX.push_back(vA[1] * vB[2] - vA[2] * vB[1]);
vX.push_back(vA[2] * vB[0] - vA[0] * vB[2]);
vX.push_back(vA[0] * vB[1] - vA[1] * vB[0]);
mag = sqrt(vX[0] * vX[0] + vX[1] * vX[1] + vX[2] * vX[2]);
for(int i = 0; i < 3; i++) vX[i] /= mag;
return vX;}
I've checked already to make sure that there are an equal number of normal vectors and faces (which there should be, if I'm right).
Thank you in advance! :)
Edit Here is how I am enabling/disabling features of OpenGL:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
GLfloat amb_light[] = 0.1, 0.1, 0.1, 1.0 ;
GLfloat diffuse[] = {0.6, 0.6, 0.6, 1};
GLfloat specular[] = {0.7, 0.7, 0.3, 1};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb_light);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_SMOOTH);
glLightModeli(L_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDisable(GL_CULL_FACE);
Are you using elements? Obj files start counting at 1 but OpenGL starts counting at 0. Just subtract 1 from each element and you should get the correct rendering.
The orientation of normals matters. It looks like the face orientation of your object is not consistens, so the normals of neighbor faces, with similar planes, point in opposite directions.
If you imported that model from a model file, I suggest you don't calculate the normals in your code – you should not do this anyway, since artists may make manual adjustments to the normals to locally fine tune illumination – but store them in the model file as well. All 3D modellers have a function to flip normals into a common orientation. In Blender e.g. this function is reached with the hotkey CTRL + N in edit mode.
for(int i = 0; i < 3; i++) this->normals.push_back(point[i]);
That only provides one normal for each face. You need one normal for each vertex.
I am trying to create a 3D box, that would play the role of a playing board/surface/room for a 3D game in C++, using OpenGl. As a starting point I found some code that does that for a 2D surface. My question would be how to modify the following code to serve my purpose:
for (float i = -width; i + 0.1 <= width; i += 0.1) {
for (float j = -height; j + 0.1 <= height; j+= 0.1) {
glBegin(GL_QUADS);
glNormal3f(0, 1, 0);
glVertex3f(i, 0, j);
glVertex3f(i, 0, j + 0.1);
glVertex3f(i + 0.1, 0, j + 0.1);
glVertex3f(i + 0.1, 0, j);
glEnd();
}
}
Thanks a lot.
You can either use above code 6 times but each time apply different rotation/translation matrix, or you can do it the right way and generate correct geometry for missing 5 walls of your box. There are lots of samples for drawing cubes, ie.:
http://www.opengl.org/resources/code/samples/glut_examples/examples/examples.html
I have a pretty straightforward question. We are asked to make a checkerboard using glRecti in c++ using visual basic 2010. Here's what I have so far and was wondering if anyone can point me in the right direction.
#include <gl/glut.h>
void myInit(void)
{
glClearColor(1.0,1.0,1.0,0.0); // set white background color
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 640.0, 0.0, 480.0);
}
void drawChecker(int size)
{
int i = 0;
int j = 0;
for (i = 0; i < 7 ; i++) {
if((i + j)%2 == 0) // if i + j is even
glColor3f( 0.4, 0.2, 0.6);
else
glColor3f( 0.2, 0.3, 0.4);
glRecti(i*size, j*size, size, size); // draw the rectangle
j++;
}
glFlush();
}
void checkerboard(void) {
glClear(GL_COLOR_BUFFER_BIT); // clear the screen
drawChecker(32);
}
void main(int argc, char** argv)
{
glutInit(&argc, argv); // initialize the toolkit
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // set display mode
glutInitWindowSize(640,480); // set window size
glutInitWindowPosition(100, 150); // set window position on screen
glutCreateWindow("null"); // open the screen window
glutDisplayFunc(checkerboard); // register redraw function
myInit();
glutMainLoop(); // go into a perpetual loop
}
You should try
for (i = 0; i < 8 ; ++i) {
for (j = 0; j < 8; ++j) {
if((i + j)%2 == 0) // if i + j is even
glColor3f( 0.4, 0.2, 0.6);
else
glColor3f( 0.2, 0.3, 0.4);
glRecti(i*size, j*size, (i+1)*size, (j+1)*size); // draw the rectangle
}
}
You should think if you would rather want to let i and j go to 7 and not to 6, which would make a real checkerboard. Remember that the loop is repeated as long as i is lower than 7 (therefore it is done for i from 0 to 6). Therefore I changed the 7 to 8. If the 7 was really intended, then excuse me for taking this freedom.
Furthermore are the last two arguments not the size of the rectangle, but its opposite vertex, therfore the use of i+1 and j+1.