Related
Hello so i am attempting to use a mouse function to move the perspective of gluLookAt to no luck so far i have attempted to adjust upX and upY based off of the mouse position however I want the program to be able to do an entire 360 rotation around the object based on the mouse movement and would like it to stop when the mouse movement in the window stops. Any help would be appreciated I am still learning
#include <iostream>
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
float posX=4, posY=6, posZ=5, targetX=0, targetY=0, targetZ=0, upX=0, upY=1, upZ=0;
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, 4.0/3.0, 1, 40);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(posX, posY, posZ, targetX, targetY, targetZ, upX, upY, upZ);
glColor3f(1.0, 1.0, 1.0);
glutWireTeapot(1.5);
glBegin(GL_LINES);
glColor3f(1, 0, 0); glVertex3f(0, 0, 0); glVertex3f(10, 0, 0);
glColor3f(0, 1, 0); glVertex3f(0, 0, 0); glVertex3f(0, 10, 0);
glColor3f(0, 0, 1); glVertex3f(0, 0, 0); glVertex3f(0, 0, 10);
glEnd();
glFlush();
}
void usage(){
std::cout<< "\n\n\
q,Q: Quit\n\n" ;
std::cout.flush();
}
void onMouseMove(int x, int y)
{
posX = x*cos(posY) + PosY*sin(PosX)*sin(yRot) - dz*cos(xRot)*sin(yRot)
glutPostRedisplay();
}
void KeyboardFunc (unsigned char key, int eyeX, int eyeY)
{
switch (key)
{
case 'q':
case 'Q':
exit(0);
break;
}
glutPostRedisplay();
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
usage();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(300,250);
glutInitWindowSize(800, 600);
glutCreateWindow("Final");
init();
glutDisplayFunc(display);
glutPassiveMotionFunc(&onMouseMove);
glutKeyboardFunc(&KeyboardFunc);
glutMainLoop();
}
If you want to implement an arcball camera, and you want to do it with the fixed-function pipeline matrix stack, it'd actually be simpler to not use gluLookAt() but glRotate/glTranslate, like so:
glTranslatef(0f, 0f, -radius);
glRotatef(angX, 1f, 0f, 0f);
glRotatef(angY, 0f, 1f, 0f);
glTranslatef(-targetX, -targetY, -targetZ);
where radius is the distance of the "camera" to the viewed point, angX is the angle around the X axis, angY the angle around the Y axis and (targetX, targetY, targetZ) is the position of the viewed point (your targetX/Y/Z).
You don't have to compute sin/cos yourself (it is computed by glRotatef) and all you have to do is set/increase angX and angY in your motion function.
I succesfully managed to rotate my object but I need to right click on the object to stop its rotation. I don't know how to make the object to rotate just around its center and then stop, I'll attach the code to see exactly what's happening with this shape. The problem, I think, is with the spinDisplay() function... the thing is that I need to rotate around its center on left mouse click and on the right mouse click I should change the color of the object....
#include <stdlib.h>
#include <math.h>
#include "dependente\freeglut\freeglut.h"
#include "dependente\glfw\glfw3.h"
#include <stdio.h> //incluziuni librarii
float ORG[3] = { 0,0,0 };
static GLfloat spin = 0.0;
GLfloat viewangle = 0, tippangle = 0, traj[120][3]; //variabila pentru unghi camera
GLfloat d[3] = { 0.1, 0.1, 0.1 }; //vector directie
GLfloat xAngle = 0.0, yAngle = 0.0, zAngle = 0.0;
bool draw_triangle = false; //variabila desenat figuri
bool draw_square = false;
bool draw_decagon = false;
void Triangle(void) //draw the triangle shape
{
glBegin(GL_TRIANGLE_FAN);//triangles have a common vertex, which is the central vertex
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(0.0f, 1.0f, 0.0f); //V0(red)
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); //V1(green)
glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(1.0f, -1.0f, 1.0f); //V2(blue)
glEnd();
}
void Square(void) {
glBegin(GL_QUADS);
glVertex2f(-1.0f, 1.0f); // top left
glVertex2f(1.0f, 1.0f); // top right
glVertex2f(1.0f, -1.0f); // bottom right
glVertex2f(-1.0f, -1.0f); // bottom left
glEnd();
}
void Decagon(void) //draw the decagon shape
{
glBegin(GL_POLYGON);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.72f,0.8f, 0.0f); //a1
glVertex3f(0.52f, 0.8f,0.0f); //z
glVertex3f(0.35f, 0.64f, 0.0f); //b1
glVertex3f(0.3f, 0.48f, 0.0f); //d1
glVertex3f(0.35f, 0.3f, 0.0f); //e1
glVertex3f(0.52f, 0.16f, 0.0f); //l1
glVertex3f(0.72f, 0.16f, 0.0f); //m1
glVertex3f(0.9f, 0.3f, 0.0f); //o1
glVertex3f(0.95f, 0.48f, 0.0f); //p1
glVertex3f(0.9f, 0.64f, 0.0f); //c1
glScalef(10, 10, 10);
glTranslatef(1, 2, 3);
glEnd();
}
void Keyboard(unsigned char key, int x, int y) //press a key to perform actions
{
switch (key) {
case 'd': d[0] += 0.1; break; //camera right
case 'a': d[0] -= 0.1; break; //camera left
case 'w': d[1] += 0.1; break; //camera up
case 's': d[1] -= 0.1; break; //camera down
case 'm': d[2] += 0.1; break; //magnify
case 'n': d[2] -= 0.1; break; //minify
case 't': draw_triangle = true; draw_decagon = false; break; //draw pyramid when key is pressed
case 'q': draw_square = true; draw_decagon = false; draw_triangle = false; break; //draw cube when key is pressed
case 'l': draw_decagon = true; draw_triangle = false; draw_square = false; break; //draw prism when key is pressed
case 'x': xAngle += 5; break; //modify x axis angle
case 'y': yAngle += 5; break; //modify y axis angle
case 'z': zAngle += 5; break; //modify z axis angle
default: printf(" Keyboard %c == %d", key, key); //see what key it's pressed
}
glutPostRedisplay();
}
void spinDisplay() //here it's the problematic function
{
spin = spin + 0.1;
if (spin > 360.0)
{
spin = 0.0;
}
glutPostRedisplay();
}
void mouse(int buton, int state, int x, int y)
{
switch (buton) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
glutIdleFunc(spinDisplay);
break;
case GLUT_RIGHT_BUTTON: //here I don't know how to change the color of the shape
glutIdleFunc(NULL);
default:glutIdleFunc(NULL);
break;
}
}
void redraw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glLoadIdentity();
glTranslatef(0, 0, -3);
glRotatef(tippangle, 1, 0, 0); // Up and down arrow keys 'tip' view.
glRotatef(viewangle, 0, 1, 0); // Right/left arrow keys 'turn' view.
glDisable(GL_LIGHTING);
glPushMatrix();
glTranslatef(d[0], d[1], d[2]); // Move box down X axis.
glScalef(0.7f, 0.7f, 0.7f); //increase the object size
glRotatef(zAngle, 0, 0, 1);
glRotatef(yAngle, 0, 1, 0);
glRotatef(xAngle, 1, 0, 0);
glRotatef(spin, 0.0, 0.0, 1.0);
if (draw_triangle)
Triangle();
if (draw_decagon)
Decagon();
if (draw_square)
Square();
glPopMatrix();
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(900, 600);
glutInitWindowPosition(300, 300);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("Figure Rotation");
glutDisplayFunc(redraw);
glutKeyboardFunc(Keyboard);
glutMouseFunc(mouse);
glClearColor(0.1, 0.0, 0.1, 1.0);
glMatrixMode(GL_PROJECTION);//specify which matrix is the current matrix, matrix that represents your camera's lens (aperture, far-field, near-field, etc).
gluPerspective(60, 1.5, 1, 10); //set up a perspective projection matrix
glMatrixMode(GL_MODELVIEW); //specify which matrix is the current matrix,matrix that represents your camera (position, pointing, and up vector).
glutMainLoop();
return 1;
}
Solely based on your code, the main problem is at Decagon() for its shape vertices definition.
As such vertices are defined not at the center of the shape itself but defined towards the top right, thus it won't rotate around itself but seem to orbit around the center although your sequence of matrix multiplications are working ok.
For simplicity, I would visualize centering it at 0,0 along xy plane, then define right half of its shape then mirror it back to the left one. You can take advantage of - minus sign. Implicitly take advantage of defining shape in NDC (Normalizd Device Coordinate) space.
Note: not exactly the same ratio as per your original definition, but to get you an idea. You can try swapping the following into yours, then it should rotate around itself.
glBegin(GL_POLYGON);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.25f, 0.5f, 0.0f);
glVertex3f(0.45f, 0.30f, 0.0f);
glVertex3f(0.55f, 0.0f, 0.0f);
glVertex3f(0.45f, -0.30f, 0.0f);
glVertex3f(0.25f, -0.5f, 0.0f);
glVertex3f(-0.25f, -0.5f, 0.0f);
glVertex3f(-0.45f, -0.30f, 0.0f);
glVertex3f(-0.55f, 0.0f, 0.0f);
glVertex3f(-0.45f, 0.30f, 0.0f);
glVertex3f(-0.25f, 0.5f, 0.0f);
//glScalef(10, 10, 10); // this won't have any effect on result
//glTranslatef(1, 2, -3);// the same
glEnd();
You have 2 options here
Completely change the vertices definition (only with Decagon to be similar to above relative to the origin). Other shapes are already good, it's defined relative to the origin.
Carefully determine the origin of the shape regardless of how your defined shape's vertices. Use such position to translate back the shape as part of matrix operation firstly before all other operations (please read on to know why).
Concept of rotation around itself
The concept of rotation around itself is that we need to do the following operations in order
Scale (in this case we don't have)
Rotation
Translation
Scaling although we don't have in this case, should be last otherwise it might affect other two operations.
If we translate first to the arbitrary position, then the rotation will happen around such point. In fact, rotation works relatively to the origin 0,0, thus we just need to do by any means to place the object back to origin first before we proceed, then we can rotate, translate to desire position it should be, and scale.
Let's see your matrix multiplication order
glScalef(0.7f, 0.7f, 0.7f); //increase the object size
glTranslatef(d[0], d[1], d[2]); // Move box down X axis.
glRotatef(zAngle, 0, 0, 1);
glRotatef(yAngle, 0, 1, 0);
glRotatef(xAngle, 1, 0, 0);
glRotatef(spin, 0.0, 0.0, 1.0);
This means we do the following in order
rotate around z-axis with spin angle
rotate around x-axis with xAngle angle
rotate around y-axis with yAngle angle
rotate around z-axis with zAngle angle
Although we could possibly combine the first and last together, but anyway it's ok.
Also you might want to further look at Euler Angles when we rotate around 3 cardinal axes like this, it can lead to Gimbal lock problem but it can be solved by limiting angles user can rotate around a certain axis.
The order is right. This is translated into mathematics terms as S * T * Rz * Ry * Rx * Rspin in which you can see it's inverse of the order in code. Rspin happen first, then Rx then so on.
Now what happen if Decagon shape is defined not relative to the origin, but defined to in the way that it translated to the right.
Take my vertices definition, but + 0.55f for all x position, we will have
glBegin(GL_POLYGON);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.80f, 0.5f, 0.0f);
glVertex3f(1.0f, 0.30f, 0.0f);
glVertex3f(1.10f, 0.0f, 0.0f);
glVertex3f(1.0f, -0.30f, 0.0f);
glVertex3f(0.80f, -0.5f, 0.0f);
glVertex3f(0.30f, -0.5f, 0.0f);
glVertex3f(0.10f, -0.30f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.1f, 0.30f, 0.0f);
glVertex3f(0.30f, 0.5f, 0.0f);
glEnd();
If you swap above code to your vertices definition, then it won't rotate around itself anymore. But we know that it takes -0.55f in x-axis to bring this shape back to origin, thus if we add glTranslatef(-0.55f, 0.0f, 0.0f) to be the first operation to execute then it will work the same.
We'd have
glScalef(0.7f, 0.7f, 0.7f);
glTranslatef(d[0], d[1], d[2]);
glRotatef(zAngle, 0, 0, 1);
glRotatef(yAngle, 0, 1, 0);
glRotatef(xAngle, 1, 0, 0);
glRotatef(spin, 0.0, 0.0, 1.0);
glTranslatef(-0.55f, 0.0f, 0.0f); // <------ add this
In short, translate target object to be at origin first before rotating (around itself), then proceed proper sequence as before.
If you desire to have such object to be located at the location you've defined the shape's vertices i.e. it's to the right +0.55f along x-axis and still rotate around itself. Then you use glTranslatef(d[0] + 0.55f, d[1], d[2]) instead.
Further Notes
The last two gl operations glScalef() and glTranslatef() won't have any effect as you already drew the shape. These two operations get discarded every frame when you call glLoadIdentity().
Just note that source code is still based on fixed-function pipeline of OpenGL. You might want to also take a look at modern programmable pipeline. This will allows you more flexibility in controlling virtual camera thus matrix operations are more clear cut and separated to the object itself whenever we need to move around. So this will make matrix operations easier to grasp, and to understand.
Edit
For additional control and satisfy application requirement as follows
Left click to rotate indefinitely, then left click again to stop
Right click to cycle through the color for rendered shape
We have to have control flags, and information for us to change at any frame time as follows.
bool isSpinning = false;
#define NUM_COLOR 4
int sCurrColor = 0;
GLfloat sColor[NUM_COLOR][3] = {
{1.0f, 1.0f, 1.0f},
{1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, 1.0f}
};
So for colors, we have white, red, blue, and green. Total in 4 colors, each color has 3 component values for RGB. We start with white color as seen in sCurrColor for our index.
Now your mouse() function would looks like this
void mouse(int buton, int state, int x, int y)
{
switch (buton) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN && !isSpinning)
isSpinning = true;
else if (state == GLUT_DOWN && isSpinning)
isSpinning = false;
break;
case GLUT_RIGHT_BUTTON: //here I don't know how to change the color of the shape
if (state == GLUT_DOWN)
sCurrColor = (sCurrColor + 1) % NUM_COLOR;
break;
default:glutIdleFunc(NULL);
break;
}
}
We optimized moving glutIdleFunc(spinDisplay); to be called inside main() function just before glutMainLoop(). As your requirements, we don't have to change it every frame.
Thus, spinDisplay() is now changed to be
void spinDisplay() //here it's the problematic function
{
if (isSpinning)
{
spin = spin + 3.0;
if (spin > 360.0)
{
spin = 0.0;
}
}
glutPostRedisplay();
}
Probably better to change the name of function to something like display() as it's more generic to not confuse that we have to spin everytime. Anyway, I didn't change this for the sake of brevity and consistency of your code.
Now the last part is to plug in sColor to be used by all those shapes in rendering. For example for Decagon you can do this
glColor3f(sColor[sCurrColor][0], sColor[sCurrColor][1], sColor[sCurrColor][2]);
This will be the same for other shapes if you like to have the same effect by right clicking to cycle through the color.
I am working on a project for mouse control to look around. I have been successful with rotating the camera using the mouse however I am trying to get the mouse to do 360 turns without the mouse leaving the screen before it can fully rotate. I read around and came across glutWarpPointer(), where most posts said to use it after getting the difference between the centre and the new mouse position in the window.
The issue this causes with my program is that when I move the mouse it will rotate very slightly for that frame the restart the location to the original point. Basically it i have a blue ball in front of me and green behind when i try to rotate towards the green ball the camera will move slightly but stay locked on the blue ball.
Is there a way to around or a fix?
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//rotate and translating the camera
glRotatef(-camVert, 1.0, 0.0, 0.0);
glRotatef(-camHor, 0.0, 1.0, 0.0);
glTranslatef(-posx,-posy,-posz);
//blue and green ball
glPushMatrix();
glColor3f(0.0, 1.0, 0.0);
glTranslatef(1, 0, 25);
glutSolidSphere(5, 20, 20);
glPopMatrix();
glPushMatrix();
glColor3f(0.0,0.0,1.0);
glTranslatef(0, 0, -25);
glutSolidSphere(5, 20, 20);
glPopMatrix();
};
void setAngle(float angy, float angx)
{
camVert = angy*1.5;
if (camVert > 90)
camVert = 90;
else if (camVert < -90)
camVert = -90;
camHor = angx*0.5;
}
void MoveCam(float distance, float direction)
{
float rads = (camHor+direction)*PI / 180;
posx -= sin(rads)*distance;
posz -= cos(rads)*distance;
};
void mouseMove(int x, int y)
{
float diffx = midx - x;
float diffy = midy - y;
setAngle(diffy,diffx);
//glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
}
I have two viewports that are currently display 4 points in each of their corners. One viewport (left side) has gray corners, the other (right) has red corners. The two viewports are placed next to each other, with the red viewport intentionally made smaller. The viewport with red corners is also drawing a GL_TRIANGLES.
You can see them here:
The points in the triangle should be in the bottom left corner, top left corner and bottom right corner of the red viewport, but the bottom right corner is significantly short.
I think the second (red) glViewport is still using measurements from a previous object, the other viewport probably.
Am I setting up the second viewport correctly?
I want to have the second viewport 100 pixels across, not 900 pixels, squeezed into 100 pixels.
Here is my code.
I am using the latest version of glut and currently still learning how to use OpenGL/glut.
// windows/pannels
int winWidth = 900; // window width
int winHeight = 600; // window height
int pannelToolsWidth = 100;
int pannelToolsHeight = winHeight;
int pannelToolsX = winWidth - pannelToolsWidth;
int pannelToolsY = 0;
int drawSpaceWidth = winWidth - pannelToolsWidth;
int drawSpaceHeight = winHeight;
// drawing
float red = 0.0f;
float green = 0.0f;
float blue = 0.0f;
float lineSize = 1.0f;
float pointSize = 1.0f;
// ...
// draws a pannel. Make sure to define a colour before calling.
void drawPannel(int x, int y, int width, int height)
{
glBegin(GL_TRIANGLES);
glVertex2f(float(x), float(y));
glVertex2f(float(x), float(height));
glVertex2f(float(width), 0.0);
glEnd();
//glBegin(GL_TRIANGLES);
// glVertex2f(, );
// glVertex2f(, );
// glVertex2f(, );
//glEnd();
}
// Starts a new glViewport and visualises the bounderies with coloured points.
// scene: id of the viewport (viewports draw different things)
// x/y: viewports draw from the bottom left corner
void drawViewport(int x, int y, int width, int height, float red, float green, float blue, int scene)
{
// draw viewport (colours used to visualise limits)
glViewport(x, y, width, height);
glColor3f(red, green, blue);
glBegin(GL_POINTS);
glVertex2f(0.0f, float(winHeight));
glVertex2f(float(winWidth), float(winHeight));
glVertex2f(0.0f, 0.0f);
glVertex2f(float(winWidth), 0.0f);
glEnd();
// draw viewport content. text methods should be called last because the glRasterPos2i() effects the viewport
switch (scene)
{
// add more cases for other viewports here.
case 0:
// colour
// drawing
// text
break;
case 1:
glColor3f(0.8, 0.8, 0.7);
drawPannel(0, 0, pannelToolsWidth, pannelToolsHeight);
break;
default:
// do nothing
break;
}
}
void init()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); //set clear background colour
glPointSize(10.0); //set point size
glColor3f(1.0f, 1.0f, 1.0f); //set draw colour
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, winWidth, 0, winHeight); //setup 2D projection
}
void collectScene()
{
glClear(GL_COLOR_BUFFER_BIT);
// viewport(s)
drawViewport(0, 0, drawSpaceWidth, drawSpaceHeight, 0.5, 0.5, 0.5, 0); // paint area
drawViewport(pannelToolsX, pannelToolsY, pannelToolsWidth, pannelToolsHeight, 1, 0, 0, 1); // GUI area
glFlush();
glutSwapBuffers(); //swap front and back buffers
}
//called when no event in queue
void idle()
{
glutPostRedisplay();
}
int main()
{
// create the window
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); // double buffer with RGBA
glutInitWindowSize(winWidth, winHeight);
glutInitWindowPosition(100, 100); // from top left
glutCreateWindow("Paint");
init();
glutDisplayFunc(collectScene);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}
Thank you
Projection matrix is relative to the viewport, indeed it is usually set after glViewport call. In your case it doesn't change.
I'm trying to play around with OpenGL and this is my very first code. How can I change to different view to 2 object drawn on the screen?
Is there anyway to do this manually, in stead of using function gluPerspective()?
I tried glRotatef(60, 0.0, 0.0, 5.0) but there is nothing happen. Cos I want to see other faces of the Pyramid and also different view of the rotating sphere.
Also I want to set different colours to different objects that I draw on the screen, how can I do that?
The code to set colour for each object, which is glColor3f, I put it in between glPushMatrix() and glPopMatrix(), also I always include the line glLoadIdentity() before starting draw objects on screen. As far as I know, this line will reset the settings of the previous objects and allows me to set new properties for new object.
Then why when I press button D, the sphere is blue when it supposes to be in white?
Here is my full code:
#include <windows.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <math.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#define X .525731112119133606
#define Z .850650808352039932
#define Y 0.0
#define PI 3.1415926535898
#define CIRCLE_STEP 5000
using namespace std;
// Open an OpenGL window
GLFWwindow* window;
int keyboard = 0, itr;
bool big_Sphere = true, sphereWithNormalV = false, animation = false;
GLdouble angle = 0;
/****Step 1: define vertices in (x, y, z) form****/
// Coordinates to draw a Icosahedron
GLfloat icoVertices[12][3] = {
{-X, Y, Z}, {X, Y, Z}, {-X, Y, -Z}, {X, Y, -Z},
{Y, Z, X}, {Y, Z, -X}, {Y, -Z, X}, {Y, -Z, -X},
{Z, X, Y}, {-Z, X, Y}, {Z, -X, Y}, {-Z, -X, Y}
};
// Coordinates to draw a Pyramid
GLfloat pyVertices[4][3] = {
{0.0f, 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, -1.0f}
};
static GLuint icoIndices[20][3] = {
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
static GLuint pyIndices[4][3] = {
{0,1,2}, {0,1,3}, {0,2,3}, {1,2,3}
};
/************************/
void normalize3f(float v[3]) {
GLfloat d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
if (d == 0.0) {
fprintf(stderr, "zero length vector");
return;
}
v[0] /= d; v[1] /= d; v[2] /= d;
}
void sphereNormalV(GLfloat p1[3], GLfloat p2[3], GLfloat p3[3])
{
glBegin(GL_LINES);
glVertex3f(p1[0] *1.5,p1[1] *1.5, p1[2] *1.5);
glVertex3fv(p1);
glEnd();
glBegin(GL_LINES);
glVertex3f(p2[0] *1.1,p2[1] *1.1, p2[2] *1.1);
glVertex3fv(p2);
glEnd();
glBegin(GL_LINES);
glVertex3f(p3[0] *1.1,p3[1] *1.1, p3[2] *1.1);
glVertex3fv(p3);
glEnd();
}
void drawtriangle(float *v1, float *v2, float *v3)
{
glBegin(GL_LINE_LOOP);
//glNormal3fv(v1);
glVertex3fv(v1);
//glNormal3fv(v2);
glVertex3fv(v2);
//glNormal3fv(v3);
glVertex3fv(v3);
glEnd();
}
void subdivide(GLfloat *v1, GLfloat *v2, GLfloat *v3, long depth)
{
GLfloat v12[3], v23[3], v31[3];
GLint i;
if (depth == 0){
drawtriangle(v1, v2, v3);
if (sphereWithNormalV == true){
sphereNormalV(v1, v2, v3);
}
return;
}
for (i = 0; i < 3; i++) {
v12[i] = v1[i]+v2[i];
v23[i] = v2[i]+v3[i];
v31[i] = v3[i]+v1[i];
}
normalize3f(v12);
normalize3f(v23);
normalize3f(v31);
subdivide(v1, v12, v31, depth-1);
subdivide(v2, v23, v12, depth-1);
subdivide(v3, v31, v23, depth-1);
subdivide(v12, v23, v31, depth-1);
}
void drawSphere(GLfloat x, GLfloat y, GLfloat z){
glLoadIdentity();
glPushMatrix();
if (big_Sphere == true){
glScaled(0.4, 0.55, 0.4);
}else{
glScaled(0.13, 0.18, 0.13);
}
if (animation){
glTranslatef(x, y, z);
}
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 20; i++) {
subdivide(&icoVertices[icoIndices[i][0]][0], &icoVertices[icoIndices[i][1]][0], &icoVertices[icoIndices[i][2]][0], 3);
}
glEnd();
glPopMatrix();
}
void drawPyramid(){//(GLfloat x, GLfloat y, GLfloat z){
glLoadIdentity();
glPushMatrix();
glScaled(0.13, 0.18, 0.13);
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 4; i++){
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3fv(pyVertices[pyIndices[i][0]]);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3fv(pyVertices[pyIndices[i][1]]);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3fv(pyVertices[pyIndices[i][2]]);
}
glEnd();
glPopMatrix();
}
int getKeyPressed(){
if (glfwGetKey(window, GLFW_KEY_A)){
keyboard = GLFW_KEY_A;
}
if (glfwGetKey(window, GLFW_KEY_B)){
keyboard = GLFW_KEY_B;
}
if (glfwGetKey(window, GLFW_KEY_C)){
keyboard = GLFW_KEY_A;
}
if (glfwGetKey(window, GLFW_KEY_D)){
keyboard = GLFW_KEY_D;
}
if (glfwGetKey(window, GLFW_KEY_E)){
keyboard = GLFW_KEY_E;
}
return keyboard;
}
void controlSphere(bool _big_Sphere, bool _sphereNormalV, bool _animation){
big_Sphere = _big_Sphere;
sphereWithNormalV = _sphereNormalV;
animation = _animation;
}
void gluPerspective(double fovy,double aspect, double zNear, double zFar)
{
// Start in projection mode.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
int main( void ) {
if (!glfwInit()){
fprintf(stderr, "Failed to initialize GLFW.\n");
return -1;
}
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(1100, 800, "Hello World", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "glfw failed to create window.\n");
//glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
glewInit();
if (glewInit() != GLEW_OK){
fprintf(stderr, "Failed to initialize GLEW: %s.\n", glewGetErrorString(glewInit()));
return -1;
}
// 4x anti aliasing
glfwWindowHint(GLFW_SAMPLES, 4);
/**Step 3: Main loop for OpenGL draw the shape**
/* Main loop */
int i = 0;
GLfloat pos_X, pos_Y;
glRotatef(60, 0.0f, 0.3f, 0.4f);
do{
//glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
switch(getKeyPressed()){
case 65:
controlSphere(true, false, false);
drawSphere(0, 0, 0);
break;
case 66:
controlSphere(true, true, false);
drawSphere(0, 0, 0);
break;
case 67:
// drawPyramid();
break;
case 68:
// drawing a Sphere moving in a circular path
controlSphere(false, false, true);
angle = 2*PI*i/CIRCLE_STEP;
pos_X = cos(angle) * 4.5;
pos_Y = sin(angle) * 4.5;
drawSphere(pos_X, pos_Y, 0);
i += 1;
angle += 1;
if (angle >= 360){
angle = 0;
}
// drawing a Pyramid rotate around its y axis
drawPyramid();
break;
default:
controlSphere(true, false, false);
drawSphere(0, 0, 0);
break;
}
Sleep(1);
// Swap front and back rendering buffers
glfwSwapBuffers(window);
//Poll for and process events
glfwPollEvents();
} // check if the ESC key was pressed or the window was closed
while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);
/***********************************************/
// Close window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
// Exit program
exit( EXIT_SUCCESS );
}
Is there anyway to do this manually, in stead of using function gluPerspective()?
I don't really understand this question. But if you want to set multiples objects (that have the same parameters) with different transformations, scale, rotation and/or translation, you need to push this to the stack and then draw the desired object. A good starting point can be found here: http://www.songho.ca/opengl/gl_transform.html
Also I want to set different colours to different objects that I draw on the screen, how can I do that?
Your sphere is blue because the last call for glColor3f() was in drawPyramid().
You can change the color of your ball by just calling glColor3f (1.0f, 1.0f, 1.0f); in the beginning of its draw function:
void drawSphere (GLfloat x, GLfloat y, GLfloat z)
{
glColor3f (1.0f, 1.0f, 1.0f);
...
}
A really great site to learn OpenGL from the old pipeline (what you just implemented) to the new (GLSL) is http://www.lighthouse3d.com/tutorials/.
You are looking for Multiple viewports which allows the to split the screen. In your case two different viewports two different cameras(one for each) will be enough.
Check this post.