Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

As provided, the code will draw and rotate a simple triangle in 3D. You are to modify the code to draw a cube in 3d

As provided, the code will draw and rotate a simple triangle in 3D. You are to modify the code to draw a cube in 3d with each vertex having its own color. Details: You are to draw a cube centered on the origin. It should be 1.0 - 1.5 units on a side. The 8 vertices of the cube should be coded using the colors black, red, green, blue, yellow, magenta, cyan, and white. You will have to change the data that is used by the OpenGL calls in order to do this. A vertex and fragment shader will also be provided that will provide the functionality you need for this project.

////////////////////////////////////////////////////////////////////////////// // // --- LoadShaders.cxx --- // ////////////////////////////////////////////////////////////////////////////// #include  #include  #define GLEW_STATIC #include  #include "LoadShaders.h" #ifdef __cplusplus extern "C" { #endif // __cplusplus //---------------------------------------------------------------------------- static const GLchar* ReadShader( const char* filename ) { #ifdef WIN32 FILE* infile; fopen_s( &infile, filename, "rb" ); #else FILE* infile; fopen_s(&infile, filename, "rb"); // FILE* infile = fopen( filename, "rb" ); #endif // WIN32 if ( !infile ) { #ifdef _DEBUG std::cerr << "Unable to open file '" << filename << "'" << std::endl; #endif /* DEBUG */ return NULL; } fseek( infile, 0, SEEK_END ); int len = ftell( infile ); fseek( infile, 0, SEEK_SET ); GLchar* source = new GLchar[len+1]; fread( source, 1, len, infile ); fclose( infile ); source[len] = 0; return const_cast(source); } //---------------------------------------------------------------------------- GLuint LoadShaders( ShaderInfo* shaders ) { if ( shaders == NULL ) { return 0; } GLuint program = glCreateProgram(); ShaderInfo* entry = shaders; while ( entry->type != GL_NONE ) { GLuint shader = glCreateShader( entry->type ); entry->shader = shader; const GLchar* source = ReadShader( entry->filename ); if ( source == NULL ) { for ( entry = shaders; entry->type != GL_NONE; ++entry ) { glDeleteShader( entry->shader ); entry->shader = 0; } return 0; } glShaderSource( shader, 1, &source, NULL ); delete [] source; glCompileShader( shader ); GLint compiled; glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled ); if ( !compiled ) { #ifdef _DEBUG GLsizei len; glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &len ); GLchar* log = new GLchar[len+1]; glGetShaderInfoLog( shader, len, &len, log ); std::cerr << "Shader compilation failed: " << log << std::endl; delete [] log; #endif /* DEBUG */ return 0; } glAttachShader( program, shader ); ++entry; } #ifdef GL_VERSION_4_1 if ( GLEW_VERSION_4_1 ) { // glProgramParameteri( program, GL_PROGRAM_SEPARABLE, GL_TRUE ); } #endif /* GL_VERSION_4_1 */ glLinkProgram( program ); GLint linked; glGetProgramiv( program, GL_LINK_STATUS, &linked ); if ( !linked ) { #ifdef _DEBUG GLsizei len; glGetProgramiv( program, GL_INFO_LOG_LENGTH, &len ); GLchar* log = new GLchar[len+1]; glGetProgramInfoLog( program, len, &len, log ); std::cerr << "Shader linking failed: " << log << std::endl; delete [] log; #endif /* DEBUG */ for ( entry = shaders; entry->type != GL_NONE; ++entry ) { glDeleteShader( entry->shader ); entry->shader = 0; } return 0; } return program; } //---------------------------------------------------------------------------- #ifdef __cplusplus } #endif // __cplusplus 
////////////////////////////////////////////////////////////////////////////// // // --- LoadShaders.h --- // ////////////////////////////////////////////////////////////////////////////// #ifndef __LOAD_SHADERS_H__ #define __LOAD_SHADERS_H__ #ifdef __cplusplus extern "C" { #endif // __cplusplus //---------------------------------------------------------------------------- // // LoadShaders() takes an array of ShaderFile structures, each of which // contains the type of the shader, and a pointer a C-style character // string (i.e., a NULL-terminated array of characters) containing the // entire shader source. // // The array of structures is terminated by a final Shader with the // "type" field set to GL_NONE. // // LoadShaders() returns the shader program value (as returned by // glCreateProgram()) on success, or zero on failure. // typedef struct { GLenum type; const char* filename; GLuint shader; } ShaderInfo; GLuint LoadShaders(ShaderInfo*); //---------------------------------------------------------------------------- #ifdef __cplusplus }; #endif // __cplusplus #endif // __LOAD_SHADERS_H__
#include  #include  #include  #include  #include  #include "LoadShaders.h" #include "vmath.h" #include "vgl.h" #include  using namespace std; #define BUFFER_OFFSET(x) ((const void*) (x)) GLuint programID; /* * Arrays to store the indices/names of the Vertex Array Objects and * Buffers. Rather than using the books enum approach I've just * gone out and made a bunch of them and will use them as needed. * * Not the best choice I'm sure. */ GLuint vertexBuffers[10], arrayBuffers[10], elementBuffers[10]; /* * Global variables * The location for the transformation and the current rotation * angle are set up as globals since multiple methods need to * access them. */ float rotationAngle; bool elements; int nbrTriangles, materialToUse=0; map locationMap; // Prototypes GLuint buildProgram(string vertexShaderName, string fragmentShaderName); int glutStartUp(int & argCount, char *argValues[], string windowTitle="No Title", int width = 500, int height = 500); void setAttributes(float lineWidth = 1.0, GLenum face = GL_FRONT_AND_BACK, GLenum fill = GL_FILL); void buildObjects(); void getLocations(); void init(string vertexShader, string fragmentShader); /* * Routine to encapsulate some of the startup routines for GLUT. It returns the window ID of the * single window that is created. */ int glutStartUp(int & argCount, char *argValues[], string title, int width, int height) { int windowID; GLenum glewErrCode; glutInit(&argCount, argValues); glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(width, height); windowID = glutCreateWindow(title.c_str()); glutInitContextVersion(3, 1); glutInitContextProfile(GLUT_CORE_PROFILE); glewErrCode = glewInit(); if (glewErrCode != GLEW_OK) { cerr << "Glew init failed " << glewErrCode << endl; exit(EXIT_FAILURE); } return windowID; } /* * Use the author's routines to build the program and return the program ID. */ GLuint buildProgram(string vertexShaderName, string fragmentShaderName) { /* * Use the Books code to load in the shaders. */ ShaderInfo shaders[] = { { GL_VERTEX_SHADER, vertexShaderName.c_str() }, { GL_FRAGMENT_SHADER, fragmentShaderName.c_str() }, { GL_NONE, NULL } }; GLuint program = LoadShaders(shaders); if (program == 0) { cerr << "GLSL Program didn't load. Error " << endl << "Vertex Shader = " << vertexShaderName << endl << "Fragment Shader = " << fragmentShaderName << endl; } glUseProgram(program); return program; } /* * Set up the clear color, lineWidth, and the fill type for the display. */ void setAttributes(float lineWidth,GLenum face, GLenum fill ) { /* * I'm using wide lines so that they are easier to see on the screen. * In addition, this version fills in the polygons rather than leaving it * as lines. */ glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glLineWidth(lineWidth); glPolygonMode(face, fill); glEnable(GL_DEPTH); } /* * read and/or build the objects to be displayed. Also sets up attributes that are * vertex related. */ void buildObjects() { GLfloat vertices[] = { -0.5, -0.5, -0.5, 1.0, // Triangle 1 -0.5, 0.5, -0.5, 1.0, -0.5, 0.5, 0.5, 1.0, -0.5, -0.5, -0.5, 1.0, // Triangle 2 -0.5, 0.5, 0.5, 1.0, -0.5, -0.5, 0.5, 1.0, }; GLfloat colors[] = { 1.00, 0.00, 0.00, 1.00, 1.00, 0.00, 0.00, 1.00, 1.00, 0.00, 0.00, 1.00, // Triangle 1 -- RED 0.00, 0.24, 1.00, 1.00, 0.00, 0.24, 1.00, 1.00, 0.00, 0.24, 1.00, 1.00, // Triangle 3 -- Blue }; float vertexColors[] = { // r g b a 0.0, 0.0, 0.0, 1.0, // The vertex colors of a unit cube. 0.0, 0.0, 1.0, 1.0, }; GLfloat normals[] = { -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // Triangle 1 -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // Triangle 2 }; glGenVertexArrays(1, vertexBuffers); glBindVertexArray(vertexBuffers[0]); // Alternately... // GLuint vaoID; // glGenVertexArrays(1, &vaoID); // glBindVertexArray(vaoID); // /* * Test code for internal object. */ nbrTriangles = 2; glGenBuffers(1, &(arrayBuffers[0])); glBindBuffer(GL_ARRAY_BUFFER, arrayBuffers[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(colors)+sizeof(normals), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(colors), colors); glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(colors), sizeof(normals), normals); /* * Set up variables into the shader programs (Note: We need the * shaders loaded and built into a program before we do this) */ GLuint vPosition = glGetAttribLocation(programID, "vPosition"); glEnableVertexAttribArray(vPosition); glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); GLuint vColor = glGetAttribLocation(programID, "vColor"); glEnableVertexAttribArray(vColor); glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vertices))); GLuint vNormal = glGetAttribLocation(programID, "vNormal"); glEnableVertexAttribArray(vNormal); glVertexAttribPointer(vNormal, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(nbrTriangles*12*sizeof(float))); } /* * This fills in the locations of most of the uniform variables for the program. * there are better ways of handling this but this is good in going directly from * what we had. * * Revised to get the locations and names of the uniforms from OpenGL. These * are then stored in a map so that we can look up a uniform by name when we * need to use it. The map is still global but it is a little neater than the * version that used all the locations. The locations are still there right now * in case that is more useful for you. * */ void getLocations() { /* * Find out how many uniforms there are and go out there and get them from the * shader program. The locations for each uniform are stored in a global -- locationMap -- * for later retrieval. */ GLint numberBlocks; char uniformName[1024]; int nameLength; GLint size; GLenum type; glGetProgramiv(programID, GL_ACTIVE_UNIFORMS, &numberBlocks); for (int blockIndex = 0; blockIndex < numberBlocks; blockIndex++) { glGetActiveUniform(programID, blockIndex, 1024, &nameLength, &size, &type, uniformName); cout << uniformName << endl; locationMap[string(uniformName)] = blockIndex; } } void init( string vertexShader, string fragmentShader) { setAttributes(1.0f, GL_FRONT_AND_BACK, GL_FILL); programID = buildProgram(vertexShader, fragmentShader); buildObjects(); getLocations(); } /* * Timer routine -- when called it increments the angle by 1 degree, * tells Glut to redraw the screen, and sets a timer for 1/30 of a * second later. */ void timer(int value) { rotationAngle += 1.0f; if (rotationAngle >= 360.0) rotationAngle -= 360.0; glutPostRedisplay(); glutTimerFunc(1000 / 30, timer, 1); } /* * The display routine is basically unchanged at this point. */ void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // needed vmath::mat4 currentMatrix = vmath::rotate(rotationAngle, 0.0f, 1.0f, 0.0f); glUniformMatrix4fv(locationMap["modelingTransform"], 1, GL_TRUE, currentMatrix); glBindVertexArray(vertexBuffers[0]); glBindBuffer(GL_ARRAY_BUFFER, arrayBuffers[0]); glDrawArrays(GL_TRIANGLES, 0, nbrTriangles * 3); glFlush(); } /* * Handle keypresses -- only one recognized in this version is q for quit. */ void keypress(unsigned char key, int x, int y) { switch (key) { case 'q': case 'Q': exit(0); break; default: // do nothing.... break; } } /* * Main program with calls for many of the helper routines. */ int main(int argCount, char *argValues[]) { glutStartUp(argCount, argValues, "My Test of New Routines"); init("project0.vert", "project0.frag"); glutDisplayFunc(display); glutTimerFunc(1000 / 30, timer, 1); glutKeyboardFunc(keypress); glutMainLoop(); }

