Draw and Rotate an Arrow - c++

I am trying to draw an arrow using the style below but this arrow should be also rotated according to a condition (need to pass the degree for each condition). I can draw the rectangle and a triangle but I cannot draw the triangle as an arrowhead. Also, how can I include the rotation degree into the code? Is there any easier way to draw an arrow and rotate it?
int triangleRect=4, triangleTri=3, lineWidth=3;
double twicePi = 2.0f * M_PI, angle_offsetR =1.5* M_PI/2, radius = 0.05,
xR=m_start.x(), y=m_start.y(), xT=m_start.x()+ m_rect_width;
glColor3f(0,1,0);
glLineWidth(lineWidth);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MULTISAMPLE);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glBegin(GL_TRIANGLE_FAN);
//RECTANGLE
for(int i = 0; i <= triangleRect; i++) {
glVertex2f((xR + (radius * cos(i * twicePi / triangleRect + angle_offsetR)))* m_parent_width_function(),
(y + (radius * sin(i * twicePi / triangleRect + angle_offsetR)))* m_parent_height_function());
}
// TRIANGLE
for(int i = 0; i <= triangleTri; i++) {
glVertex2f((xT + (radius * cos(i * twicePi / triangleTri + angle_offsetR)))* m_parent_width_function(),
(y + (radius * sin(i * twicePi / triangleTri + angle_offsetR)))* m_parent_height_function());
}
glEnd();

You accidentally add angle_offsetR to the angle for the triangle vectors. Furthermore you've to restart a GL_TRIANGLE_FAN primitiv when you draw an new shape (see Triangle primitives).
If you want to rotate the model, then set the add a rotation around the z axis to the model view matrix by glRotatef.
Do not translate and scale the vertex coordinates. Use glScale and glTranslate. The matrix transformations are not commutative, the order matters:
float angle_of_roation = 30.0; // 30°
glPushMatrix();
// scale
glScalef( m_parent_width_function(), m_parent_height_function(), 1.0f);
// move triangle and rectangle to the position in the world
glTranslatef(xR, y, 0.0f);
// roatate triangle and rectangle
glRotatef(angle_of_roation, 0, 0, 1);
//RECTANGLE
glBegin(GL_TRIANGLE_FAN);
for(int i = 0; i <= triangleRect; i++) {
float angle = i * twicePi / triangleRect + angle_offsetR;
glVertex2f(radius * cos(angle), radius * sin(angle));
}
glEnd();
glPushMatrix();
// translate triangle relative to rectangle
glTranslatef(xT-xR, 0.0f, 0.0f);
// TRIANGLE
glBegin(GL_TRIANGLE_FAN);
for(int i = 0; i <= triangleTri; i++) {
float angle = i * twicePi / triangleTri;
glVertex2f(radius * cos(angle), radius * sin(angle));
}
glEnd();
glPopMatrix();
glPopMatrix();

Related

My FPS camera is going crazy what I should do to fix it? Also Warning C26451 Arithmetic overflow

