CS计算机代考程序代写 compiler GPU Hive b’triangle_renderer.tar.gz’

b’triangle_renderer.tar.gz’

/***** BallMath.h – Essential routines for Arcball. *****/
#ifndef _H_BallMath
#define _H_BallMath
#include “BallAux.h”

HVect MouseOnSphere(HVect mouse, HVect ballCenter, double ballRadius);
HVect ConstrainToAxis(HVect loose, HVect axis);
int NearestConstraintAxis(HVect loose, HVect *axes, int nAxes);
Quat Qt_FromBallPoints(HVect from, HVect to);
void Qt_ToBallPoints(Quat q, HVect *arcFrom, HVect *arcTo);
#endif

triangle_renderer/BallAux.cpp
triangle_renderer/BallAux.cpp/***** BallAux.c *****/
#include 
#include “BallAux.h”

Quat qOne = {0, 0, 0, 1};

/* Return quaternion product qL * qR.  Note: order is important!
 * To combine rotations, use the product Mul(qSecond, qFirst),
 * which gives the effect of rotating by qFirst then qSecond. */
Quat Qt_Mul(Quat qL, Quat qR)
{
    Quat qq;
    qq.w = qL.w*qR.w – qL.x*qR.x – qL.y*qR.y – qL.z*qR.z;
    qq.x = qL.w*qR.x + qL.x*qR.w + qL.y*qR.z – qL.z*qR.y;
    qq.y = qL.w*qR.y + qL.y*qR.w + qL.z*qR.x – qL.x*qR.z;
    qq.z = qL.w*qR.z + qL.z*qR.w + qL.x*qR.y – qL.y*qR.x;
    return (qq);
}

/* Construct rotation matrix from (possibly non-unit) quaternion.
 * Assumes matrix is used to multiply column vector on the left:
 * vnew = mat vold.  Works correctly for right-handed coordinate system
 * and right-handed rotations. */
void Qt_ToMatrix(Quat q, HMatrix &out)
{
    double Nq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
    double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
    double xs = q.x*s,        ys = q.y*s,     zs = q.z*s;
    double wx = q.w*xs,       wy = q.w*ys,    wz = q.w*zs;
    double xx = q.x*xs,       xy = q.x*ys,    xz = q.x*zs;
    double yy = q.y*ys,       yz = q.y*zs,    zz = q.z*zs;
    out[X][X] = 1.0 – (yy + zz); out[Y][X] = xy + wz; out[Z][X] = xz – wy;
    out[X][Y] = xy – wz; out[Y][Y] = 1.0 – (xx + zz); out[Z][Y] = yz + wx;
    out[X][Z] = xz + wy; out[Y][Z] = yz – wx; out[Z][Z] = 1.0 – (xx + yy);
    out[X][W] = out[Y][W] = out[Z][W] = out[W][X] = out[W][Y] = out[W][Z] = 0.0;
    out[W][W] = 1.0;
}

/* Return conjugate of quaternion. */
Quat Qt_Conj(Quat q)
{
    Quat qq;
    qq.x = -q.x; qq.y = -q.y; qq.z = -q.z; qq.w = q.w;
    return (qq);
}

/* Return vector formed from components */
HVect V3_(float x, float y, float z)
{
    HVect v;
    v.x = x; v.y = y; v.z = z; v.w = 0;
    return (v);
}

/* Return norm of v, defined as sum of squares of components */
float V3_Norm(HVect v)
{
    return ( v.x*v.x + v.y*v.y + v.z*v.z );
}

/* Return unit magnitude vector in direction of v */
HVect V3_Unit(HVect v)
{
    static HVect u = {0, 0, 0, 0};
    float vlen = sqrt(V3_Norm(v));
    if (vlen != 0.0) {
    u.x = v.x/vlen; u.y = v.y/vlen; u.z = v.z/vlen;
    }
    return (u);
}

/* Return version of v scaled by s */
HVect V3_Scale(HVect v, float s)
{
    HVect u;
    u.x = s*v.x; u.y = s*v.y; u.z = s*v.z; u.w = v.w;
    return (u);
}

/* Return negative of v */
HVect V3_Negate(HVect v)
{
    static HVect u = {0, 0, 0, 0};
    u.x = -v.x; u.y = -v.y; u.z = -v.z;
    return (u);
}

/* Return sum of v1 and v2 */
HVect V3_Add(HVect v1, HVect v2)
{
    static HVect v = {0, 0, 0, 0};
    v.x = v1.x+v2.x; v.y = v1.y+v2.y; v.z = v1.z+v2.z;
    return (v);
}

/* Return difference of v1 minus v2 */
HVect V3_Sub(HVect v1, HVect v2)
{
    static HVect v = {0, 0, 0, 0};
    v.x = v1.x-v2.x; v.y = v1.y-v2.y; v.z = v1.z-v2.z;
    return (v);
}