vmath.h

#ifndef __VMATH_H__ #define __VMATH_H__ #define _USE_MATH_DEFINES 1 // Include constants defined in math.h #include  namespace vmath { template  inline T radians(T angleInRadians) { return angleInRadians * static_cast(180.0/M_PI); } template  class ensure { public: inline ensure() { switch (false) { case false: case cond: break; } } }; template  class vecN; template  class vecN { public: typedef class vecN my_type; // Default constructor does nothing, just like built-in types inline vecN() { // Uninitialized variable } // Copy constructor inline vecN(const vecN& that) { assign(that); } // Construction from scalar inline vecN(T s) { int n; for (n = 0; n < len; n++) { data[n] = s; } } // Assignment operator inline vecN& operator=(const vecN& that) { assign(that); return *this; } inline vecN operator+(const vecN& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] + that.data[n]; return result; } inline vecN& operator+=(const vecN& that) { return (*this = *this + that); } inline vecN operator-() const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = -data[n]; return result; } inline vecN operator-(const vecN& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] - that.data[n]; return result; } inline vecN& operator-=(const vecN& that) { return (*this = *this - that); } inline vecN operator*(const vecN& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] * that.data[n]; return result; } inline vecN& operator*=(const vecN& that) { return (*this = *this * that); } inline vecN operator*(const T& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] * that; return result; } inline vecN& operator*=(const T& that) { assign(*this * that); return *this; } inline vecN operator/(const vecN& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] * that.data[n]; return result; } inline vecN& operator/=(const vecN& that) { assign(*this * that); return *this; } inline vecN operator/(const T& that) const { my_type result; int n; for (n = 0; n < len; n++) result.data[n] = data[n] / that; return result; } inline vecN& operator/(const T& that) { assign(*this / that); } inline T& operator[](int n) { return data[n]; } inline const T& operator[](int n) const { return data[n]; } inline static int size(void) { return len; } inline operator const T* () const { return &data[0]; } protected: T data[len]; inline void assign(const vecN& that) { int n; for (n = 0; n < len; n++) data[n] = that.data[n]; } }; template  class Tvec2 : public vecN { public: typedef vecN base; // Uninitialized variable inline Tvec2() {} // Copy constructor inline Tvec2(const base& v) : base(v) {} // vec2(x, y); inline Tvec2(T x, T y) { base::data[0] = x; base::data[1] = y; } }; template  class Tvec3 : public vecN { public: typedef vecN base; // Uninitialized variable inline Tvec3() {} // Copy constructor inline Tvec3(const base& v) : base(v) {} // vec3(x, y, z); inline Tvec3(T x, T y, T z) { base::data[0] = x; base::data[1] = y; base::data[2] = z; } // vec3(v, z); inline Tvec3(const Tvec2& v, T z) { base::data[0] = v[0]; base::data[1] = v[1]; base::data[2] = z; } // vec3(x, v) inline Tvec3(T x, const Tvec2& v) { base::data[0] = x; base::data[1] = v[0]; base::data[2] = v[1]; } }; template  class Tvec4 : public vecN { public: typedef vecN base; // Uninitialized variable inline Tvec4() {} // Copy constructor inline Tvec4(const base& v) : base(v) {} // vec4(x, y, z, w); inline Tvec4(T x, T y, T z, T w) { base::data[0] = x; base::data[1] = y; base::data[2] = z; base::data[3] = w; } // vec4(v, z, w); inline Tvec4(const Tvec2& v, T z, T w) { base::data[0] = v[0]; base::data[1] = v[1]; base::data[2] = z; base::data[3] = w; } // vec4(x, v, w); inline Tvec4(T x, const Tvec2& v, T w) { base::data[0] = x; base::data[1] = v[0]; base::data[2] = v[1]; base::data[3] = w; } // vec4(x, y, v); inline Tvec4(T x, T y, const Tvec2& v) { base::data[0] = x; base::data[1] = y; base::data[2] = v[0]; base::data[3] = v[1]; } // vec4(v1, v2); inline Tvec4(const Tvec2& u, const Tvec2& v) { base::data[0] = u[0]; base::data[1] = u[1]; base::data[2] = v[0]; base::data[3] = v[1]; } // vec4(v, w); inline Tvec4(const Tvec3& v, T w) { base::data[0] = v[0]; base::data[1] = v[1]; base::data[2] = v[2]; base::data[3] = w; } // vec4(x, v); inline Tvec4(T x, const Tvec3& v) { base::data[0] = x; base::data[1] = v[0]; base::data[2] = v[1]; base::data[3] = v[2]; } }; typedef Tvec2 vec2; typedef Tvec2 ivec2; typedef Tvec2 uvec2; typedef Tvec2 dvec2; typedef Tvec3 vec3; typedef Tvec3 ivec3; typedef Tvec3 uvec3; typedef Tvec3 dvec3; typedef Tvec4 vec4; typedef Tvec4 ivec4; typedef Tvec4 uvec4; typedef Tvec4 dvec4; template  static inline const vecN operator * (T x, const vecN& v) { return v * x; } template  static inline const Tvec2 operator / (T x, const Tvec2& v) { return Tvec2(x / v[0], x / v[1]); } template  static inline const Tvec3 operator / (T x, const Tvec3& v) { return Tvec3(x / v[0], x / v[1], x / v[2]); } template  static inline const Tvec4 operator / (T x, const Tvec4& v) { return Tvec4(x / v[0], x / v[1], x / v[2], x / v[3]); } template  static inline T dot(const vecN& a, const vecN& b) { int n; T total = T(0); for (n = 0; n < len; n++) { total += a[n] * b[n]; } return total; } template  static inline vecN cross(const vecN& a, const vecN& b) { return Tvec3(a[1] * b[2] - b[1] * a[2], a[2] * b[0] - b[2] * a[0], a[0] * b[1] - b[0] * a[1]); } template  static inline T length(const vecN& v) { T result(0); for (int i = 0; i < v.size(); ++i) { result += v[i] * v[i]; } return (T)sqrt(result); } template  static inline vecN normalize(const vecN& v) { return v / length(v); } template  static inline T distance(const vecN& a, const vecN& b) { return length(b - a); } template  class matNM { public: typedef class matNM my_type; typedef class vecN vector_type; // Default constructor does nothing, just like built-in types inline matNM() { // Uninitialized variable } // Copy constructor inline matNM(const matNM& that) { assign(that); } // Construction from element type // explicit to prevent assignment from T explicit inline matNM(T f) { for (int n = 0; n < w; n++) { data[n] = f; } } // Construction from vector inline matNM(const vector_type& v) { for (int n = 0; n < w; n++) { data[n] = v; } } // Assignment operator inline matNM& operator=(const my_type& that) { assign(that); return *this; } inline matNM operator+(const my_type& that) const { my_type result; int n; for (n = 0; n < w; n++) result.data[n] = data[n] + that.data[n]; return result; } inline my_type& operator+=(const my_type& that) { return (*this = *this + that); } inline my_type operator-(const my_type& that) const { my_type result; int n; for (n = 0; n < w; n++) result.data[n] = data[n] - that.data[n]; return result; } inline my_type& operator-=(const my_type& that) { return (*this = *this - that); } // Matrix multiply. // TODO: This only works for square matrices. Need more template skill to make a non-square version. inline my_type operator*(const my_type& that) const { ensure(); my_type result(0); for (int j = 0; j < w; j++) { for (int i = 0; i < h; i++) { T sum(0); for (int n = 0; n < w; n++) { sum += data[n][i] * that[j][n]; } result[j][i] = sum; } } return result; } inline my_type& operator*=(const my_type& that) { return (*this = *this * that); } inline vector_type& operator[](int n) { return data[n]; } inline const vector_type& operator[](int n) const { return data[n]; } inline operator T*() { return &data[0][0]; } inline operator const T*() const { return &data[0][0]; } inline matNM transpose(void) const { matNM result; int x, y; for (y = 0; y < w; y++) { for (x = 0; x < h; x++) { result[x][y] = data[y][x]; } } return result; } static inline my_type identity() { ensure(); my_type result(0); for (int i = 0; i < w; i++) { result[i][i] = 1; } return result; } static inline int width(void) { return w; } static inline int height(void) { return h; } protected: // Column primary data (essentially, array of vectors) vecN data[w]; // Assignment function - called from assignment operator and copy constructor. inline void assign(const matNM& that) { int n; for (n = 0; n < w; n++) data[n] = that.data[n]; } }; /* template  class TmatN : public matNM { public: typedef matNM base; typedef TmatN my_type; inline TmatN() {} inline TmatN(const my_type& that) : base(that) {} inline TmatN(float f) : base(f) {} inline TmatN(const vecN& v) : base(v) {} inline my_type transpose(void) { my_type result; int x, y; for (y = 0; y < h; y++) { for (x = 0; x < h; x++) { result[x][y] = data[y][x]; } } return result; } }; */ template  class Tmat4 : public matNM { public: typedef matNM base; typedef Tmat4 my_type; inline Tmat4() {} inline Tmat4(const my_type& that) : base(that) {} inline Tmat4(const base& that) : base(that) {} inline Tmat4(const vecN& v) : base(v) {} inline Tmat4(const vecN& v0, const vecN& v1, const vecN& v2, const vecN& v3) { base::data[0] = v0; base::data[1] = v1; base::data[2] = v2; base::data[3] = v3; } }; typedef Tmat4 mat4; typedef Tmat4 imat4; typedef Tmat4 umat4; typedef Tmat4 dmat4; static inline mat4 frustum(float left, float right, float bottom, float top, float n, float f) { mat4 result(mat4::identity()); if ((right == left) || (top == bottom) || (n == f) || (n < 0.0) || (f < 0.0)) return result; result[0][0] = (2.0f * n) / (right - left); result[1][1] = (2.0f * n) / (top - bottom); result[2][0] = (right + left) / (right - left); result[2][1] = (top + bottom) / (top - bottom); result[2][2] = -(f + n) / (f - n); result[2][3]= -1.0f; result[3][2] = -(2.0f * f * n) / (f - n); result[3][3] = 0.0f; return result; } static inline mat4 perspective(float fovy /* in degrees */, float aspect, float n, float f) { float top = n * tan(radians(0.5f*fovy)); // bottom = -top float right = top * aspect; // left = -right return frustum(-right, right, -top, top, n, f); } template  static inline Tmat4 lookat(vecN eye, vecN center, vecN up) { const Tvec3 f = normalize(center - eye); const Tvec3 upN = normalize(up); const Tvec3 s = cross(f, upN); const Tvec3 u = cross(s, f); const Tmat4 M = Tmat4(Tvec4(s[0], u[0], -f[0], T(0)), Tvec4(s[1], u[1], -f[1], T(0)), Tvec4(s[2], u[2], -f[2], T(0)), Tvec4(T(0), T(0), T(0), T(1))); return M * translate(-eye); } template  static inline Tmat4 translate(T x, T y, T z) { return Tmat4(Tvec4(1.0f, 0.0f, 0.0f, 0.0f), Tvec4(0.0f, 1.0f, 0.0f, 0.0f), Tvec4(0.0f, 0.0f, 1.0f, 0.0f), Tvec4(x, y, z, 1.0f)); } template  static inline Tmat4 translate(const vecN& v) { return translate(v[0], v[1], v[2]); } template  static inline Tmat4 scale(T x, T y, T z) { return Tmat4(Tvec4(x, 0.0f, 0.0f, 0.0f), Tvec4(0.0f, y, 0.0f, 0.0f), Tvec4(0.0f, 0.0f, z, 0.0f), Tvec4(0.0f, 0.0f, 0.0f, 1.0f)); } template  static inline Tmat4 scale(const Tvec4& v) { return scale(v[0], v[1], v[2]); } template  static inline Tmat4 scale(T x) { return Tmat4(Tvec4(x, 0.0f, 0.0f, 0.0f), Tvec4(0.0f, x, 0.0f, 0.0f), Tvec4(0.0f, 0.0f, x, 0.0f), Tvec4(0.0f, 0.0f, 0.0f, 1.0f)); } template  static inline Tmat4 rotate(T angle, T x, T y, T z) { Tmat4 result; const T x2 = x * x; const T y2 = y * y; const T z2 = z * z; float rads = float(angle) * 0.0174532925f; const float c = cosf(rads); const float s = sinf(rads); const float omc = 1.0f - c; result[0] = Tvec4(T(x2 * omc + c), T(y * x * omc + z * s), T(x * z * omc - y * s), T(0)); result[1] = Tvec4(T(x * y * omc - z * s), T(y2 * omc + c), T(y * z * omc + x * s), T(0)); result[2] = Tvec4(T(x * z * omc + y * s), T(y * z * omc - x * s), T(z2 * omc + c), T(0)); result[3] = Tvec4(T(0), T(0), T(0), T(1)); return result; } template  static inline Tmat4 rotate(T angle, const vecN& v) { return rotate(angle, v[0], v[1], v[2]); } #ifdef min #undef min #endif template  static inline T min(T a, T b) { return a < b ? a : b; } #ifdef max #undef max #endif template  static inline T max(T a, T b) { return a >= b ? a : b; } template  static inline vecN min(const vecN& x, const vecN& y) { vecN t; int n; for (n = 0; n < N; n++) { t[n] = min(x[n], y[n]); } return t; } template  static inline vecN max(const vecN& x, const vecN& y) { vecN t; int n; for (n = 0; n < N; n++) { t[n] = max(x[n], y[n]); } return t; } template  static inline vecN clamp(const vecN& x, const vecN& minVal, const vecN& maxVal) { return min(max(x, minVal), maxVal); } template  static inline vecN smoothstep(const vecN& edge0, const vecN& edge1, const vecN& x) { vecN t; t = clamp((x - edge0) / (edge1 - edge0), vecN(T(0)), vecN(T(1))); return t * t * (vecN(T(3)) - vecN(T(2)) * t); } template  static inline matNM matrixCompMult(const matNM& x, const matNM& y) { matNM result; int i, j; for (j = 0; j < M; ++j) { for (i = 0; i < N; ++i) { result[i][j] = x[i][j] * y[i][j]; } } return result; } template  static inline vecN operator*(const vecN& vec, const matNM& mat) { int n, m; vecN result(T(0)); for (m = 0; m < M; m++) { for (n = 0; n < N; n++) { result[n] += vec[m] * mat[n][m]; } } return result; } }; #endif /* __VMATH_H__ */

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

More Books

Students also viewed these Databases questions