NOTE I know that my plane and the cylinder are badly built but their purpose is just to have something to see on the screen. Considering (px,py,pz), the camera position, and (dx, dy, dz), the view direction.
Important: My camera should follow a structure similar to the one I implemented here, so I can't use glRotate, glTranslate everything has to be done manually, the imposition of my teacher sadly, And also I am using Visual Studio.
FIX: My translations are all ok now I fixed a thing in the case GLUT_KEY_LEFT and GLUT_KEY_RIGTH.
Problem: Now the remaning problem is in the mouse_motion, when I click with left mouse button and drag the mouse around the screen my camera changes it direction really fast and sometimes when I go up it faces down its strange and hard to describe XD.
Warning: Warning C26451 Arithmetic overflow: Using operator '+' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '+' to avoid overflow (io.2). class2 main.cpp 199 .
This is my the line that says gluLookAt(px, py, pz, px+dx, py+dy, pz+dz, 0.0f, 1.0f, 0.0f); How can I fix it?
Camera: I just want the motion of the mouse to allow me to define the direction I want to go and use the up, down, left, right keys to move.
#include <math.h>
#include <ctime>
#include <iostream>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#define PI 3.1415926535897932384626433832795
//For Camera
#define GlUT_KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
// angle of rotation for the camera direction
float angle = 0.0f; //alpha
float angle1 = 0.0f; //beta
// actual vector representing the camera's direction
float dx = 0.0f;
float dy = 0.0f;
float dz = 1.0f;
// XZ position of the camera
float px = 0.0f;
float py = 0.0f;
float pz = 10.0f;
float speed = 1.0f;
float rotateSpeed = 0.0008f;
//For FPS
int timebase;
float frame;
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short
// (you cant make a window with zero width).
if(h == 0)
h = 1;
// compute window's aspect ratio
float ratio = w * 1.0 / h;
// Set the projection matrix as current
glMatrixMode(GL_PROJECTION);
// Load Identity Matrix
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set perspective
gluPerspective(45.0f ,ratio, 1.0f ,1000.0f);
// return to the model view matrix mode
glMatrixMode(GL_MODELVIEW);
}
// Draw Figures
void drawAxis() {
glBegin(GL_LINES);
// X axis in Red
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(100.0f, 0.0f, 0.0f);
glVertex3f(-100.0f, 0.0f, 0.0f);
// Y Axis in Green
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 100.0f, 0.0f);
glVertex3f(0.0f, -100.0f, 0.0f);
// Z Axis in Blue
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 100.0f);
glVertex3f(0.0f, 0.0f, -100.0f);
glEnd();
}
void drawPlane(float width) {
width/=2;
glBegin(GL_TRIANGLE_FAN);
glColor3f(4.0f, 1.0f, 1.0f);
glVertex3d(width, 0,width);
glVertex3d(width, 0, -width);
glVertex3d(-width, 0,-width);
glColor3f(3.0f, 1.0f, 0.0f);
glVertex3d(width, 0, width);
glVertex3d(-width, 0, -width);
glVertex3d(-width, 0, width);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3d(width, 0, -width);
glVertex3d(width, 0, width);
glVertex3d(-width, 0, -width);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3d(-width, 0, -width);
glVertex3d(width, 0, width);
glVertex3d(-width, 0, width);
glEnd();
}
void drawCylinder(float radius, float height, int slices) {
float interval = 2 * PI / slices;
float next_a, next_h;
for (float a = 0; a < 2 * PI; a += interval) {
next_a = a + interval;
if (next_a > 2 * PI) {
next_a = 2 * PI;
}
glBegin(GL_TRIANGLES);
//Top
glColor3f(0.698f, 0.133f, 0.133f);
glVertex3f(0.0f, height / 2, 0.0f);
glVertex3f(radius * sin(a), height / 2, radius * cos(a));
glVertex3f(radius * sin(next_a), height / 2, radius * cos(next_a));
//Bottom
glColor3f(0.698f, 0.133f, 0.133f);
glVertex3f(0.0f, -height / 2, 0.0f);
glVertex3f(radius * sin(next_a), -height / 2, radius * cos(next_a));
glVertex3f(radius * sin(a), -height / 2, radius * cos(a));
for (float h = -height / 2; h < height / 2; h += height) {
next_h = h + height;
if (next_h > height / 2) {
next_h = height / 2;
}
//Walls
glColor3f(1.0f, 0.271f, 0.0f);
glVertex3f(radius * sin(next_a), next_h, radius * cos(next_a));
glVertex3f(radius * sin(a), next_h, radius * cos(a));
glVertex3f(radius * sin(next_a), h, radius * cos(next_a));
glColor3f((a + 0.05) / (2 * PI), (a + 0.3) / (2 * PI), (h + height / 2) / height);
glVertex3f(radius * sin(a), next_h, radius * cos(a));
glVertex3f(radius * sin(a), h, radius * cos(a));
glVertex3f(radius * sin(next_a), h, radius * cos(next_a));
}
glEnd();
}
}
void renderScene(void) {
// clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// set the camera
glLoadIdentity();
//FPS Camera
gluLookAt(px, py, pz, px+dx, py+dy, pz+dz, 0.0f, 1.0f, 0.0f);
// put the geometric transformations here
// put drawing instructions here
drawAxis();
drawPlane(4);
drawCylinder(1,3,30);
//FPS counter
frame++;
int final_time = glutGet(GLUT_ELAPSED_TIME);
if (final_time - timebase > 1000) {
int fps = frame * 1000.0f / (final_time - timebase);
char title[(((sizeof fps) * CHAR_BIT) + 2) / 3 + 2];
sprintf(title,"FPS: %d", fps);
glutSetWindowTitle(title);
timebase = final_time;
frame = 0;
}
// End of frame
glutSwapBuffers();
}
//FPS Camera
void move(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT: {
px -= (dz * speed);
pz += (dx * speed);
break;
}
case GLUT_KEY_LEFT: {
px += (dz * speed);
pz -= (dx * speed);
break;
}
case GLUT_KEY_UP: {
px += (dx * speed);
pz += (dz * speed);
break;
}
case GLUT_KEY_DOWN: {
px -= (dx * speed);
pz -= (dz * speed);
break;
}
default: {
break;
}
}
glutPostRedisplay();
}
void mouse_motion(int x, int y) {
float lx = x - 800;
float ly = y - 800;
angle = angle + lx * rotateSpeed;
angle1 = angle1 + ly * rotateSpeed;
dx = cos(angle1) * sin(angle);
dy = sin(angle1);
dz = cos(angle1) * cos(angle);
}
int main(int argc, char **argv) {
// init GLUT and the window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,800);
glutCreateWindow("CG");
// Required callback registry
glutIdleFunc(renderScene);
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
//FPS
timebase = glutGet(GLUT_ELAPSED_TIME);
// put here the registration of the keyboard callbacks
glutSpecialFunc(move);
glutMotionFunc(mouse_motion);
//glutPassiveMotionFunc(mouse_motion);
// OpenGL settings
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
// enter GLUT's main cycle
glutMainLoop();
return 1;
}