/* Halve arc between unit vectors v0 and v1. */
HVect V3_Bisect(HVect v0, HVect v1)
{
    HVect v = {0, 0, 0, 0};
    float Nv;
    v = V3_Add(v0, v1);
    Nv = V3_Norm(v);
    if (Nv < 1.0e-5) {     v = V3_(0, 0, 1);     } else {     v = V3_Scale(v, 1/sqrt(Nv));     }     return (v); } /* Return dot product of v1 and v2 */ float V3_Dot(HVect v1, HVect v2) {     return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); } /* Return cross product, v1 x v2 */ HVect V3_Cross(HVect v1, HVect v2) {     static HVect v = {0, 0, 0, 0};     v.x = v1.y*v2.z-v1.z*v2.y;     v.y = v1.z*v2.x-v1.x*v2.z;     v.z = v1.x*v2.y-v1.y*v2.x;     return (v); } /***** Ball.h *****/ #ifndef _H_Ball #define _H_Ball #include "BallAux.h" #ifdef __APPLE__ #include
#else
#include
#endif

typedef enum AxisSet{NoAxes, CameraAxes, BodyAxes, OtherAxes, NSets} AxisSet;
typedef float *ConstraintSet;
typedef struct {
HVect center;
double radius;
Quat qNow, qDown, qDrag;
HVect vNow, vDown, vFrom, vTo, vrFrom, vrTo;
HMatrix mNow, mDown;
Bool showResult, dragging;
ConstraintSet sets[NSets];
int setSizes[NSets];
AxisSet axisSet;
int axisIndex;
} BallData;

/* Public routines */
void Ball_Init(BallData *ball);
void Ball_Place(BallData *ball, HVect center, double radius);
void Ball_Mouse(BallData *ball, HVect vNow);
void Ball_UseSet(BallData *ball, AxisSet axisSet);
void Ball_ShowResult(BallData *ball);
void Ball_HideResult(BallData *ball);
void Ball_Update(BallData *ball);
void Ball_Value(BallData *ball, GLfloat *mNow);
void Ball_BeginDrag(BallData *ball);
void Ball_EndDrag(BallData *ball);
void Ball_Draw(BallData *ball);
/* Private routines */
void DrawAnyArc(HVect vFrom, HVect vTo);
void DrawHalfArc(HVect n);
void Ball_DrawConstraints(BallData *ball);
void Ball_DrawDragArc(BallData *ball);
void Ball_DrawResultArc(BallData *ball);
#endif

///////////////////////////////////////////////////
//
// Hamish Carr
// January, 2018
//
// ————————
// GeometricSurfaceFaceDS.h
// ————————
//
// Base code for geometric assignments.
//
// This is the minimalistic Face-based D/S for storing
// surfaces, to be used as the basis for fuller versions
//
// It will include object load / save code & render code
//
///////////////////////////////////////////////////

#ifndef _GEOMETRIC_SURFACE_FACE_DS_H
#define _GEOMETRIC_SURFACE_FACE_DS_H

#include

#include “Cartesian3.h”

class GeometricSurfaceFaceDS
{ // class GeometricSurfaceFaceDS
public:
// vectors to store vertex and triangle information – relying on POD rule
std::vector vertices;

// bounding sphere size
float boundingSphereSize;

// midpoint of object
Cartesian3 midPoint;

// constructor will initialise to safe values
GeometricSurfaceFaceDS();

// read routine returns true on success, failure otherwise
bool ReadFileTriangleSoup(char *fileName);

// routine to render
void Render();
}; // class GeometricSurfaceFaceDS

#endif

///////////////////////////////////////////////////
//
// Hamish Carr
// January, 2018
//
// ————————
// Cartesian3.h
// ————————
//
// A minimal class for a point in Cartesian space
//
///////////////////////////////////////////////////

#ifndef CARTESIAN3_H
#define CARTESIAN3_H

#include

// the class – we will rely on POD for sending to GPU
class Cartesian3
{ // Cartesian3
public:
// the coordinates
float x, y, z;

// constructors
Cartesian3();
Cartesian3(float X, float Y, float Z);
Cartesian3(const Cartesian3 &other);

// equality operator
bool operator ==(const Cartesian3 &other);

// addition operator
Cartesian3 operator +(const Cartesian3 &other);

// subtraction operator
Cartesian3 operator -(const Cartesian3 &other);

// multiplication operator
Cartesian3 operator *(float factor);

// division operator
Cartesian3 operator /(float factor);

// crossproduct routine
Cartesian3 cross(const Cartesian3 &other);

// routine to find the length
float length();

// normalisation routine
Cartesian3 normalise();

}; // Cartesian3

