Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

The programming problem is based on Homework #2. Our goal is now to apply force-

ID: 3768963 • Letter: T

Question

The programming problem is based on Homework #2. Our goal is now to apply force-directed relaxation algorithm to refine the curve topology. Two forces are used, an attractive
“mechanical” force ( ) applied between adjacent beads on the same
component and a repulsive “electrical” force ( ) applied between all other pairs of beads.  
Your programming tasks include:
1. Implement the force model so that your sketched curves can be relaxed automatically to a refined shape (a keyboard event “r” to trigger the relaxation iteration) (40 pts)
3
2. 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. 3. Adding a projective shadow to the 3D scene. (30 pts) 4. 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

#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;
/****************************************************************************
calcCubicSpline

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));
}
}

/****************************************************************************
reticleDraw

draw reticle surface as visual helper
***************************************************************************/
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;
}
/****************************************************************************
DrawAxises

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();
}
/****************************************************************************
Display()

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()

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;

}
/****************************************************************************
mouseAna()

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();
}
/****************************************************************************
mouseMotion()

mouse 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;
}
}
/****************************************************************************
Keyboard()

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;
}
/****************************************************************************
menu_select()

every menu selection is a mode chagener
*****************************************************************************/
// selection callback
static void menu_select(int mode)
{
Keyboard( (unsigned char)mode, 0,0 );
}
/****************************************************************************
create_menu()

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);
}

/****************************************************************************
Animate()

redrawing
*****************************************************************************/
static void Animate()
{
//if (screen_dirty)
glutPostRedisplay();
}
/****************************************************************************
Main()

Startup
*****************************************************************************/
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;
}

answer is left yet but i cant text here because space is not enough,please drop your maild in comment i will mail to you.