I need the code in opengl and c++, Implement the force model so that your sketch
ID: 3766880 • Letter: I
Question
I need the code in opengl and c++,
Implement the force model so that your sketched curves can be relaxed automatically to a refined shape (40 pts)
Adding collision avoidance mechanism (30 pts): during each iteration of shape refinement, check to determine if moving the bead to its desired location will cause the knot to move into an unsafe position. If so, bring the unsafe components apart to avoid collisions.
Adding a shadow to the 3D scene. (30 pts)
Implement view finding function, so that after each relaxation is done the system will rotate the curves into a position that users see the fewest intersections. (bonus point 15 pts)
Explanation / Answer
Program:
#include <Windows.h>
#include "GLglut.h"
#include "spline2D.h"
#include "matrix.h"
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
static int sizeW = 800, sizeH = 600;
//variables for drawing Cylinder
// the angles between two consecutive points
float * angles;
// the lengths between two consecutive points
float * lengths;
// interpolation steps
int steps = 5;
//variables for drawing reticle surface as a visual helper
#define GRID_SIZE_W 100
#define GRID_SIZE_H 100
#define V_MINUS(A,B) {A[0]-B[0], A[1]-B[1], A[2]-B[2]}
#define V_CROSS(A,B)
{A[1]*B[2]-A[2]*B[1],
A[2]*B[0]-A[0]*B[2],
A[0]*B[1]-A[1]*B[0]}
static float reticle[GRID_SIZE_W][GRID_SIZE_H];
int Vertex_cp = -1;
//variables for mouse event with momentum
static int g_button;
static int g_state;
static float g_scale = 1.0;
static int g_x;
static int g_y;
static double g_axis[3] = { 1, 0, 0 };
static float g_angle = 0.0;
static int g_down_x;
static int g_down_y;
static double g_down_time;
//Variabales for rotate the scene and Zooming
static int mouseVertexX = -999, mouseVertexY = -999;
static bool mouseStateUses[3] = { false };
static int modStates = 0;
static float alphaCamera = 30, betaCamera = 5, zoomCamera = 0;
// to clear the screen later
static bool screen_dirty = true;
//for cursor visual effect
VecF locationCursor(0.0, 0.0, 0.0);
vector< VecF > controlVertexs;
//vector<Vertex> Vertexs;
/****************************************
use calcCubicSpline to insert the vertex in the right place by manipulate the vercor's order
*****************************************************/
static void calcCubicSpline()
{
// You We need at least 3 Vertexs to define a plane
if ( controlVertexs.size() < 3 )
return;
unsigned p = controlVertexs.size();
// Vertexs.clear();
for(int i = 0; i < p; ++i)
{
insertVertex(Vertex(controlVertexs[i].x,
controlVertexs[i].y,
controlVertexs[i].z));
}
}
/**************************************************
Use reticleDraw method to draw reticle surface
***************************************************/
void reticleDraw()
{
static GLfloat color1[] = { 0.8, 0.8, 0.8, 1.0 };
static GLfloat color2[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
static GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 };
static GLfloat blue[] = { 0.0, 0.0, 1.0, 1.0 };
glEnable(GL_LIGHTING);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_QUADS);
static GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat mat_shininess[] = { 100.0 };
for (int x = -GRID_SIZE_W / 2; x<GRID_SIZE_W / 2 - 1; ++x)
{
for (int z = -GRID_SIZE_H / 2; z<GRID_SIZE_H / 2 - 1; ++z)
{
if ((x & 8) ^ (z & 8))
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color1);
else
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color2);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
float a[] = { x + 0, reticle[x + 0 + GRID_SIZE_W / 2][z + 0 + GRID_SIZE_H / 2], z + 0 };
float b[] = { x + 0, reticle[x + 0 + GRID_SIZE_W / 2][z + 1 + GRID_SIZE_H / 2], z + 1 };
float c[] = { x + 1, reticle[x + 1 + GRID_SIZE_W / 2][z + 1 + GRID_SIZE_H / 2], z + 1 };
float d[] = { x + 1, reticle[x + 1 + GRID_SIZE_W / 2][z + 0 + GRID_SIZE_H / 2], z + 0 };
float ab[] = V_MINUS(a, b);
float cb[] = V_MINUS(c, b);
float n[] = V_CROSS(cb, ab);
glNormal3f(n[0], n[1], n[2]);
glVertex3f(a[0], a[1], a[2]);
glVertex3f(b[0], b[1], b[2]);
glVertex3f(c[0], c[1], c[2]);
glVertex3f(d[0], d[1], d[2]);
}
}
glEnd();
glDisable(GL_LIGHTING);
// Flat reticle
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_QUADS);
glColor3ub(128, 128, 128);
for (int x = -GRID_SIZE_W / 2; x<GRID_SIZE_W / 2 - 4; x += 5)
{
for (int z = -GRID_SIZE_H / 2; z<GRID_SIZE_H / 2 - 4; z += 5)
{
glVertex3f(x - 0.5, -0.5f, z - 0.5);
glVertex3f(x - 0.5, -0.5f, z + 4.5);
glVertex3f(x + 4.5, -0.5f, z + 4.5);
glVertex3f(x + 4.5, -0.5f, z - 0.5);
}
}
glEnd();
}
static void reticleClear()
{
for (int x=0; x<GRID_SIZE_W; ++x)
for (int z=0; z<GRID_SIZE_H; ++z)
reticle[x][z] = 0;
}
/***********************************
Use DrawAxises method to draw axis wit r, g, b
Axes: (x,y,z)=(r,g,b)
*****************************************************/
void DrawAxises()
{
//
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glPushMatrix();
glRotatef(90.0, 0.0, 1.0, 0.0);
glColor3ub(255, 0, 0);
glutSolidCone(0.5, 80.0, 5, 1);
glPopMatrix();
glPushMatrix();
glRotatef(-90.0, 1.0, 0.0, 0.0);
glColor3ub(0, 255, 0);
glutSolidCone(0.5, 80.0, 5, 1);
glPopMatrix();
glPushMatrix();
glRotatef(0.0, 1.0, 0.0, 0.0);
glColor3ub(0, 0, 255);
glutSolidCone(0.5, 80.0, 5, 1);
glPopMatrix();
}
/**************************************************
use Display() method to Clear and redraw the scene.
****************************************************************/
static void Display()
{
unsigned i;
// Make a rotation matrix out of mouseAna Vertex
const Matrix4F& rot = rotateY( betaCamera ) * rotateX( alphaCamera );
// Rotate camera
VecF cam_loc(5.0, 6.0, -100.0), cam_up(0.0, 1.0, 0.0);
cam_loc = cam_loc * rot;
cam_up = cam_up * rot;
// Clear the screen
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
// Prepare zoom by changiqng FOV
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float fov = 45 + zoomCamera;
if ( fov < 5 ) fov = 5;
if ( fov > 160 ) fov = 160;
gluPerspective( fov, (float)sizeW/(float)sizeH, 1.0, 500.0 );
gluLookAt( cam_loc.x, cam_loc.y, cam_loc.z, // eye
0.0, 0.0, -1.0,// target
cam_up.x, cam_up.y, cam_up.z ); // up
// Draw(visual helper)
reticleDraw();
DrawAxises();
// Control Vertexs when picking a vertex
int old_sel = Vertex_cp;
if ( mouseStateUses[0] == mouseStateUses[1] == mouseStateUses[2] == 0 )
Vertex_cp = -1;
for ( int i = 0; i < controlVertexs.size(); ++i )
{
const VecF& cp = controlVertexs[i];
VecF cpPevious(-1, -1, -1);
if(i != 0)
{
cpPevious = controlVertexs[i - 1];
}
if ( ( cp - locationCursor ).len() < 2.0 )
{
Vertex_cp = i;
glutSetCursor(GLUT_CURSOR_INFO);
}
// draw the points as solid
glPushMatrix();
glTranslatef(cp.x, cp.y, cp.z);
if ( Vertex_cp == i )
glColor3ub( 115, 255, 255 );//on the cursor
else
glColor3ub( 255, 255, 115 );
glutSolidSphere(3.0,50,50);
glPopMatrix();
glBegin( GL_POINTS );
// glVertex3f( cp.x, 0, cp.z );
glVertex3f( cp.x, cp.y, cp.z );
glEnd();
glEnable(GL_LIGHTING);
// add some material (Silver) to the cylinder
GLfloat SplineColor[] = { 0.19225f, 0.19225f, 0.19225f, 51.2f };
glMaterialfv(GL_FRONT, GL_SPECULAR, SplineColor);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, SplineColor);
glMaterialf(GL_FRONT, GL_SHININESS, 50.0);
float specReflection[] = { 0.508273f, 0.508273f, 0.508273f, 51.2f };
float diffuseReflection[] = { 0.50754f, 0.50754f, 0.50754f, 51.2f };
glMaterialfv(GL_FRONT, GL_SPECULAR, specReflection);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseReflection);
if (Vertexs.size() >= 3) {
glLineWidth(10);
glBegin(GL_LINE_STRIP);
vector<double> ks = getNaturalKs();
vector<double> ksz = getNaturalKsZ();
// Loop over all the Vertexs (skipping the first)
for (int j = 0; j <= Vertexs.size() - 3; ++j) {
for (int i = j + 1; i < j + 3; ++i) {
Vertex cur = Vertexs[i];
Vertex pre = Vertexs[i - 1];
// Iterate over the X's between this Vertex and the preious
double increse = (cur.x - pre.x) / steps;
for (double x = pre.x; x <= cur.x; x += increse) {
double y = evalSpline(x, ks);
double z= evalSplineZ(x, ksz);;
if (y == -1) {
break;
}
if((i == j + 2)||(i == 0) || (i == 1))
{
// Calculate the length between point_1 and point_2
double length = sqrt((pre.x - cur.x)*(pre.x - cur.x) + (pre.y - cur.y)*(pre.y - cur.y) + (pre.z - cur.z)*(pre.z - cur.z));
// Find out the crossproduct of vector Z and vector point_1->point_2
double p1[3] = { 0, 0, 1 };
double p2[3] = { cur.x - pre.x, cur.y - pre.y, cur.z - pre.z };
p2[0] = p2[0] / length; p2[1] = p2[1] / length; p2[2] = p2[2] / length;
double cp[3];
cp[0] = (p1[1] * p2[2]) - (p1[2] * p2[1]);
cp[1] = (p1[2] * p2[0]) - (p1[0] * p2[2]);
cp[2] = (p1[0] * p2[1]) - (p1[1] * p2[0]);
//printf("%f,%f,%f ", cp[0], cp[1], cp[2]);
// Find out the dotproduct of vector Z and vector point_1->point_2
double angle = acos(p1[0] * p2[0] + p1[1] * p2[1] + p1[2] * p2[2])*180.0 / PI;
//printf("%f ", angle);
// when I used cyliders my line look stright and not smooth but it works
/*glPushMatrix();
GLUquadricObj *obj = gluNewQuadric();
glTranslatef(pre.x, pre.y, pre.z);
glRotatef(angle, cp[0], cp[1], cp[2]);
gluCylinder(obj, 3, 3, length, 20, 20);
glPopMatrix();*/
glVertex3f(x, y, z);
}
}
}
}
glEnd();
glLineWidth(1);
}
}
if ( Vertex_cp < 0 && old_sel != Vertex_cp )
glutSetCursor( GLUT_CURSOR_CROSSHAIR );
// Find out the world coordinates of mouseAna Vertexer
// to locate the cursor
if ( mouseStateUses[0] == mouseStateUses[1] == mouseStateUses[2] == 0 )
{
GLdouble model[16], proj[16];
GLint view[4];
GLfloat z;
GLdouble ox, oy, oz;
glGetDoublev(GL_MODELVIEW_MATRIX, model);
glGetDoublev(GL_PROJECTION_MATRIX, proj);
glGetIntegerv(GL_VIEWPORT, view);
glReadPixels(mouseVertexX, view[3]-mouseVertexY-1, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
gluUnProject(mouseVertexX, view[3]-mouseVertexY-1, z, model, proj, view, &ox, &oy, &oz);
locationCursor = VecF(ox, oy, oz);
// Draw the cursor
glPushMatrix();
glDisable(GL_LIGHTING) ;
glTranslatef(ox, oy, oz);
glColor3ub( 255, 0, 255 );
glutSolidSphere(0.5,12,12);
glPopMatrix();
}
glFlush();
glutSwapBuffers();
screen_dirty = false;
}
/*******************************************
Reshape() method to Reset the viewport for window changes
*****************************************************************************/
static void Reshape( int w, int h )
{
sizeW = w;
sizeH = h;
glViewport( 0, 0, sizeW, sizeH );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
/****************************************************************************
Keyboard()
key press callback
*****************************************************************************/
static void Keyboard( unsigned char key, int, int )
{
switch (key)
{
case 'a':
controlVertexs.push_back( locationCursor );
calcCubicSpline();
break;
case 'd':
if ( Vertex_cp >= 0 )
{
controlVertexs.erase( controlVertexs.begin() + Vertex_cp );
Vertex_cp = -1;
calcCubicSpline();
}
break;
case 'c':
calcCubicSpline();
controlVertexs.clear();
reticleClear();
break;
case '+':
steps += 1;
calcCubicSpline();
break;
case '-':
steps -= 1;
calcCubicSpline();
if (steps < 0) steps = 0;
break;
case '/': zoomCamera -= 1; break;
case '*': zoomCamera += 1; break;
case 'm': mouseStateUses[1] = !mouseStateUses[1]; break;
case 'q': exit( 0 ); break;
}
screen_dirty=true;
}
/****************************************
Use the method mouseAna() to mouse button callback
***********************************************/
static void mouseAna( int button, int state, int x, int y)
{
mouseStateUses[ button ] = (state==GLUT_DOWN);
modStates = glutGetModifiers();
glutSetCursor( GLUT_CURSOR_CROSSHAIR );
if ( button == 1 && state==GLUT_DOWN )
glutSetCursor( GLUT_CURSOR_CYCLE );
if ( button == 0 )
{
if ( state==GLUT_UP )
{
calcCubicSpline();
screen_dirty=true;
}
else if ( state==GLUT_DOWN && Vertex_cp<0 )
Keyboard( 'a', 0,0 );
}
//-----attempt for mouse event with momentum--------
y = HEIGHT - y;
g_button = button;
g_state = state;
g_x = x;
g_y = y;
// Respond to mouse button presses.
// If button1 pressed, mark this state so we know in motion function.
if (button == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN){
g_down_x = x;
g_down_y = y;
//printf("LEFT MOUSE DOWN at [%d,%d] ", g_x, g_y);
SYSTEMTIME time;
GetSystemTime(&time);
g_down_time = time.wMinute * 60 + time.wSecond + time.wMilliseconds / 1000.0;
//printf("downtime = %f ", g_down_time);
}
else{
//printf("LEFT MOUSE UP ");
SYSTEMTIME time;
GetSystemTime(&time);
double now = time.wMinute * 60 + time.wSecond + time.wMilliseconds / 1000.0;
double traversed = (x - g_down_x)*(x - g_down_x) + (y - g_down_y)*(y - g_down_y);
if ((now - g_down_time) < 0.2 && traversed > 225) {
//printf("up = %f ", now);
//printf("short!");
}
else{
g_angle = 0;
}
}
}
else if (button == GLUT_RIGHT_BUTTON) {
if (state == GLUT_DOWN){
}
else{
g_scale = 1.0;
}
}
//glutPostRedisplay();
}
/*************************************************************
Use mouse method mouseMotion() to movement callback
************************************************************/
static void mouseMotion( int x, int y )
{
if ( mouseStateUses[0] && mouseVertexX != -999 )
if (Vertex_cp >= 0)
{
//controlVertexs[Vertex_cp].x += -(x - mouseVertexY) /3;
controlVertexs[Vertex_cp].y += -(y - mouseVertexY) / 3;
calcCubicSpline();
}
if ( mouseStateUses[1] && mouseVertexX != -999 )
{
alphaCamera += -(y - mouseVertexY);
betaCamera += (x - mouseVertexX);
screen_dirty=true;
}
if ( mouseVertexX != x || mouseVertexY != y )
{
mouseVertexX = x;
mouseVertexY = y;
screen_dirty=true;
}
}
/**************************************************
Use Keyboard() method
Keyboard press callback for special characters for rolling ball effect
********************************************************/
static void keyboard_special( int key, int, int )
{
switch (key)
{
case GLUT_KEY_UP: alphaCamera += 5 ; break;
case GLUT_KEY_DOWN: alphaCamera += -5 ; break;
case GLUT_KEY_RIGHT: betaCamera += -5 ; break;
case GLUT_KEY_LEFT: betaCamera += 5 ; break;
}
screen_dirty=true;
}
/*********************************************
Use menu_select() select method to select every menu selection
*****************************************************/
// selection callback
static void menu_select(int mode)
{
Keyboard( (unsigned char)mode, 0,0 );
}
/*****************************************************
use create_menu() method to create menu options
*******************************************************/
static void create_menu(void)
{
glutCreateMenu(menu_select);
glutAddMenuEntry(" m (rolling-ball) Rotate the Scene", 'm');
glutAddMenuEntry(" d Delete control Vertex",'d');
glutAddMenuEntry(" a Add control Vertex",'a');
glutAddMenuEntry(" c Clear all",'c');
glutAddMenuEntry(" + Increase Step",'+');
glutAddMenuEntry(" - Decrese Step",'-');
glutAddMenuEntry(" / Zoom in",'/');
glutAddMenuEntry(" * Zoom out",'*');
glutAddMenuEntry(" q Exit",'q');
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
/******************************************************
Use the metho Animate() to redraw with animation
********************************************************/
static void Animate()
{
//if (screen_dirty)
glutPostRedisplay();
}
/*********************************************************
USe Main() method to begin the program
*************************************************/
int main( int argc, char *argv[] )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
glutInitWindowSize( sizeW, sizeH );
glutInitWindowPosition( 0, 0 );
if ( !glutCreateWindow( "Natural Cubic Spline in 3D" ) )
{
printf( "Couldn't open window. " );
return 1;
}
glutDisplayFunc( Display );
glutMouseFunc( mouseAna );
glutMotionFunc( mouseMotion );
glutPassiveMotionFunc( mouseMotion );
glutKeyboardFunc( Keyboard );
glutSpecialFunc( keyboard_special );
glutReshapeFunc( Reshape );
glutIdleFunc(Animate);
glutSetCursor( GLUT_CURSOR_CROSSHAIR );
// lights for the scene
glEnable(GL_LIGHTING);
GLfloat lightAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f} ;
glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lightAmbient);
glEnable(GL_LIGHT0);
GLfloat light0Position[] = {0.7f, 0.5f, 0.9f, 0.0f} ;
GLfloat light0Ambient[] = {0.0f, 0.5f, 1.0f, 0.8f} ;
GLfloat light0Diffuse[] = {0.0f, 0.5f, 1.0f, 0.8f} ;
GLfloat light0Specular[] = {0.0f, 0.5f, 1.0f, 0.8f} ;
glLightfv(GL_LIGHT0, GL_POSITION,light0Position) ;
glLightfv(GL_LIGHT0, GL_AMBIENT,light0Ambient) ;
glLightfv(GL_LIGHT0, GL_DIFFUSE,light0Diffuse) ;
glLightfv(GL_LIGHT0, GL_SPECULAR,light0Specular) ;
glEnable(GL_LIGHT1);
GLfloat light1Position[] = {0.5f, 0.7f, 0.2f, 0.0f} ;
GLfloat light1Ambient[] = {1.0f, 0.5f, 0.0f, 0.8f} ;
GLfloat light1Diffuse[] = {1.0f, 0.5f, 0.0f, 0.8f} ;
GLfloat light1Specular[] = {1.0f, 0.5f, 0.0f, 0.8f} ;
glLightfv(GL_LIGHT1, GL_POSITION,light1Position) ;
glLightfv(GL_LIGHT1, GL_AMBIENT,light1Ambient) ;
glLightfv(GL_LIGHT1, GL_DIFFUSE,light1Diffuse) ;
glLightfv(GL_LIGHT1, GL_SPECULAR,light1Specular) ;
reticleClear();
create_menu() ;
glutMainLoop();
return 0;
}