// stream output
std::ostream & operator << (std::ostream &outStream, Cartesian3 value); #endif /***** BallAux.h - Vector and quaternion routines for Arcball. *****/ #ifndef _H_BallAux #define _H_BallAux typedef int Bool; typedef struct {float x, y, z, w;} Quat; enum QuatPart {X, Y, Z, W, QuatLen}; typedef Quat HVect; typedef float HMatrix[QuatLen][QuatLen]; extern Quat qOne; void Qt_ToMatrix(Quat q, HMatrix &out); Quat Qt_Conj(Quat q); Quat Qt_Mul(Quat qL, Quat qR); HVect V3_(float x, float y, float z); float V3_Norm(HVect v); HVect V3_Add(HVect v1, HVect v2); HVect V3_Unit(HVect v); HVect V3_Scale(HVect v, float s); HVect V3_Negate(HVect v); HVect V3_Sub(HVect v1, HVect v2); float V3_Dot(HVect v1, HVect v2); HVect V3_Cross(HVect v1, HVect v2); HVect V3_Bisect(HVect v0, HVect v1); #endif # University of Leeds # COMP 5821M Triangle Soup Renderer This is a very simple renderer for triangle soup. It makes no attempt to be efficient, which keeps the code clearer. ============================ LINUX (FENG-LINUX) COMPILE: ============================ To compile on the University Linux machines, you will need to do the following: [userid@machine triangle_renderer]$ module add qt/5.3.1 [userid@machine triangle_renderer]$ qmake -project QT+=opengl LIBS+=-lGLU [userid@machine triangle_renderer]$ qmake [userid@machine triangle_renderer]$ make You should see a compiler warning about an unused parameter, which can be ignored. To execute the renderer, pass the file name on the command line: [userid@machine triangle_renderer]$ ./Assignment2MeshDSHandout ../models/tetrahedron.tri On other Linux installs (such as your own machine), the details may vary. ============================ MAC OS 11 (BIG SUR) COMPILE: ============================ First you will need to install Qt. The simplest way to do this is to use the Homebrew package manager: https://brew.sh Once you have installed this (following the instructions), you will want to use: brew install qt@5 Note that the current version of Qt is 6, which the code will refuse to compile against, so you must explicitly choose qt 5. If you have already installed Qt, you may need to use /usr/local/Cellar/qt@5/5.15.2/bin/qmake instead of qmake userid@machine triangle_renderer % qmake -project QT+=opengl CONFIG+=c++11 userid@machine triangle_renderer % qmake userid@machine triangle_renderer % make On MacOS, the executable is bundled as an application, so you will need to invoke it as follows: userid@machine triangle_renderer % ./triangle_renderer.app/Contents/MacOS/triangle_renderer ../models/tetrahedron.tri ============================ WINDOWS 10 COMPILE: ============================ Install Qt 5.13.0, it will come with QT creator. It can be found here: https://download.qt.io/archive/qt/5.13/5.13.0/qt-opensource-windows-x86-5.13.0.exe.mirrorlist Once QT is installed, restart your computer. Open Powershell on the folder where you have the source code - can be done by shift+right click in the explorer window, and choosing open powershell - or open powershell, cd "directory" Run qmake -project QT+=opengl LIBS+=-lopengl32 Double click the .pro file that was generated: this will open QTCreator. Select a compiler version that fits your machine (e.g. MSVC2017 64bit). Click details to see where the different configurations (debug, release) will be built, and change it if you like. Click Configure project. Click Build to confirm the compilation is correct, and produces no errors. The executable can be ran from the powershell going to the build folder you defined by doing ./triangle_renderer.exe ../models/tetrahedron.tri Alternatively, you can click "Projects" on QTCreator, click "run" under your configuration, and write ../models/tetrahedron.tri where it says "Command line arguments". This will allow running with a parameter when you click the green arrow. triangle_renderer/Cartesian3.cpp triangle_renderer/Cartesian3.cpp/////////////////////////////////////////////////// // //  Hamish Carr //  January, 2018 // //  ------------------------ //  Cartesian3.h //  ------------------------ //   //  A minimal class for a point in Cartesian space //   /////////////////////////////////////////////////// #include "Cartesian3.h" #include "math.h" // constructors Cartesian3::Cartesian3()      : x(0.0), y(0.0), z(0.0)      {} Cartesian3::Cartesian3(float X, float Y, float Z)     : x(X), y(Y), z(Z)      {} Cartesian3::Cartesian3(const Cartesian3 &other)     : x(other.x), y(other.y), z(other.z)      {}      // equality operator bool Cartesian3::operator ==(const Cartesian3 &other)     { // Cartesian3::operator ==()     return ((x == other.x) && (y == other.y) && (z == other.z));     } // Cartesian3::operator ==() // addition operator Cartesian3 Cartesian3::operator +(const Cartesian3 &other)     { // Cartesian3::operator +()     Cartesian3 returnVal(x + other.x, y + other.y, z + other.z);     return returnVal;     } // Cartesian3::operator +() // subtraction operator Cartesian3 Cartesian3::operator -(const Cartesian3 &other)     { // Cartesian3::operator -()     Cartesian3 returnVal(x - other.x, y - other.y, z - other.z);     return returnVal;     } // Cartesian3::operator -() // multiplication operator Cartesian3 Cartesian3::operator *(float factor)     { // Cartesian3::operator *()     Cartesian3 returnVal(x * factor, y * factor, z * factor);     return returnVal;     } // Cartesian3::operator *() // division operator Cartesian3 Cartesian3::operator /(float factor)     { // Cartesian3::operator /()     Cartesian3 returnVal(x / factor, y / factor, z / factor);     return returnVal;     } // Cartesian3::operator /() // crossproduct routine Cartesian3 Cartesian3::cross(const Cartesian3 &other)     { // Cartesian3::operator ==()     Cartesian3 returnVal(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x);     return returnVal;     } // Cartesian3::operator ==() // routine to find the length float Cartesian3::length()     { // Cartesian3::length()     return (x*x + y*y + z*z);        } // Cartesian3::length() // normalisation routine Cartesian3 Cartesian3::normalise()     { // Cartesian3::normalise()     float length = sqrt(x*x+y*y+z*z);     Cartesian3 returnVal(x/length, y/length, z/length);     return returnVal;     } // Cartesian3::normalise() // stream output std::ostream & operator << (std::ostream &outStream, Cartesian3 value)     { // stream output     outStream << value.x << " " << value.y << " " << value.z;     return outStream;     } // stream output          triangle_renderer/GeometricSurfaceFaceDS.cpp triangle_renderer/GeometricSurfaceFaceDS.cpp/////////////////////////////////////////////////// // //  Hamish Carr //  January, 2018 // //  ------------------------ //  GeometricSurfaceFaceDS.cpp //  ------------------------ //   //  Base code for geometric assignments. // //  This is the minimalistic Face-based D/S for storing //  surfaces, to be used as the basis for fuller versions //   //  It will include object load / save code & render code //   /////////////////////////////////////////////////// #include "GeometricSurfaceFaceDS.h" #include 
#include 
#include 
#ifdef __APPLE__
#include 
#include 
#else
#include 
#include 
#endif