OpenGL independent rotation

I'm trying to draw these shaped bellow this this:
What I want
Tried this code:
glLoadIdentity();
glColor3f(0.98f, 0.83f, 0.73f);
glBegin(GL_POLYGON);
for (float i = 0; i <= (2 * p); i += 0.001) {
x = 100 * cos(i)-10;
y = 115 * sin(i)+270;
glVertex2f(x, y);
}
glEnd();
glRotatef(-135.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i) - 10;
y = 115 * sin(i) + 270;
glVertex2f(x, y);
}
But this is what I get:
What I get
If I want to only use the glLoadIdentity and glRotatef for rotation, do you have any idea about how to fix it?
Note:
I don't want to use push/pop or translation
You have to rotate the object around its center and move the rotated object to its position in the world. glRotatef rotates the vertices around (0, 0). Draw the object around (0, 0) and glTranslate to move the object to its position in the world:
glTranslate(-10.0f, 270.0f, 0.0f);
glRotatef(-135.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i);
y = 115 * sin(i);
glVertex2f(x, y);
}
Note, the matrix operations like glRotate and glTranslate specify a new matrix and multiply the current matrix by the new matrix.
If you are not allowed to use glTranslate, you have to rotate the translation vector (-10, 270) in the opposite direction. Use the trigonometric functions sin an cos to rotate the vector (see Rotation matrix). You need to invert the angle and convert it to Radians since the unit of sin and cos is Radian.
float tx = -10.0f;
float ty = 270.0f;
float angle = -135.0f;
float inv_angle_rad = -angle * M_PI / 180.0f;
float tx_rot = tx * cos(inv_angle_rad) - ty * sin(inv_angle_rad);
float ty_rot = tx * sin(inv_angle_rad) + ty * cos(inv_angle_rad);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i) + tx_rot;
y = 115 * sin(i) + ty_rot;
glVertex2f(x, y);
}

Rotation along a path in opengl

i want to move an object along a path (sine wave), lets suppose object is a roller coaster.
it moves through translate but my problem is that i also want to rotate that object according to the path.
i tried this code before translate but its not working.
if (x = -4.8)
{
glRotatef(89, 1, 1, 0);
}
my code with only translation looks like this.
i want to add rotation here along sine waves
void object()
{ glPushMatrix();
glTranslatef(x, y, 0);
glColor3f(0.0f, 0.0f, 0.0f);//Set drawing color
glBegin(GL_QUADS);
glVertex2f(-0.3, 0.1);
glVertex2f(0.3, 0.1);
glVertex2f(0.3, -0.1);
glVertex2f(-0.3, -0.1);
glEnd();
glFlush();
glPopMatrix();
glFlush();
}
void drawsine()
{
glBegin(GL_LINE_STRIP);//Primitive
glColor3f(255, 0, 0);//Set drawing color
int i = 0;
float x = 0, y = 0;
for (x = -5; x < 6; x = x + 0.1)
{
y = (sin(3.142*x)) / 3.142*x;
glVertex2f(x, y);
//int j= 0;
sinex[i] = x;
siney[i] = y;
i++;
}
glEnd();
glFlush();
}
The angle of rotation depends on the direction vector along the sine wave.
The direction vector can be calculated by the subtraction of 2 positions. Subtract the position before the current position from the positions after the current position, to calcaulte the direction vector. In the following i is the current position of the object:
dx = sinex[i+1] - sinex[i-1];
dy = siney[i+1] - siney[i-1];
The angle of rotation can be calculated by the arcus tangent using atan2, which returns an angle in radians:
float ang_rad = atan2( dy, dx );
Since the angle has to be passed to glRotatef in degrees, the angle has to be converted from radians to degrees, before a rotation around the z axis can be performed.
A full circle in has 360 degrees or 2*Pi radians. So the scale from radians to degrees 180/Pi:
float ang_deg = ang_rad * 180.0f / M_PI;
glRotatef( ang_deg, 0, 0, 1 );
The following cde snippet show how to apply the code. Be aware that there is no bounds check. This means i has to be grater or equal 1 and less than the number of points - 1 (1 <= i < 110):
#define _USE_MATH_DEFINES
#include <math.h>
{
// [...]
drawsine();
x = sinex[i];
y = siney[i];
dx = sinex[i+1] - sinex[i-1];
dy = siney[i+1] - siney[i-1];
object();
// [...]
}
void object()
{
glPushMatrix();
glTranslatef(x, y, 0);
float ang_rad = atan2( dy, dx );
float ang_deg = ang_rad * 180.0f / M_PI;
glRotatef( ang_deg, 0, 0, 1 );
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(-0.3, 0.1);
glVertex2f(0.3, 0.1);
glVertex2f(0.3, -0.1);
glVertex2f(-0.3, -0.1);
glEnd();
glPopMatrix();
}