// constructor will initialise to safe values
GeometricSurfaceFaceDS::GeometricSurfaceFaceDS()
    { // GeometricSurfaceFaceDS::GeometricSurfaceFaceDS()
    // force the size to nil (should not be necessary, but . . .)
    vertices.resize(0);

    // set this to something reasonable
    boundingSphereSize = 1.0;
    
    // set the midpoint to the origin
    midPoint = Cartesian3(0.0, 0.0, 0.0);
    } // GeometricSurfaceFaceDS::GeometricSurfaceFaceDS()

// read routine returns true on success, failure otherwise
bool GeometricSurfaceFaceDS::ReadFileTriangleSoup(char *fileName)
    { // GeometricSurfaceFaceDS::ReadFileTriangleSoup()
    // these are for accumulating a bounding box for the object
    Cartesian3 minCoords(1000000.0, 1000000.0, 1000000.0);
    Cartesian3 maxCoords(-1000000.0, -1000000.0, -1000000.0);
    
    // open the input file
    std::ifstream inFile(fileName);
    if (inFile.bad()) 
        return false;
    
    // set the number of vertices and faces
    long nTriangles = 0, nVertices = 0;
    
    // set the midpoint to the origin
    midPoint = Cartesian3(0.0, 0.0, 0.0);

    // read in the number of vertices
    inFile >> nTriangles;
    nVertices = nTriangles * 3;

    // now allocate space for them all
    vertices.resize(nVertices);
    
    // now loop to read the vertices in, and hope nothing goes wrong
    for (int vertex = 0; vertex < nVertices; vertex++)         { // for each vertex         inFile >> vertices[vertex].x >> vertices[vertex].y >> vertices[vertex].z;

        // keep running track of midpoint, &c.
        midPoint = midPoint + vertices[vertex];
        if (vertices[vertex].x < minCoords.x) minCoords.x = vertices[vertex].x;         if (vertices[vertex].y < minCoords.y) minCoords.y = vertices[vertex].y;         if (vertices[vertex].z < minCoords.z) minCoords.z = vertices[vertex].z;         if (vertices[vertex].x > maxCoords.x) maxCoords.x = vertices[vertex].x;
        if (vertices[vertex].y > maxCoords.y) maxCoords.y = vertices[vertex].y;
        if (vertices[vertex].z > maxCoords.z) maxCoords.z = vertices[vertex].z;
        } // for each vertex

    // now sort out the size of a bounding sphere for viewing
    // and also set the midpoint’s location
    midPoint = midPoint / vertices.size();
    
    // now go back through the vertices, subtracting the mid point
    for (int vertex = 0; vertex < nVertices; vertex++)         { // per vertex         vertices[vertex] = vertices[vertex] - midPoint;         } // per vertex     // the bounding sphere radius is just half the distance between these     boundingSphereSize = sqrt((maxCoords - minCoords).length()) * 1.0;     return true;     } // GeometricSurfaceFaceDS::ReadFileTriangleSoup() // routine to render void GeometricSurfaceFaceDS::Render()     { // GeometricSurfaceFaceDS::Render()     // walk through the faces rendering each one     glBegin(GL_TRIANGLES);     // we will loop in 3's, assuming CCW order     for (unsigned int vertex = 0; vertex < vertices.size(); )         { // per triangle         // use increment to step through them         Cartesian3 *v0 = &(vertices[vertex++]);         Cartesian3 *v1 = &(vertices[vertex++]);         Cartesian3 *v2 = &(vertices[vertex++]);         // now compute the normal vector         Cartesian3 uVec = *v1 - *v0;         Cartesian3 vVec = *v2 - *v0;         Cartesian3 normal = uVec.cross(vVec).normalise();         glNormal3fv(&normal.x);         glVertex3fv(&v0->x);
        glVertex3fv(&v1->x);
        glVertex3fv(&v2->x);
        } // per triangle
    glEnd();
    } // GeometricSurfaceFaceDS::Render()

triangle_renderer/GeometricWidget.cpp
triangle_renderer/GeometricWidget.cpp///////////////////////////////////////////////////
//
//  Hamish Carr
//  January, 2018
//
//  ————————
//  GeometricWidget.h
//  ————————
//  
//  The main widget that shows the geometry
//  
///////////////////////////////////////////////////

#include 
#ifdef __APPLE__
#include 
#include 
#else
#include 
#include 
#endif

#include “GeometricWidget.h”
static GLfloat light_position[] = {0.0, 0.0, 1.0, 0.0};                         

// constructor
GeometricWidget::GeometricWidget(GeometricSurfaceFaceDS *newSurface, QWidget *parent)
    : QGLWidget(parent)
    { // constructor
    // store pointer to the model
    surface = newSurface;
    
    // initialise arcballs to 80% of the widget’s size
    Ball_Init(&lightBall);      Ball_Place(&lightBall, qOne, 0.80);
    Ball_Init(&objectBall);     Ball_Place(&objectBall, qOne, 0.80);

    // initialise translation values
    translate_x = translate_y = 0.0;
    
    // and set the button to an arbitrary value
    whichButton = -1;
    
    } // constructor

// destructor
GeometricWidget::~GeometricWidget()
    { // destructor
    // nothing yet
    } // destructor                                                                 

// called when OpenGL context is set up
void GeometricWidget::initializeGL()
    { // GeometricWidget::initializeGL()
    // enable Z-buffering
    glEnable(GL_DEPTH_TEST);
    
    // set lighting parameters
    glShadeModel(GL_FLAT);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);
    
    // background is pink
    glClearColor(1.0, 0.7, 0.7, 1.0);
    } // GeometricWidget::initializeGL()

// called every time the widget is resized
void GeometricWidget::resizeGL(int w, int h)
    { // GeometricWidget::resizeGL()
    // reset the viewport
    glViewport(0, 0, w, h);
    
    // set projection matrix to be glOrtho based on zoom & window size
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
    // retrieve the scale factor
    float size = surface->boundingSphereSize;
    
    // compute the aspect ratio of the widget
    float aspectRatio = (float) w / (float) h;
    
    // depending on aspect ratio, set to accomodate a sphere of radius = diagonal without clipping
    if (aspectRatio > 1.0)
        glOrtho(-aspectRatio * size, aspectRatio * size, -size, size, -size, size);
    else
        glOrtho(-size, size, -size/aspectRatio, size/aspectRatio, -size, size);

    } // GeometricWidget::resizeGL()
    
// called every time the widget needs painting
void GeometricWidget::paintGL()
    { // GeometricWidget::paintGL()
    // clear the buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // set lighting on
    glEnable(GL_LIGHTING);

    // set model view matrix based on stored translation, rotation &c.
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // set light position first
    // retrieve rotation from arcball & apply
    GLfloat mNow[16];
    Ball_Value(&lightBall, mNow);
    glMultMatrixf(mNow);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
             
    // apply translation for interface control
    glLoadIdentity();
    glTranslatef(translate_x, translate_y, 0.0);

    // apply rotation matrix from arcball
    Ball_Value(&objectBall, mNow);
    glMultMatrixf(mNow);

    // now draw the surface
    surface->Render();
    } // GeometricWidget::paintGL()

// mouse-handling
void GeometricWidget::mousePressEvent(QMouseEvent *event)
    { // GeometricWidget::mousePressEvent()
    // store the button for future reference
    whichButton = event->button();

    // find the minimum of height & width   
    float size = (width() > height()) ? height() : width();

    // convert to the ArcBall’s vector type
    HVect vNow;

    // scale both coordinates from that
    vNow.x = (2.0 * event->x() – size) / size;
    vNow.y = (size – 2.0 * event->y() ) / size;

    // now either translate or rotate object or light
    switch(whichButton)
        { // button switch
        case Qt::RightButton:
            // save the last x, y
            last_x = vNow.x; last_y = vNow.y;
            // and update
            updateGL();
            break;
        case Qt::MiddleButton:
            // pass the point to the arcball code   
            Ball_Mouse(&lightBall, vNow);
            // start dragging
            Ball_BeginDrag(&lightBall);
            // update the widget
            updateGL();
            break;
        case Qt::LeftButton:
            // pass the point to the arcball code   
            Ball_Mouse(&objectBall, vNow);
            // start dragging
            Ball_BeginDrag(&objectBall);
            // update the widget
            updateGL();
            break;
        } // button switch
    } // GeometricWidget::mousePressEvent()
    