OpenGL the direction of translation is not right after rotation

I'm writing a simple demo with the fixed pipeline mode in OpenGL
First I write some codes that will draw a rectangle, with top-left point (x1,y1), and buttom-right point (x2,y2)
// Drawing here
glPushMatrix();
// Perform rotation first
glTranslatef(x_cent, y_cent, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glScalef(scale, scale, 1.0f);
// Set origin back to the screen center with the rotation set above
glTranslatef(-x_cent, -y_cent, 0.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_QUADS);
{
glVertex2f(x1, y2);
glVertex2f(x2, y2);
glVertex2f(x2, y1);
glVertex2f(x1, y1);
}
glEnd();
// End of drawing
glPopMatrix();
After I tweak the value of the angle with arrow keys, say 45 degrees counter-clockwise, and now the rectangle will rotate 45 degrees counter-clockwise. Then I translate it with arrow keys, it moves in the direction of up, down, left, and right. Everything works fine.
So I write anoter part of code that will draw a general polygon. It's similar to the code above. I simply draw lines between each pair of points
for (int i = 0; i < p_size; i++)
{
float x1 = point[i].x, x2 = point[(i + 1) % p_size].x;
float y1 = point[i].y, y2 = point[(i + 1) % p_size].y;
x1 = ((x1 + 0.5f) / winWidth) * 2.0f - 1.0f;
x2 = ((x2 + 0.5f) / winWidth) * 2.0f - 1.0f;
y1 = ((-y1 + 0.5f) / winHeight) * 2.0f + 1.0f;
y2 = ((-y2 + 0.5f) / winHeight) * 2.0f + 1.0f;
// Set the curent coord origin to this poly's center
float x_cent = (left + right) / 2.0, y_cent = (top + down) / 2.0;
float ratio = winWidth / winHeight;
if (ratio > 1)
{
x1 *= ratio;
x2 *= ratio;
}
else //if (ratio < 1)
{
y1 /= ratio;
y2 /= ratio;
}
// Drawing here
glPushMatrix();
// Perform rotation first
glTranslatef(x_cent, y_cent, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glScalef(scale, scale, 1.0f);
// Set origin back to the screen center with the rotation set above
glTranslatef(-x_cent, -y_cent, 0.0f);
glBegin(GL_LINES);
{
glVertex2f(x1, y1);
glVertex2f(x2, y2);
}
glEnd();
// End of drawing
glPopMatrix();
}
I rotate the polygon with arrow keys, that works fine, say also 45 degrees counter-clockwise. But after the rotation, when I translate it with up key, it moves not up but in the direction of 45 degrees.
Bbut why can the rectangle translate normally in the 4 directions after rotation? These two part of codes are almost the same, why is this happening...

opengl: rotating an ellipse

I am having trouble rotating an ellipse in OpenGL. So, I have some code to draw an ellipse as follows:
glPushAttrib(GL_CURRENT_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(2.0);
glPushMatrix();
glTranslatef(0, 0, 0); // ellipse centre
glBegin(GL_LINE_LOOP);
float inc = (float) M_PI / 500.0;
for (GLfloat i = 0; i < M_PI * 2; i+=inc)
{
float x = cos(i) * 0.4;
float y = sin(i) * 0.4;
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
glPopAttrib();
This produces a picture as so:
Now what I want to do is rotate this ellipse clockwise. So I added a glrotate in between but the result was not what I had expected.
So, I did something like:
glPushAttrib(GL_CURRENT_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(2.0);
glPushMatrix();
glTranslatef(0, 0, 0);
glRotatef(-90, 1, 1, 0);
glBegin(GL_LINE_LOOP);
float inc = (float) M_PI / 500.0;
for (GLfloat i = 0; i < M_PI * 2; i+=inc)
{
float x = cos(i) * 0.4;
float y = sin(i) * 0.4;
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
glPopAttrib();
This produced an image which was simply collapsed. What I wanted to do was rotate the ellipse along its center by the specified degrees. Also, I tried playing around with the various parameters of glRotatef but could not get it do as I expected. The resulting image looks like:
You're working in the XY plane, so you can't really rotate around a vector in XY. Instead, you want to rotate along the unit Z axis (glRotate (angle, 0, 0, 1);). Imagine your screen being the XY coordinate system and the Z axis pointing inwards. What you want is to rotate around the Z axis, so your XY plane remains in the XY plane.