void GeometricWidget::mouseMoveEvent(QMouseEvent *event)
    { // GeometricWidget::mouseMoveEvent()
    // find the minimum of height & width   
    float size = (width() > height()) ? height() : width();

    // convert to the ArcBall’s vector type
    HVect vNow;

    // scale both coordinates from that
    vNow.x = (2.0 * event->x() – size) / size;
    vNow.y = (size – 2.0 * event->y() ) / size;

    // now either translate or rotate object or light
    switch(whichButton)
        { // button switch
        case Qt::RightButton:
            // subtract the translation
            translate_x += vNow.x – last_x;
            translate_y += vNow.y – last_y;
            last_x = vNow.x; 
            last_y = vNow.y;
            // update the widget
            updateGL();
            break;
        case Qt::MiddleButton:
            // pass it to the arcball code  
            Ball_Mouse(&lightBall, vNow);
            // start dragging
            Ball_Update(&lightBall);
            // update the widget
            updateGL();
            break;
        case Qt::LeftButton:
            // pass it to the arcball code  
            Ball_Mouse(&objectBall, vNow);
            // start dragging
            Ball_Update(&objectBall);
            // update the widget
            updateGL();
            break;
        } // button switch
    } // GeometricWidget::mouseMoveEvent()
    
void GeometricWidget::mouseReleaseEvent(QMouseEvent *event)
    { // GeometricWidget::mouseReleaseEvent()
    // now either translate or rotate object or light
    switch(whichButton)
        { // button switch
        case Qt::RightButton:
            // just update
            updateGL();
            break;
        case Qt::MiddleButton:
            // end the drag
            Ball_EndDrag(&lightBall);
            // update the widget
            updateGL();
            break;
        case Qt::LeftButton:
            // end the drag
            Ball_EndDrag(&objectBall);
            // update the widget
            updateGL();
            break;
        } // button switch
    } // GeometricWidget::mouseReleaseEvent()
    

triangle_renderer/main.cpp
triangle_renderer/main.cpp///////////////////////////////////////////////////
//
//  Hamish Carr
//  January, 2018
//
//  ————————
//  main.cpp
//  ————————
//  
///////////////////////////////////////////////////

#include 
#include “GeometricWidget.h”
#include 

int main(int argc, char **argv)
    { // main()
    // initialize QT
    QApplication app(argc, argv);

    // the geometric surface
    GeometricSurfaceFaceDS surface;

    // check the args to make sure there’s an input file
    if (argc == 2)
        { // two parameters – read a file
        if (!surface.ReadFileTriangleSoup(argv[1]))
            { // surface read failed 
            printf(“Read failed for file %s\n”, argv[1]);
            exit(0);
            } // surface read failed
        else
            { // surface read succeeded
            //  create a window
            GeometricWidget aWindow(&surface, NULL);
    
            //  set the initial size
            aWindow.resize(600, 600);

            // show the window
            aWindow.show();

            // set QT running
            return app.exec();
            } // surface read succeeded         
        } // two parameters – read a file
    else 
        { // too many parameters 
        printf(“Usage: %s filename\n”, argv[0]); 
        exit (0);
        } // too many parameters 

    // paranoid return value
    exit(0);
    } // main()

triangle_renderer/BallMath.cpp
triangle_renderer/BallMath.cpp/**** BallMath.c – Essential routines for ArcBall.  ****/
#include 
#include “BallMath.h”
#include “BallAux.h”

/* Convert window coordinates to sphere coordinates. */
HVect MouseOnSphere(HVect mouse, HVect ballCenter, double ballRadius)
{
    HVect ballMouse;
    double mag;
    ballMouse.x = (mouse.x – ballCenter.x) / ballRadius;
    ballMouse.y = (mouse.y – ballCenter.y) / ballRadius;
    mag = ballMouse.x*ballMouse.x + ballMouse.y*ballMouse.y;
    if (mag > 1.0) {
    double scale = 1.0/sqrt(mag);
    ballMouse.x *= scale; ballMouse.y *= scale;
    ballMouse.z = 0.0;
    } else {
    ballMouse.z = sqrt(1 – mag);
    }
    ballMouse.w = 0.0;
    return (ballMouse);
}

/* Construct a unit quaternion from two points on unit sphere */
Quat Qt_FromBallPoints(HVect from, HVect to)
{
    Quat qu;
    qu.x = from.y*to.z – from.z*to.y;
    qu.y = from.z*to.x – from.x*to.z;
    qu.z = from.x*to.y – from.y*to.x;
    qu.w = from.x*to.x + from.y*to.y + from.z*to.z;
    return (qu);
}

/* Convert a unit quaternion to two points on unit sphere */
void Qt_ToBallPoints(Quat q, HVect *arcFrom, HVect *arcTo)
{
    double s;
    s = sqrt(q.x*q.x + q.y*q.y);
    if (s == 0.0) {
    *arcFrom = V3_(0.0, 1.0, 0.0);
    } else {
    *arcFrom = V3_(-q.y/s, q.x/s, 0.0);
    }
    arcTo->x = q.w*arcFrom->x – q.z*arcFrom->y;
    arcTo->y = q.w*arcFrom->y + q.z*arcFrom->x;
    arcTo->z = q.x*arcFrom->y – q.y*arcFrom->x;
    if (q.w < 0.0) *arcFrom = V3_(-arcFrom->x, -arcFrom->y, 0.0);
}

/* Force sphere point to be perpendicular to axis. */
HVect ConstrainToAxis(HVect loose, HVect axis)
{
    HVect onPlane;
    float norm;
    onPlane = V3_Sub(loose, V3_Scale(axis, V3_Dot(axis, loose)));
    norm = V3_Norm(onPlane);
    if (norm > 0.0) {
    if (onPlane.z < 0.0) onPlane = V3_Negate(onPlane);     return ( V3_Scale(onPlane, 1/sqrt(norm)) );     } /* else drop through */     if (axis.z == 1) {     onPlane = V3_(1.0, 0.0, 0.0);     } else {     onPlane = V3_Unit(V3_(-axis.y, axis.x, 0.0));     }     return (onPlane); } /* Find the index of nearest arc of axis set. */ int NearestConstraintAxis(HVect loose, HVect *axes, int nAxes) {     HVect onPlane;     float max, dot;     int i, nearest;     max = -1; nearest = 0;     for (i=0; imax) {
        max = dot; nearest = i;
    }
    }
    return (nearest);
}

///////////////////////////////////////////////////
//
// Hamish Carr
// January, 2018
//
// ————————
// GeometricWidget.h
// ————————
//
// The main widget that shows the geometry
//
///////////////////////////////////////////////////

#ifndef _GEOMETRIC_WIDGET_H
#define _GEOMETRIC_WIDGET_H

#include
#include
#include “GeometricSurfaceFaceDS.h”
#include “Ball.h”

class GeometricWidget : public QGLWidget
{ // class GeometricWidget
Q_OBJECT
public:
// the model – i.e. the surface
GeometricSurfaceFaceDS *surface;

// arcball for storing light rotation
BallData lightBall;

// arcball for storing object rotation
BallData objectBall;

// translation in window x,y
GLfloat translate_x, translate_y;
GLfloat last_x, last_y;

// which button was last pressed
int whichButton;

// constructor
GeometricWidget(GeometricSurfaceFaceDS *newSurface, QWidget *parent);

// destructor
~GeometricWidget();

protected:
// called when OpenGL context is set up
void initializeGL();
// called every time the widget is resized
void resizeGL(int w, int h);
// called every time the widget needs painting
void paintGL();

// mouse-handling
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);

}; // class GeometricWidget

#endif

triangle_renderer/Ball.cpp
triangle_renderer/Ball.cpp/***** Ball.c *****/
/* Ken Shoemake, 1993 */
#ifdef __APPLE__
#include 
#else
#include 
#endif
#include “Ball.h”
#include “BallMath.h”
#include “BallAux.h”

#define ARCBALL_TRUE 1
#define ARCBALL_FALSE 0
#define LG_NSEGS 4
#define NSEGS (1<center = qOne;
    ball->radius = 1.0;
    ball->vDown = ball->vNow = qOne;
    ball->qDown = ball->qNow = qOne;
    for (i=15; i>=0; i–)
    ((float *)ball->mNow)[i] = ((float *)ball->mDown)[i] = ((float *)mId)[i];
    ball->showResult = ball->dragging = ARCBALL_FALSE;
    ball->axisSet = NoAxes;
    ball->sets[CameraAxes] = mId[X]; ball->setSizes[CameraAxes] = 3;
    ball->sets[BodyAxes] = ball->mDown[X]; ball->setSizes[BodyAxes] = 3;
    ball->sets[OtherAxes] = otherAxis[X]; ball->setSizes[OtherAxes] = 1;
}

/* Set the center and size of the controller. */
void Ball_Place(BallData *ball, HVect center, double radius)
{
    ball->center = center;
    ball->radius = radius;
}

/* Incorporate new mouse position. */
void Ball_Mouse(BallData *ball, HVect vNow)
{
    ball->vNow = vNow;
}

/* Choose a constraint set, or none. */
void Ball_UseSet(BallData *ball, AxisSet axisSet)
{
    if (!ball->dragging) ball->axisSet = axisSet;
}

/* Begin drawing arc for all drags combined. */
void Ball_ShowResult(BallData *ball)
{
    ball->showResult = ARCBALL_TRUE;
}

/* Stop drawing arc for all drags combined. */
void Ball_HideResult(BallData *ball)
{
    ball->showResult = ARCBALL_FALSE;
}

/* Using vDown, vNow, dragging, and axisSet, compute rotation etc. */
void Ball_Update(BallData *ball)
{
    int setSize = ball->setSizes[ball->axisSet];
    HVect *set = (HVect *)(ball->sets[ball->axisSet]);
    ball->vFrom = MouseOnSphere(ball->vDown, ball->center, ball->radius);
    ball->vTo = MouseOnSphere(ball->vNow, ball->center, ball->radius);
    if (ball->dragging) {
    if (ball->axisSet!=NoAxes) {
        ball->vFrom = ConstrainToAxis(ball->vFrom, set[ball->axisIndex]);
        ball->vTo = ConstrainToAxis(ball->vTo, set[ball->axisIndex]);
    }
    ball->qDrag = Qt_FromBallPoints(ball->vFrom, ball->vTo);
    ball->qNow = Qt_Mul(ball->qDrag, ball->qDown);
    } else {
    if (ball->axisSet!=NoAxes) {
        ball->axisIndex = NearestConstraintAxis(ball->vTo, set, setSize);
    }
    }
    Qt_ToBallPoints(ball->qDown, &ball->vrFrom, &ball->vrTo);
    Qt_ToMatrix(Qt_Conj(ball->qNow), ball->mNow); /* Gives transpose for GL. */
}

/* Return rotation matrix defined by controller use. */
void Ball_Value(BallData *ball, GLfloat *mNow)
{
    int i;
    for (i=15; i>=0; i–) mNow[i] = ((float *)ball->mNow)[i];
}

/* Begin drag sequence. */
void Ball_BeginDrag(BallData *ball)
{
    ball->dragging = ARCBALL_TRUE;
    ball->vDown = ball->vNow;
}

/* Stop drag sequence. */
void Ball_EndDrag(BallData *ball)
{
    int i;
    ball->dragging = ARCBALL_FALSE;
    ball->qDown = ball->qNow;
    for (i=15; i>=0; i–)
    ((float *)ball->mDown)[i] = ((float *)ball->mNow)[i];
}

/* Draw the controller with all its arcs. */
void Ball_Draw(BallData *ball)
{
    float r = ball->radius;
    glPushMatrix();
    glLoadIdentity();
    glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 1.0);
    RIMCOLOR();
    glScalef(r, r, r);
/*    circ(0.0, 0.0, 1.0); */
    Ball_DrawResultArc(ball);
    Ball_DrawConstraints(ball);
    Ball_DrawDragArc(ball);
    glPopMatrix();
}

/* Draw an arc defined by its ends. */
void DrawAnyArc(HVect vFrom, HVect vTo)
{
    int i;
    HVect pts[NSEGS+1];
    double dot;
    pts[0] = vFrom;
    pts[1] = pts[NSEGS] = vTo;
    for (i=0; isetSizes[ball->axisSet];
    if (ball->axisSet==NoAxes) return;
    set = ball->sets[ball->axisSet];
    for (axisI=0; axisIaxisIndex!=axisI) {
        if (ball->dragging) continue;
        FARCOLOR();
    } else NEARCOLOR();
    axis = *(HVect *)&set[4*axisI];
/*  if (axis.z==1.0) {
        circ(0.0, 0.0, 1.0);
    } else {
*/      DrawHalfArc(axis);
/*  } */
    }
}

/* Draw “rubber band” arc during dragging. */
void Ball_DrawDragArc(BallData *ball)
{
    DRAGCOLOR();
    if (ball->dragging) DrawAnyArc(ball->vFrom, ball->vTo);
}

/* Draw arc for result of all drags. */
void Ball_DrawResultArc(BallData *ball)
{
    RESCOLOR();
    if (ball->showResult) DrawAnyArc(ball->vrFrom, ball->vrTo);
}

._triangle_renderer

triangle_renderer/BallMath.h

triangle_renderer/BallAux.cpp

triangle_renderer/._Ball.h

triangle_renderer/Ball.h

triangle_renderer/GeometricSurfaceFaceDS.h

triangle_renderer/Cartesian3.h

triangle_renderer/BallAux.h

triangle_renderer/._readme.txt

triangle_renderer/readme.txt

triangle_renderer/Cartesian3.cpp

triangle_renderer/GeometricSurfaceFaceDS.cpp

triangle_renderer/GeometricWidget.cpp

triangle_renderer/main.cpp

triangle_renderer/._BallMath.cpp

triangle_renderer/BallMath.cpp

triangle_renderer/GeometricWidget.h

triangle_renderer/._Ball.cpp

triangle_renderer/Ball.cpp