From fc40bbdffec981b4215ac12b1c5c6b7d04ec2ef0 Mon Sep 17 00:00:00 2001 From: Angelo Papenhoff Date: Sat, 17 Jan 2015 21:51:04 +0100 Subject: [PATCH] Added OpenGL test. --- tests/gl/Makefile | 21 + tests/gl/Makefile.mingw | 20 + tests/gl/camera.cpp | 168 +++++ tests/gl/camera.h | 37 ++ tests/gl/gl.h | 6 + tests/gl/glshader.cpp | 61 ++ tests/gl/main.cpp | 341 ++++++++++ tests/gl/math.cpp | 1227 ++++++++++++++++++++++++++++++++++++ tests/gl/math/conversion.h | 93 +++ tests/gl/math/dquat.h | 45 ++ tests/gl/math/mat3.h | 43 ++ tests/gl/math/mat4.h | 52 ++ tests/gl/math/math.h | 21 + tests/gl/math/quat.h | 54 ++ tests/gl/math/vec3.h | 40 ++ tests/gl/math/vec4.h | 39 ++ tests/gl/rwtest.h | 15 + 17 files changed, 2283 insertions(+) create mode 100755 tests/gl/Makefile create mode 100755 tests/gl/Makefile.mingw create mode 100755 tests/gl/camera.cpp create mode 100755 tests/gl/camera.h create mode 100755 tests/gl/gl.h create mode 100755 tests/gl/glshader.cpp create mode 100755 tests/gl/main.cpp create mode 100755 tests/gl/math.cpp create mode 100755 tests/gl/math/conversion.h create mode 100755 tests/gl/math/dquat.h create mode 100755 tests/gl/math/mat3.h create mode 100755 tests/gl/math/mat4.h create mode 100755 tests/gl/math/math.h create mode 100755 tests/gl/math/quat.h create mode 100755 tests/gl/math/vec3.h create mode 100755 tests/gl/math/vec4.h create mode 100755 tests/gl/rwtest.h diff --git a/tests/gl/Makefile b/tests/gl/Makefile new file mode 100755 index 0000000..9cfc2c7 --- /dev/null +++ b/tests/gl/Makefile @@ -0,0 +1,21 @@ +BUILDDIR = build +SRC = main.cpp glshader.cpp math.cpp camera.cpp +OBJ = $(patsubst %.cpp, $(BUILDDIR)/%.o, $(SRC)) +DEP = $(patsubst %.cpp, $(BUILDDIR)/%.d, $(SRC)) +RWDIR=$(HOME)/src/librw +LDLIBS=-pthread -lX11 -lXrandr -lXi -lXxf86vm -lGL -lGLEW -lm +CFLAGS=-g -I$(RWDIR) -Wall -Wextra + +rwtest: $(OBJ) $(RWDIR)/librw-opengl.a /usr/local/lib/libglfw3.a + $(CXX) $^ $(LDLIBS) -o $@ + +$(BUILDDIR)/%.o: %.cpp + $(CXX) $(CFLAGS) -c $< -o $@ + +$(BUILDDIR)/%.d: %.cpp + $(CXX) -MM -MT '$(patsubst %.cpp,$(BUILDDIR)%.o,$<)' $(CFLAGS) $< > $@ + +clean: + rm $(BUILDDIR)/* rwtest + +-include $(DEP) diff --git a/tests/gl/Makefile.mingw b/tests/gl/Makefile.mingw new file mode 100755 index 0000000..7c48528 --- /dev/null +++ b/tests/gl/Makefile.mingw @@ -0,0 +1,20 @@ +BUILDDIR = build +SRC = main.cpp glshader.cpp math.cpp camera.cpp +OBJ = $(patsubst %.cpp, $(BUILDDIR)/%.o, $(SRC)) +DEP = $(patsubst %.cpp, $(BUILDDIR)/%.d, $(SRC)) +RWDIR=$(HOME)/src/librw +LDLIBS=-static -lglfw3 -lglew32 -lopengl32 -lgdi32 +CFLAGS=-g -I$(RWDIR) -Wall -Wextra -DGLEW_STATIC + +rwtest: $(OBJ) $(RWDIR)/librw.a + $(CXX) $^ $(LDLIBS) -o $@ + +$(BUILDDIR)/%.o: %.cpp + $(CXX) $(CFLAGS) -c $< -o $@ + +$(BUILDDIR)/%.d: %.cpp + $(CXX) -MM -MT '$(patsubst %.cpp,$(BUILDDIR)%.o,$<)' $(CFLAGS) $< > $@ + +dep: $(DEP) + +-include $(DEP) diff --git a/tests/gl/camera.cpp b/tests/gl/camera.cpp new file mode 100755 index 0000000..4e2b6f0 --- /dev/null +++ b/tests/gl/camera.cpp @@ -0,0 +1,168 @@ +#include "rwtest.h" + +using namespace std; + +void +Camera::look(void) +{ + projMat = Mat4::perspective(fov, aspectRatio, n, f); + viewMat = Mat4::lookat(position, target, up); + +// state->mat4(PMAT,true)->val = Mat4::perspective(fov, aspectRatio, n, f); +// Mat4 mv = Mat4::lookat(position, target, up); +// state->mat4(MVMAT, true)->val = mv; +// state->mat3(NORMALMAT, true)->val = Mat3(mv); +} + +void +Camera::setPosition(Vec3 q) +{ + position = q; +} + +Vec3 +Camera::getPosition(void) +{ + return position; +} + +void +Camera::setTarget(Vec3 q) +{ + position -= target - q; + target = q; +} + +Vec3 +Camera::getTarget(void) +{ + return target; +} + +float +Camera::getHeading(void) +{ + Vec3 dir = target - position; + float a = atan2(dir.y, dir.x)-PI/2.0f; + return local_up.z < 0.0f ? a-PI : a; +} + +void +Camera::turn(float yaw, float pitch) +{ + yaw /= 2.0f; + pitch /= 2.0f; + Quat dir = Quat(target - position); + Quat r(cos(yaw), 0.0f, 0.0f, sin(yaw)); + dir = r*dir*r.K(); + local_up = Vec3(r*Quat(local_up)*r.K()); + + Quat right = dir.wedge(Quat(local_up)).U(); + r = Quat(cos(pitch), right*sin(pitch)); + dir = r*dir*r.K(); + local_up = Vec3(right.wedge(dir).U()); + if(local_up.z >=0) up.z = 1; + else up.z = -1; + + target = position + Vec3(dir); +} + +void +Camera::orbit(float yaw, float pitch) +{ + yaw /= 2.0f; + pitch /= 2.0f; + Quat dir = Quat(target - position); + Quat r(cos(yaw), 0.0f, 0.0f, sin(yaw)); + dir = r*dir*r.K(); + local_up = Vec3(r*Quat(local_up)*r.K()); + + Quat right = dir.wedge(Quat(local_up)).U(); + r = Quat(cos(-pitch), right*sin(-pitch)); + dir = r*dir*r.K(); + local_up = Vec3(right.wedge(dir).U()); + if(local_up.z >=0) up.z = 1; + else up.z = -1; + + position = target - Vec3(dir); +} + +void +Camera::dolly(float dist) +{ + Vec3 dir = (target - position).normalized()*dist; + position += dir; + target += dir; +} + +void +Camera::zoom(float dist) +{ + Vec3 dir = target - position; + float curdist = dir.norm(); + if(dist >= curdist) + dist = curdist-0.01f; + dir = dir.normalized()*dist; + position += dir; +} + +void +Camera::pan(float x, float y) +{ + Vec3 dir = (target-position).normalized(); + Vec3 right = dir.cross(up).normalized(); +// Vec3 local_up = right.cross(dir).normalized(); + dir = right*x + local_up*y; + position += dir; + target += dir; + +} + +float +Camera::sqDistanceTo(Vec3 q) +{ + return (position - q).normsq(); +} + +float +Camera::distanceTo(Vec3 q) +{ + return (position - q).norm(); +} + +void +Camera::setFov(float f) +{ + fov = f; +} + +float +Camera::getFov(void) +{ + return fov; +} + +void +Camera::setAspectRatio(float r) +{ + aspectRatio = r; +} + +void +Camera::setNearFar(float n, float f) +{ + this->n = n; + this->f = f; +} + +Camera::Camera() +{ + position = Vec3(0.0f, 6.0f, 0.0f); + target = Vec3(0.0f, 0.0f, 0.0f); + local_up = up = Vec3(0.0f, 0.0f, 1.0f); + fov = 55.0f; + aspectRatio = 1.0f; + n = 0.1f; + f = 100.0f; +} + diff --git a/tests/gl/camera.h b/tests/gl/camera.h new file mode 100755 index 0000000..0a47263 --- /dev/null +++ b/tests/gl/camera.h @@ -0,0 +1,37 @@ +class Camera +{ +private: + Vec3 position; + Vec3 target; + Vec3 up; + Vec3 local_up; + + float fov, aspectRatio; + float n, f; + +public: + Mat4 projMat; + Mat4 viewMat; + + void setPosition(Vec3 q); + Vec3 getPosition(void); + void setTarget(Vec3 q); + Vec3 getTarget(void); + float getHeading(void); + + void turn(float yaw, float pitch); + void orbit(float yaw, float pitch); + void dolly(float dist); + void zoom(float dist); + void pan(float x, float y); + + void setFov(float f); + float getFov(void); + void setAspectRatio(float r); + void setNearFar(float n, float f); + + void look(void); + float distanceTo(Vec3 q); + float sqDistanceTo(Vec3 q); + Camera(void); +}; diff --git a/tests/gl/gl.h b/tests/gl/gl.h new file mode 100755 index 0000000..d5ee854 --- /dev/null +++ b/tests/gl/gl.h @@ -0,0 +1,6 @@ +namespace gl { + +GLint linkProgram(GLint vertshader, GLint fragshader); +GLint compileShader(const char **src, int count, int type); + +} diff --git a/tests/gl/glshader.cpp b/tests/gl/glshader.cpp new file mode 100755 index 0000000..b8b525d --- /dev/null +++ b/tests/gl/glshader.cpp @@ -0,0 +1,61 @@ +#include "rwtest.h" + +namespace gl { + +GLint +linkProgram(GLint vertshader, GLint fragshader) +{ + GLint success; + GLint len; + char *log; + + GLint program = glCreateProgram(); + assert(program != 0); + glBindAttribLocation(program, 0, "in_vertex"); + glBindAttribLocation(program, 1, "in_texCoord"); + glBindAttribLocation(program, 2, "in_normal"); + glBindAttribLocation(program, 3, "in_color"); + glBindAttribLocation(program, 4, "in_weight"); + glBindAttribLocation(program, 5, "in_indices"); + glBindAttribLocation(program, 6, "in_extraColor"); + glAttachShader(program, vertshader); + glAttachShader(program, fragshader); + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, &success); + if(!success){ + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); + log = new char[len]; + glGetProgramInfoLog(program, len, NULL, log); + fprintf(stderr, "Link Error: %s\n", log); + delete[] log; + glDeleteProgram(program); + return 0; + } + return program; +} + +GLint +compileShader(const char **src, int count, int type) +{ + GLint success; + GLint len; + char *log; + + GLint shader = glCreateShader(type); + assert(shader != 0); + glShaderSource(shader, count, src, NULL); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if(!success){ + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); + log = new char[len]; + glGetShaderInfoLog(shader, len, NULL, log); + fprintf(stderr, "Shader Error: %s\n", log); + delete[] log; + glDeleteProgram(shader); + return 0; + } + return shader; +} + +} diff --git a/tests/gl/main.cpp b/tests/gl/main.cpp new file mode 100755 index 0000000..26b0c8b --- /dev/null +++ b/tests/gl/main.cpp @@ -0,0 +1,341 @@ +#include "rwtest.h" + +using namespace std; + +int screenWidth = 640, screenHeight= 480; +bool running = true; +Camera *camera; + +GLint program; +GLuint vbo; + +Rw::Clump *clump; + +char *filename; + +void +renderAtomic(Rw::Atomic *atomic) +{ + using namespace Rw; + static GLenum prim[] = { + GL_TRIANGLES, GL_TRIANGLE_STRIP + }; + Geometry *geo = atomic->geometry; + if(!(geo->geoflags & Geometry::NATIVE)) + Gl::Instance(atomic); + Gl::InstanceDataHeader *inst = (Gl::InstanceDataHeader*)geo->instData; + MeshHeader *meshHeader = geo->meshHeader; + + Frame *frm = atomic->frame; + frm->updateLTM(); + glUniformMatrix4fv(glGetUniformLocation(program, "worldMat"), + 1, GL_FALSE, frm->ltm); + + glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); + if(inst->vbo == 0 && inst->ibo == 0) + Gl::UploadGeo(geo); + glBindBuffer(GL_ARRAY_BUFFER, inst->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, inst->ibo); + Gl::SetAttribPointers(inst); + + uint64 offset = 0; + for(uint32 i = 0; i < meshHeader->numMeshes; i++){ + Mesh *mesh = &meshHeader->mesh[i]; + glDrawElements(prim[meshHeader->flags], mesh->numIndices, + GL_UNSIGNED_SHORT, (void*)offset); + offset += mesh->numIndices*2; + } + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(2); + glDisableVertexAttribArray(3); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +void +render(void) +{ + glUseProgram(program); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + camera->look(); + glUniformMatrix4fv(glGetUniformLocation(program, "projMat"), + 1, GL_FALSE, camera->projMat.cr); + glUniformMatrix4fv(glGetUniformLocation(program, "viewMat"), + 1, GL_FALSE, camera->viewMat.cr); + + glVertexAttrib3f(2, -0.5f, 0.5f, 0.70710f); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(3); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 28, (GLvoid*)0); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 28, (GLvoid*)12); + glDrawArrays(GL_LINES, 0, 6); + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(3); + + for(Rw::uint32 i = 0; i < clump->numAtomics; i++){ + char *name = PLUGINOFFSET(char, clump->atomicList[i]->frame, + Rw::NodeNameOffset); + if(strstr(name, "_dam") || strstr(name, "_vlo")) + continue; + renderAtomic(clump->atomicList[i]); + } +} + +void +init(void) +{ + glClearColor(0.3f, 0.3f, 0.3f, 1.0f); + glEnable(GL_DEPTH_TEST); + const char *shadersrc = + "#version 120\n" + "#ifdef VERTEX\n" + "uniform mat4 projMat;" + "uniform mat4 viewMat;" + "uniform mat4 worldMat;" + "attribute vec3 in_vertex;" + "attribute vec3 in_texColor;" + "attribute vec3 in_normal;" + "attribute vec4 in_color;" + "varying vec4 v_color;" + "vec3 lightdir = vec3(0.5, -0.5, -0.70710);" + "void main()" + "{" + " gl_Position = projMat * viewMat * worldMat * vec4(in_vertex, 1.0);" + " vec3 n = mat3(worldMat) * in_normal;" + " float l = max(0.0, dot(n, -lightdir));" + " v_color = in_color*l;" + "}\n" + "#endif\n" + "#ifdef FRAGMENT\n" + "varying vec4 v_color;" + "void main()" + "{" + " gl_FragColor = v_color;" + "}\n" + "#endif\n"; + const char *srcarr[] = { "#define VERTEX", shadersrc }; + GLint vertshader = gl::compileShader(srcarr, 2, GL_VERTEX_SHADER); + assert(vertshader != 0); + srcarr[0] = "#define FRAGMENT"; + GLint fragshader = gl::compileShader(srcarr, 2, GL_FRAGMENT_SHADER); + assert(fragshader != 0); + program = gl::linkProgram(vertshader, fragshader); + assert(program != 0); + + GLfloat vertarray[] = { + 0.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 1.0f, + + 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, + }; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertarray), + vertarray, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + camera = new Camera; + camera->setAspectRatio(1.0f*screenWidth/screenHeight); + camera->setNearFar(0.1f, 450.0f); + camera->setTarget(Vec3(0.0f, 0.0f, 0.0f)); + camera->setPosition(Vec3(0.0f, 5.0f, 0.0f)); + + Rw::RegisterMaterialRightsPlugin(); + Rw::RegisterMatFXPlugin(); + Rw::RegisterAtomicRightsPlugin(); + Rw::RegisterHAnimPlugin(); + Rw::RegisterNodeNamePlugin(); + Rw::RegisterBreakableModelPlugin(); + Rw::RegisterExtraVertColorPlugin(); + Rw::Ps2::RegisterADCPlugin(); + Rw::RegisterSkinPlugin(); + Rw::RegisterNativeDataPlugin(); +// Rw::Ps2::RegisterNativeDataPlugin(); + Rw::RegisterMeshPlugin(); + + Rw::StreamFile in; +// in.open("player-vc-ogl.dff", "rb"); +// in.open("player-iii.dff", "rb"); +// in.open("admiral-ogl.dff", "rb"); + in.open(filename, "rb"); + Rw::FindChunk(&in, Rw::ID_CLUMP, NULL, NULL); + clump = Rw::Clump::streamRead(&in); + assert(clump); + in.close(); +} + +void +keypress(GLFWwindow *w, int key, int scancode, int action, int mods) +{ + if(action != GLFW_PRESS) + return; + + switch(key){ + case 'Q': + case GLFW_KEY_ESCAPE: + running = false; + break; + } +} + +static int lastX, lastY; +static int clickX, clickY; +static bool isLDown, isMDown, isRDown; +static bool isShiftDown, isCtrlDown, isAltDown; + +void +mouseButton(GLFWwindow *w, int button, int action, int mods) +{ + double x, y; + glfwGetCursorPos(w, &x, &y); + if(action == GLFW_PRESS){ + lastX = clickX = x; + lastY = clickY = y; + if(button == GLFW_MOUSE_BUTTON_LEFT) + isLDown = true; + if(button == GLFW_MOUSE_BUTTON_MIDDLE) + isMDown = true; + if(button == GLFW_MOUSE_BUTTON_RIGHT) + isRDown = true; + }else if(action == GLFW_RELEASE){ + if(button == GLFW_MOUSE_BUTTON_LEFT) + isLDown = false; + if(button == GLFW_MOUSE_BUTTON_MIDDLE) + isMDown = false; + if(button == GLFW_MOUSE_BUTTON_RIGHT) + isRDown = false; + } +} + +void +mouseMotion(GLFWwindow *w, double x, double y) +{ + GLfloat dx, dy; + static int xoff = 0, yoff = 0; + static bool wrappedLast = false; + int width, height; + + glfwGetWindowSize(w, &width, &height); + + dx = float(lastX - x) / float(width); + dy = float(lastY - y) / float(height); + /* Wrap the mouse if it goes over the window border. + * Unfortunately, after glfwSetMousePos is done, there can be old + * events with an old mouse position, + * hence the check if the pointer was wrapped the last time. */ + if((isLDown || isMDown || isRDown) && + (x < 0 || y < 0 || x >= width || y >= height)){ + if(wrappedLast){ + dx = float(lastX-xoff - x) / float(width); + dy = float(lastY-yoff - y) / float(height); + } + xoff = yoff = 0; + while (x+xoff >= width) xoff -= width; + while (y+yoff >= height) yoff -= height; + while (x+xoff < 0) xoff += width; + while (y+yoff < 0) yoff += height; + glfwSetCursorPos(w, x+xoff, y+yoff); + wrappedLast = true; + }else{ + wrappedLast = false; + xoff = yoff = 0; + } + lastX = x+xoff; + lastY = y+yoff; + if(isLDown){ + if(isShiftDown) + camera->turn(dx*2.0f, dy*2.0f); + else + camera->orbit(dx*2.0f, -dy*2.0f); + } + if(isMDown){ + if(isShiftDown) + ; + else + camera->pan(dx*8.0f, -dy*8.0f); + } + if(isRDown){ + if(isShiftDown) + ; + else + camera->zoom(dx*12.0f); + } +} + +void +resize(GLFWwindow*, int width, int height) +{ + screenWidth = width; + screenHeight = height; + glViewport(0, 0, screenWidth, screenHeight); + camera->setAspectRatio(1.0f*screenWidth/screenHeight); +} + +void +closewindow(GLFWwindow*) +{ + running = false; +} + +int +main(int argc, char *argv[]) +{ + if(argc < 2) + return 1; + filename = argv[1]; + + if(!glfwInit()){ + fprintf(stderr, "Error: could not initialize GLFW\n"); + return 1; + } + GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, + "OpenGL", 0, 0); + if(!window){ + fprintf(stderr, "Error: could not create GLFW window\n"); + glfwTerminate(); + return 1; + } + glfwMakeContextCurrent(window); + GLenum status = glewInit(); + if(status != GLEW_OK){ + fprintf(stderr, "Error: %s\n", glewGetErrorString(status)); + return 1; + } + if(!GLEW_VERSION_2_0){ + fprintf(stderr, "Error: OpenGL 2.0 needed\n"); + return 1; + } + + init(); + + glfwSetWindowSizeCallback(window, resize); + glfwSetWindowCloseCallback(window, closewindow); + glfwSetMouseButtonCallback(window, mouseButton); + glfwSetCursorPosCallback(window, mouseMotion); + glfwSetKeyCallback(window, keypress); + while(running){ + glfwPollEvents(); + isShiftDown = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + isCtrlDown = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS; + isAltDown = glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS; + + render(); + glfwSwapBuffers(window); + } + + glfwTerminate(); + return 0; +} diff --git a/tests/gl/math.cpp b/tests/gl/math.cpp new file mode 100755 index 0000000..a1e3c76 --- /dev/null +++ b/tests/gl/math.cpp @@ -0,0 +1,1227 @@ +#include "math/math.h" + +/* + * Vec3 + */ + +std::ostream& +operator<<(std::ostream& of, const Vec3 &v) +{ + v.print(of); + return of; +} + + +Vec3::Vec3(void) + : x(0.0f), y(0.0f), z(0.0f) +{ +} + +Vec3::Vec3(float x, float y, float z) + : x(x), y(y), z(z) +{ +} + +Vec3::Vec3(float *v) + : x(v[0]), y(v[1]), z(v[2]) +{ +} + +float* +Vec3::ptr(void) +{ + return &x; +} + +Vec3 +Vec3::operator-(void) const +{ + return Vec3(-x, -y, -z); +} + +Vec3 +Vec3::operator+(const Vec3 &rhs) const +{ + return Vec3(this->x+rhs.x, this->y+rhs.y, this->z+rhs.z); +} + +Vec3 +Vec3::operator-(const Vec3 &rhs) const +{ + return Vec3(this->x-rhs.x, this->y-rhs.y, this->z-rhs.z); +} + +Vec3 +Vec3::operator*(float rhs) const +{ + return Vec3(this->x*rhs, this->y*rhs, this->z*rhs); +} + +Vec3 +Vec3::operator/(float rhs) const +{ + return Vec3(this->x/rhs, this->y/rhs, this->z/rhs); +} + +Vec3& +Vec3::operator+=(const Vec3 &rhs) +{ + *this = *this + rhs; + return *this; +} + +Vec3& +Vec3::operator-=(const Vec3 &rhs) +{ + *this = *this - rhs; + return *this; +} + +Vec3& +Vec3::operator*=(float rhs) +{ + *this = *this * rhs; + return *this; +} + +Vec3& +Vec3::operator/=(float rhs) +{ + *this = *this / rhs; + return *this; +} + +bool +Vec3::operator==(const Vec3 &rhs) const +{ + return (this->x == rhs.x) && + (this->y == rhs.y) && + (this->z == rhs.z); +} + +bool +Vec3::operator!=(const Vec3 &rhs) const +{ + return (this->x != rhs.x) || + (this->y != rhs.y) || + (this->z != rhs.z); +} + +float +Vec3::norm(void) const +{ + return sqrt(normsq()); +} + +float +Vec3::normsq(void) const +{ + return x*x + y*y + z*z; +} + +Vec3 +Vec3::normalized(void) const +{ + return Vec3(*this)/norm(); +} + +float +Vec3::dot(const Vec3 &rhs) const +{ + return this->x*rhs.x + this->y*rhs.y + this->z*rhs.z; +} + +Vec3 +Vec3::cross(const Vec3 &rhs) const +{ + return Vec3(this->y*rhs.z - this->z*rhs.y, + this->z*rhs.x - this->x*rhs.z, + this->x*rhs.y - this->y*rhs.x); +} + +void +Vec3::print(std::ostream &of) const +{ + of << "V3(" << x << ", " << y << ", " << z << ")"; +} + +/* + * Vec4 + */ + +std::ostream& +operator<<(std::ostream& of, const Vec4 &v) +{ + v.print(of); + return of; +} + + +Vec4::Vec4(void) + : x(0.0f), y(0.0f), z(0.0f), w(0.0f) +{ +} + +Vec4::Vec4(float x, float y, float z, float w) + : x(x), y(y), z(z), w(w) +{ +} + +Vec4::Vec4(float *v) + : x(v[0]), y(v[1]), z(v[2]), w(v[3]) +{ +} + +float* +Vec4::ptr(void) +{ + return &x; +} + +Vec4 +Vec4::operator-(void) const +{ + return Vec4(-x, -y, -z, -w); +} + +Vec4 +Vec4::operator+(const Vec4 &rhs) const +{ + return Vec4(this->x+rhs.x, this->y+rhs.y, this->z+rhs.z, this->w+rhs.w); +} + +Vec4 +Vec4::operator-(const Vec4 &rhs) const +{ + return Vec4(this->x-rhs.x, this->y-rhs.y, this->z-rhs.z, this->w-rhs.w); +} + +Vec4 +Vec4::operator*(float rhs) const +{ + return Vec4(this->x*rhs, this->y*rhs, this->z*rhs, this->w*rhs); +} + +Vec4 +Vec4::operator/(float rhs) const +{ + return Vec4(this->x/rhs, this->y/rhs, this->z/rhs, this->w/rhs); +} + +Vec4& +Vec4::operator+=(const Vec4 &rhs) +{ + *this = *this + rhs; + return *this; +} + +Vec4& +Vec4::operator-=(const Vec4 &rhs) +{ + *this = *this - rhs; + return *this; +} + +Vec4& +Vec4::operator*=(float rhs) +{ + *this = *this * rhs; + return *this; +} + +Vec4& +Vec4::operator/=(float rhs) +{ + *this = *this / rhs; + return *this; +} + +bool +Vec4::operator==(const Vec4 &rhs) const +{ + return (this->x == rhs.x) && + (this->y == rhs.y) && + (this->z == rhs.z) && + (this->w == rhs.w); +} + +bool +Vec4::operator!=(const Vec4 &rhs) const +{ + return (this->x != rhs.x) || + (this->y != rhs.y) || + (this->z != rhs.z) || + (this->w != rhs.w); +} + +float +Vec4::norm(void) const +{ + return sqrt(normsq()); +} + +float +Vec4::normsq(void) const +{ + return x*x + y*y + z*z + w*w; +} + +Vec4 +Vec4::normalized(void) const +{ + return Vec4(*this)/norm(); +} + +float +Vec4::dot(const Vec4 &rhs) const +{ + return this->x*rhs.x + this->y*rhs.y + this->z*rhs.z + this->w*rhs.w; +} + +void +Vec4::print(std::ostream &of) const +{ + of << "V4(" << x << ", " << y << ", " << z << ", " << w << ")"; +} + +/* + * Quat + */ + +std::ostream& +operator<<(std::ostream& of, const Quat &v) +{ + v.print(of); + return of; +} + + +Quat::Quat(void) + : w(0.0f), x(0.0f), y(0.0f), z(0.0f) +{ +} + +Quat::Quat(float w) + : w(w), x(0.0f), y(0.0f), z(0.0f) +{ +} + +Quat::Quat(float x, float y, float z) + : w(0.0f), x(x), y(y), z(z) +{ +} + +Quat::Quat(float w, float x, float y, float z) + : w(w), x(x), y(y), z(z) +{ +} + +float* +Quat::ptr(void) +{ + return &w; +} + +Quat +Quat::operator-(void) const +{ + return Quat(-w, -x, -y, -z); +} + +Quat +Quat::operator+(const Quat &rhs) const +{ + return Quat(this->w+rhs.w, this->x+rhs.x, this->y+rhs.y, this->z+rhs.z); +} + +Quat +Quat::operator-(const Quat &rhs) const +{ + return Quat(this->w-rhs.w, this->x-rhs.x, this->y-rhs.y, this->z-rhs.z); +} + +Quat +Quat::operator*(const Quat &rhs) const +{ + return Quat( + this->w*rhs.w - this->x*rhs.x - this->y*rhs.y - this->z*rhs.z, + this->w*rhs.x + this->x*rhs.w + this->y*rhs.z - this->z*rhs.y, + this->w*rhs.y + this->y*rhs.w + this->z*rhs.x - this->x*rhs.z, + this->w*rhs.z + this->z*rhs.w + this->x*rhs.y - this->y*rhs.x); +} + +Quat +Quat::operator*(float rhs) const +{ + return Quat(this->w*rhs, this->x*rhs, this->y*rhs, this->z*rhs); +} + +Quat +Quat::operator/(float rhs) const +{ + return Quat(this->w/rhs, this->x/rhs, this->y/rhs, this->z/rhs); +} + +Quat& +Quat::operator+=(const Quat &rhs) +{ + *this = *this + rhs; + return *this; +} + +Quat& +Quat::operator-=(const Quat &rhs) +{ + *this = *this - rhs; + return *this; +} + +Quat& +Quat::operator*=(const Quat &rhs) +{ + *this = *this * rhs; + return *this; +} + +Quat& +Quat::operator*=(float rhs) +{ + *this = *this * rhs; + return *this; +} + +Quat& +Quat::operator/=(float rhs) +{ + *this = *this / rhs; + return *this; +} + +bool +Quat::operator==(const Quat &rhs) const +{ + return (this->w == rhs.w) && + (this->x == rhs.x) && + (this->y == rhs.y) && + (this->z == rhs.z); +} + +bool +Quat::operator!=(const Quat &rhs) const +{ + return (this->w != rhs.w) || + (this->x != rhs.x) || + (this->y != rhs.y) || + (this->z != rhs.z); +} + +Quat +Quat::inv(void) const +{ + return K() / N(); +} + +Quat +Quat::K(void) const +{ + return Quat(w, -x, -y, -z); +} + +Quat +Quat::S(void) const +{ + return Quat(w); +} + +Quat +Quat::V(void) const +{ + return Quat(x, y, z); +} + +float +Quat::T(void) const +{ + return sqrt(N()); +} + +float +Quat::N(void) const +{ + return w*w + x*x + y*y + z*z; +} + +Quat +Quat::U(void) const +{ + return Quat(*this)/T(); +} + +Quat +Quat::wedge(const Quat &rhs) const +{ + return Quat(0.0f, + this->y*rhs.z - this->z*rhs.y, + this->z*rhs.x - this->x*rhs.z, + this->x*rhs.y - this->y*rhs.x); +} + +float +Quat::inner(const Quat &rhs) const +{ + return this->w*rhs.w + this->x*rhs.x + this->y*rhs.y + this->z*rhs.z; +} + +Quat +Quat::lerp(const Quat &q2, float t) const +{ + Quat q1 = *this; + float cos = q1.inner(q2); + if(cos < 0) + q1 = -q1; + return (q1*(1.0f - t) + q2*t).U(); +} + +Quat +Quat::slerp(const Quat &q2, float t) const +{ + Quat q1 = *this; + float cos = q1.inner(q2); + if(cos < 0){ + cos = -cos; + q1 = -q1; + } + float phi = acos(cos); + if(phi > 0.00001){ + float s = sin(phi); + q1 = q1*sin((1.0f-t)*phi)/s + q2*sin(t*phi)/s; + } + return q1; +} + +void +Quat::print(std::ostream &of) const +{ + of << "Q(" << w << ", " << x << ", " << y << ", " << z << ")"; +} + +/* + * Quat + */ + +std::ostream& +operator<<(std::ostream& of, const DQuat &v) +{ + v.print(of); + return of; +} + + +DQuat::DQuat(void) + : q1(), q2() +{ +} + +DQuat::DQuat(const Quat &q1, const Quat &q2) + : q1(q1), q2(q2) +{ +} + +DQuat +DQuat::operator-(void) const +{ + return DQuat(-q1, -q2); +} + +DQuat +DQuat::operator+(const DQuat &rhs) const +{ + return DQuat(this->q1+rhs.q1, this->q2+rhs.q2); +} + +DQuat +DQuat::operator-(const DQuat &rhs) const +{ + return DQuat(this->q1-rhs.q1, this->q2-rhs.q2); +} + +DQuat +DQuat::operator*(const DQuat &rhs) const +{ + return DQuat(this->q1*rhs.q1, this->q1*rhs.q2 + this->q2*rhs.q1); +} + +DQuat +DQuat::operator*(float rhs) const +{ + return DQuat(this->q1*rhs, this->q2*rhs); +} + +DQuat +DQuat::operator/(float rhs) const +{ + return DQuat(this->q1/rhs, this->q2/rhs); +} + +DQuat& +DQuat::operator+=(const DQuat &rhs) +{ + *this = *this + rhs; + return *this; +} + +DQuat& +DQuat::operator-=(const DQuat &rhs) +{ + *this = *this - rhs; + return *this; +} + +DQuat& +DQuat::operator*=(const DQuat &rhs) +{ + *this = *this * rhs; + return *this; +} + +DQuat& +DQuat::operator*=(float rhs) +{ + *this = *this * rhs; + return *this; +} + +DQuat& +DQuat::operator/=(float rhs) +{ + *this = *this / rhs; + return *this; +} + +bool +DQuat::operator==(const DQuat &rhs) const +{ + return (this->q1 == rhs.q1) && + (this->q2 == rhs.q2); +} + +bool +DQuat::operator!=(const DQuat &rhs) const +{ + return (this->q1 != rhs.q1) || + (this->q2 != rhs.q2); +} + +DQuat +DQuat::K(void) const +{ + return DQuat(q1.K(), -q2.K()); +} + +void +DQuat::print(std::ostream &of) const +{ + of << "DQ(" << q1 << ", " << q2 << ")"; +} + +/* + * Mat3 + */ + +std::ostream& +operator<<(std::ostream& of, const Mat3 &v) +{ + v.print(of); + return of; +} + +Mat3::Mat3(void) +{ + for(int i = 0; i < 3*3; i++) + cr[i] = 0.0f; +} + +Mat3::Mat3(float f) +{ + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) + e[i][j] = (i == j) ? f : 0.0f; +} + +Mat3::Mat3(float *f) +{ + for(int i = 0; i < 3*3; i++) + cr[i] = f[i]; +} + +Mat3::Mat3(float e00, float e10, float e20, + float e01, float e11, float e21, + float e02, float e12, float e22) +{ + e[0][0] = e00; e[1][0] = e10; e[2][0] = e20; + e[0][1] = e01; e[1][1] = e11; e[2][1] = e21; + e[0][2] = e02; e[1][2] = e12; e[2][2] = e22; +} + +float* +Mat3::ptr(void) +{ + return &e[0][0]; +} + +Mat3 +Mat3::rotation(float theta, const Vec3 &v) +{ + Mat3 m(1.0f); + float c = cos(theta); + float s = sin(theta); + m.e[0][0] = v.x*v.x*(1-c) + c; + m.e[1][0] = v.x*v.y*(1-c) - v.z*s; + m.e[2][0] = v.x*v.z*(1-c) + v.y*s; + + m.e[0][1] = v.y*v.x*(1-c) + v.z*s; + m.e[1][1] = v.y*v.y*(1-c) + c; + m.e[2][1] = v.y*v.z*(1-c) - v.x*s; + + m.e[0][2] = v.z*v.x*(1-c) - v.y*s; + m.e[1][2] = v.z*v.y*(1-c) + v.x*s; + m.e[2][2] = v.z*v.z*(1-c) + c; + return m; +} + +Mat3 +Mat3::scale(const Vec3 &v) +{ + Mat3 m(1.0f); + m.e[0][0] = v.x; + m.e[1][1] = v.y; + m.e[2][2] = v.z; + return m; +} + +Mat3 +Mat3::transpose(void) const +{ + float e[3][3]; + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++){ + e[j][i] = this->e[i][j]; + e[i][j] = this->e[j][i]; + } + return Mat3(&e[0][0]); +} + +Mat3 +Mat3::operator+(const Mat3 &rhs) const +{ + float e[9]; + for(int i = 0; i < 3*3; i++) + e[i] = this->cr[i] + rhs.cr[i]; + return Mat3(e); +} + +Mat3 +Mat3::operator-(const Mat3 &rhs) const +{ + float e[9]; + for(int i = 0; i < 3*3; i++) + e[i] = this->cr[i] - rhs.cr[i]; + return Mat3(e); +} + +Mat3 +Mat3::operator*(float rhs) const +{ + float e[9]; + for(int i = 0; i < 3*3; i++) + e[i] = this->cr[i]*rhs; + return Mat3(e); +} + +Mat3 +Mat3::operator/(float rhs) const +{ + float e[9]; + for(int i = 0; i < 3*3; i++) + e[i] = this->cr[i]/rhs; + return Mat3(e); +} + +Mat3 +Mat3::operator*(const Mat3 &rhs) const +{ + float e[3][3]; + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) + e[i][j] = this->e[0][j]*rhs.e[i][0] + + this->e[1][j]*rhs.e[i][1] + + this->e[2][j]*rhs.e[i][2]; + return Mat3(&e[0][0]); +} + +Vec3 +Mat3::operator*(const Vec3 &rhs) const +{ + float e[3]; + for(int i = 0; i < 3; i++) + e[i] = this->e[0][i]*rhs.x + + this->e[1][i]*rhs.y + + this->e[2][i]*rhs.z; + return Vec3(e); +} + +Mat3& +Mat3::operator+=(const Mat3 &rhs) +{ + *this = *this + rhs; + return *this; +} + +Mat3& +Mat3::operator-=(const Mat3 &rhs) +{ + *this = *this - rhs; + return *this; +} + +Mat3& +Mat3::operator*=(float rhs) +{ + *this = *this * rhs; + return *this; +} + +Mat3& +Mat3::operator/=(float rhs) +{ + *this = *this / rhs; + return *this; +} + +Mat3& +Mat3::operator*=(const Mat3 &rhs) +{ + *this = *this * rhs; + return *this; +} + +void +Mat3::print(std::ostream &of) const +{ + #define CM << ", " << + of << "M3(" << e[0][0] CM e[1][0] CM e[2][0] << std::endl; + of << " " << e[0][1] CM e[1][1] CM e[2][1] << std::endl; + of << " " << e[0][2] CM e[1][2] CM e[2][2] << ")"; + #undef CM +} + +/* + * Mat3 + */ + +std::ostream& +operator<<(std::ostream& of, const Mat4 &v) +{ + v.print(of); + return of; +} + +Mat4::Mat4(void) +{ + for(int i = 0; i < 4*4; i++) + cr[i] = 0.0f; +} + +Mat4::Mat4(float f) +{ + for(int i = 0; i < 4; i++) + for(int j = 0; j < 4; j++) + e[i][j] = (i == j) ? f : 0.0f; +} + +Mat4::Mat4(float *f) +{ + for(int i = 0; i < 4*4; i++) + cr[i] = f[i]; +} + +Mat4::Mat4(float e00, float e10, float e20, float e30, + float e01, float e11, float e21, float e31, + float e02, float e12, float e22, float e32, + float e03, float e13, float e23, float e33) +{ + e[0][0] = e00; e[1][0] = e10; e[2][0] = e20; e[3][0] = e30; + e[0][1] = e01; e[1][1] = e11; e[2][1] = e21; e[3][1] = e31; + e[0][2] = e02; e[1][2] = e12; e[2][2] = e22; e[3][2] = e32; + e[0][3] = e03; e[1][3] = e13; e[2][3] = e23; e[3][3] = e33; +} + +float* +Mat4::ptr(void) +{ + return &e[0][0]; +} + +Mat4 +Mat4::perspective(float fov, float aspect, float n, float f) +{ + float r = n*tan(fov*3.14159f/360.0f); + float t = r/aspect; + return frustum(-r, r, -t, t, n, f); +} + +Mat4 +Mat4::frustum(float l, float r, float b, float t, + float n, float f) +{ + Mat4 m(1.0f); + m.e[0][0] = (2.0f*n)/(r-l); + m.e[1][1] = (2.0f*n)/(t-b); + m.e[2][0] = (r+l)/(r-l); + m.e[2][1] = (t+b)/(t-b); + m.e[2][2] = -(f+n)/(f-n); + m.e[2][3] = -1.0f; + m.e[3][2] = -2.0f*f*n/(f-n); + m.e[3][3] = 0.0f; + return m; +} + +Mat4 +Mat4::ortho(float l, float r, float b, float t, + float n, float f) +{ + Mat4 m(1.0f); + m.e[0][0] = 2.0f/(r-l); + m.e[3][0] = -(r+l)/(r-l); + m.e[1][1] = 2.0f/(t-b); + m.e[3][1] = -(t+b)/(t-b); + m.e[2][2] = -2.0f/(f-n); + m.e[3][2] = -(f+n)/(f-n); + return m; +} + +Mat4 +Mat4::lookat(const Vec3 &pos, const Vec3 &target, const Vec3 &up) +{ + Vec3 forward = (target - pos).normalized(); + Vec3 side = forward.cross(up).normalized(); + Vec3 nup = side.cross(forward); + Mat4 m(1.0f); + m.e[0][0] = side.x; + m.e[1][0] = side.y; + m.e[2][0] = side.z; + m.e[0][1] = nup.x; + m.e[1][1] = nup.y; + m.e[2][1] = nup.z; + m.e[0][2] = -forward.x; + m.e[1][2] = -forward.y; + m.e[2][2] = -forward.z; + return m*Mat4::translation(-pos); +} + +Mat4 +Mat4::translation(const Vec3 &v) +{ + Mat4 m(1.0f); + m.e[3][0] = v.x; + m.e[3][1] = v.y; + m.e[3][2] = v.z; + return m; +} + +Mat4 +Mat4::rotation(float theta, const Vec3 &v) +{ + Mat4 m(1.0f); + float c = cos(theta); + float s = sin(theta); + m.e[0][0] = v.x*v.x*(1-c) + c; + m.e[1][0] = v.x*v.y*(1-c) - v.z*s; + m.e[2][0] = v.x*v.z*(1-c) + v.y*s; + + m.e[0][1] = v.y*v.x*(1-c) + v.z*s; + m.e[1][1] = v.y*v.y*(1-c) + c; + m.e[2][1] = v.y*v.z*(1-c) - v.x*s; + + m.e[0][2] = v.z*v.x*(1-c) - v.y*s; + m.e[1][2] = v.z*v.y*(1-c) + v.x*s; + m.e[2][2] = v.z*v.z*(1-c) + c; + return m; +} + +Mat4 +Mat4::scale(const Vec3 &v) +{ + Mat4 m(1.0f); + m.e[0][0] = v.x; + m.e[1][1] = v.y; + m.e[2][2] = v.z; + return m; +} + +Mat4 +Mat4::transpose(void) const +{ + float e[4][4]; + for(int i = 0; i < 4; i++) + for(int j = 0; j < 4; j++){ + e[j][i] = this->e[i][j]; + e[i][j] = this->e[j][i]; + } + return Mat4(&e[0][0]); +} + +Mat4 +Mat4::operator+(const Mat4 &rhs) const +{ + float e[16]; + for(int i = 0; i < 4*4; i++) + e[i] = this->cr[i] + rhs.cr[i]; + return Mat4(e); +} + +Mat4 +Mat4::operator-(const Mat4 &rhs) const +{ + float e[16]; + for(int i = 0; i < 4*4; i++) + e[i] = this->cr[i] - rhs.cr[i]; + return Mat4(e); +} + +Mat4 +Mat4::operator*(float rhs) const +{ + float e[16]; + for(int i = 0; i < 4*4; i++) + e[i] = this->cr[i]*rhs; + return Mat4(e); +} + +Mat4 +Mat4::operator/(float rhs) const +{ + float e[16]; + for(int i = 0; i < 4*4; i++) + e[i] = this->cr[i]/rhs; + return Mat4(e); +} + +Mat4 +Mat4::operator*(const Mat4 &rhs) const +{ + float e[4][4]; + for(int i = 0; i < 4; i++) + for(int j = 0; j < 4; j++) + e[i][j] = this->e[0][j]*rhs.e[i][0] + + this->e[1][j]*rhs.e[i][1] + + this->e[2][j]*rhs.e[i][2] + + this->e[3][j]*rhs.e[i][3]; + return Mat4(&e[0][0]); +} + +Vec4 +Mat4::operator*(const Vec4 &rhs) const +{ + float e[4]; + for(int i = 0; i < 4; i++) + e[i] = this->e[0][i]*rhs.x + + this->e[1][i]*rhs.y + + this->e[2][i]*rhs.z + + this->e[3][i]*rhs.w; + return Vec4(e); +} + +Mat4& +Mat4::operator+=(const Mat4 &rhs) +{ + *this = *this + rhs; + return *this; +} + +Mat4& +Mat4::operator-=(const Mat4 &rhs) +{ + *this = *this - rhs; + return *this; +} + +Mat4& +Mat4::operator*=(float rhs) +{ + *this = *this * rhs; + return *this; +} + +Mat4& +Mat4::operator/=(float rhs) +{ + *this = *this / rhs; + return *this; +} + +Mat4& +Mat4::operator*=(const Mat4 &rhs) +{ + *this = *this * rhs; + return *this; +} + +void +Mat4::print(std::ostream &of) const +{ + #define CM << ", " << + of << "M4(" << e[0][0] CM e[1][0] CM e[2][0] CM e[3][0] << std::endl; + of << " " << e[0][1] CM e[1][1] CM e[2][1] CM e[3][1] << std::endl; + of << " " << e[0][2] CM e[1][2] CM e[2][2] CM e[3][2] << std::endl; + of << " " << e[0][3] CM e[1][3] CM e[2][3] CM e[3][3] << ")"; + #undef CM +} + + + + + +Vec3::Vec3(const Vec4 &v) + : x(v.x), y(v.y), z(v.z) +{ +} + +Vec3::Vec3(const Quat &q) + : x(q.x), y(q.y), z(q.z) +{ +} + +Vec4::Vec4(const Vec3 &v, float w) + : x(v.x), y(v.y), z(v.z), w(w) +{ +} + +Vec4::Vec4(const Quat &q) + : x(q.x), y(q.y), z(q.z), w(q.w) +{ +} + +Quat::Quat(const Vec3 &v) + : w(0), x(v.x), y(v.y), z(v.z) +{ +} + +Quat::Quat(float w, const Vec3 &v) + : w(w), x(v.x), y(v.y), z(v.z) +{ +} + +Quat::Quat(const Vec4 &v) + : w(v.w), x(v.x), y(v.y), z(v.z) +{ +} + +Quat::Quat(const Mat3 &m) +{ + float trace, s, q[4]; + int i, j, k; + + int nxt[3] = {1, 2, 0}; + + trace = m.e[0][0] + m.e[1][1] + m.e[2][2]; + if(trace > 0.0f){ + s = sqrt(trace + 1.0f); + this->w = s / 2.0f; + s = 0.5f / s; + this->x = (m.e[2][1] - m.e[1][2]) * s; + this->y = (m.e[0][2] - m.e[2][0]) * s; + this->z = (m.e[1][0] - m.e[0][1]) * s; + }else{ + i = 0; + if(m.e[1][1] > m.e[0][0]) i = 1; + if(m.e[2][2] > m.e[i][i]) i = 2; + j = nxt[i]; + k = nxt[j]; + s = sqrt((m.e[i][i] - m.e[j][j] - m.e[k][k]) + 1.0); + q[i] = s*0.5f; + if(q[i] != 0.0f) s = 0.5f / s; + q[3] = (m.e[k][j] - m.e[j][k]) * s; + q[j] = (m.e[j][i] + m.e[i][j]) * s; + q[k] = (m.e[k][i] + m.e[i][k]) * s; + this->w = q[3]; + this->x = q[0]; + this->y = q[1]; + this->z = q[2]; + } +} + +Mat3::Mat3(const Mat4 &m) +{ + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) + this->e[i][j] = m.e[i][j]; +} + +Mat4::Mat4(const Mat3 &m) +{ + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) + this->e[i][j] = m.e[i][j]; + this->e[0][3] = 0.0f; + this->e[1][3] = 0.0f; + this->e[2][3] = 0.0f; + this->e[3][3] = 1.0f; + this->e[3][2] = 0.0f; + this->e[3][1] = 0.0f; + this->e[3][0] = 0.0f; +} + +Mat3 +Mat3::rotation(const Quat &v) +{ + Mat3 m(1.0f); + m.e[0][0] = v.w*v.w + v.x*v.x - v.y*v.y - v.z*v.z; + m.e[1][0] = 2*v.x*v.y - 2*v.w*v.z; + m.e[2][0] = 2*v.w*v.y + 2*v.x*v.z; + m.e[0][1] = 2*v.w*v.z + 2*v.x*v.y; + m.e[1][1] = v.w*v.w - v.x*v.x + v.y*v.y - v.z*v.z; + m.e[2][1] = 2*v.y*v.z - 2*v.w*v.x; + m.e[0][2] = 2*v.x*v.z - 2*v.w*v.y; + m.e[1][2] = 2*v.w*v.x + 2*v.y*v.z; + m.e[2][2] = v.w*v.w - v.x*v.x - v.y*v.y + v.z*v.z; + return m; +} + +Mat4 +Mat4::rotation(const Quat &q) +{ + Mat4 m(1.0f); + m.e[0][0] = q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z; + m.e[1][0] = 2*q.x*q.y - 2*q.w*q.z; + m.e[2][0] = 2*q.w*q.y + 2*q.x*q.z; + m.e[0][1] = 2*q.w*q.z + 2*q.x*q.y; + m.e[1][1] = q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z; + m.e[2][1] = 2*q.y*q.z - 2*q.w*q.x; + m.e[0][2] = 2*q.x*q.z - 2*q.w*q.y; + m.e[1][2] = 2*q.w*q.x + 2*q.y*q.z; + m.e[2][2] = q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z; + return m; +} + +Mat4 +Mat4::transrot(const DQuat &q) +{ + const Quat &q1 = q.q1; + const Quat &q2 = q.q2; + Mat4 m(1.0f); + m.e[0][0] = q1.w*q1.w + q1.x*q1.x - q1.y*q1.y - q1.z*q1.z; + m.e[1][0] = 2*q1.x*q1.y - 2*q1.w*q1.z; + m.e[2][0] = 2*q1.w*q1.y + 2*q1.x*q1.z; + m.e[0][1] = 2*q1.w*q1.z + 2*q1.x*q1.y; + m.e[1][1] = q1.w*q1.w - q1.x*q1.x + q1.y*q1.y - q1.z*q1.z; + m.e[2][1] = 2*q1.y*q1.z - 2*q1.w*q1.x; + m.e[0][2] = 2*q1.x*q1.z - 2*q1.w*q1.y; + m.e[1][2] = 2*q1.w*q1.x + 2*q1.y*q1.z; + m.e[2][2] = q1.w*q1.w - q1.x*q1.x - q1.y*q1.y + q1.z*q1.z; + m.e[3][0] = 2*(q1.w*q2.x - q2.w*q1.x + q1.y*q2.z - q1.z*q2.y); + m.e[3][1] = 2*(q1.w*q2.y - q2.w*q1.y + q1.z*q2.x - q1.x*q2.z); + m.e[3][2] = 2*(q1.w*q2.z - q2.w*q1.z + q1.x*q2.y - q1.y*q2.x); + return m; +} + diff --git a/tests/gl/math/conversion.h b/tests/gl/math/conversion.h new file mode 100755 index 0000000..01e7897 --- /dev/null +++ b/tests/gl/math/conversion.h @@ -0,0 +1,93 @@ +#ifndef MATH_CONVERSION_H +#define MATH_CONVERSION_H + +Vec3::Vec3(const Vec4 &v) + : x(v.x), y(v.y), z(v.z) +{ +} + +Vec3::Vec3(const Quat &q) + : x(q.x), y(q.y), z(q.z) +{ +} + +Vec4::Vec4(const Vec3 &v, float w) + : x(v.x), y(v.y), z(v.z), w(w) +{ +} + +Vec4::Vec4(const Quat &q) + : x(q.x), y(q.y), z(q.z), w(q.w) +{ +} + +Quat::Quat(const Vec3 &v) + : x(v.x), y(v.y), z(v.z) +{ +} + +Quat::Quat(float w, const Vec3 &v) + : w(w), x(v.x), y(v.y), z(v.z) +{ +} + +Quat::Quat(const Vec4 &v) + : w(v.w), x(v.x), y(v.y), z(v.z) +{ +} + +Mat3::Mat3(const Mat4 &m) +{ + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) + this->e[i][j] = m.e[i][j]; +} + +Mat4::Mat4(const Mat3 &m) +{ + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) + this->e[i][j] = m.e[i][j]; + this->e[0][3] = 0.0f; + this->e[1][3] = 0.0f; + this->e[2][3] = 0.0f; + this->e[3][3] = 1.0f; + this->e[3][2] = 0.0f; + this->e[3][1] = 0.0f; + this->e[3][0] = 0.0f; +} + +Mat4 +Mat4::rotation(const Quat &v) +{ + Mat4 m(1.0f); + m.e[0][0] = v.w*v.w + v.x*v.x - v.y*v.y - v.z*v.z; + m.e[1][0] = 2*v.x*v.y - 2*v.w*v.z; + m.e[2][0] = 2*v.w*v.y + 2*v.x*v.z; + m.e[0][1] = 2*v.w*v.z + 2*v.x*v.y; + m.e[1][1] = v.w*v.w - v.x*v.x + v.y*v.y - v.z*v.z; + m.e[2][1] = 2*v.y*v.z - 2*v.w*v.x; + m.e[0][2] = 2*v.x*v.z - 2*v.w*v.y; + m.e[1][2] = 2*v.w*v.x + 2*v.y*v.z; + m.e[2][2] = v.w*v.w - v.x*v.x - v.y*v.y + v.z*v.z; + return m; +} + +Mat3 +Mat3::rotation(const Quat &v) +{ + Mat3 m(1.0f); + m.e[0][0] = v.w*v.w + v.x*v.x - v.y*v.y - v.z*v.z; + m.e[1][0] = 2*v.x*v.y - 2*v.w*v.z; + m.e[2][0] = 2*v.w*v.y + 2*v.x*v.z; + m.e[0][1] = 2*v.w*v.z + 2*v.x*v.y; + m.e[1][1] = v.w*v.w - v.x*v.x + v.y*v.y - v.z*v.z; + m.e[2][1] = 2*v.y*v.z - 2*v.w*v.x; + m.e[0][2] = 2*v.x*v.z - 2*v.w*v.y; + m.e[1][2] = 2*v.w*v.x + 2*v.y*v.z; + m.e[2][2] = v.w*v.w - v.x*v.x - v.y*v.y + v.z*v.z; + return m; +} + +#endif + diff --git a/tests/gl/math/dquat.h b/tests/gl/math/dquat.h new file mode 100755 index 0000000..2690cea --- /dev/null +++ b/tests/gl/math/dquat.h @@ -0,0 +1,45 @@ +#ifndef MATH_DQUAT_H +#define MATH_DQUAT_H + +#include +#include + +class Vec3; +class Vec4; + +class DQuat { +public: + Quat q1, q2; + + DQuat(void); + DQuat(const Quat &q1, const Quat &q2); + DQuat operator-(void) const; + DQuat operator+(const DQuat &rhs) const; + DQuat operator-(const DQuat &rhs) const; + DQuat operator*(const DQuat &rhs) const; + DQuat operator*(float rhs) const; + DQuat operator/(float rhs) const; + DQuat &operator+=(const DQuat &rhs); + DQuat &operator-=(const DQuat &rhs); + DQuat &operator*=(const DQuat &rhs); + DQuat &operator*=(float rhs); + DQuat &operator/=(float rhs); + bool operator==(const DQuat &rhs) const; + bool operator!=(const DQuat &rhs) const; + +// DQuat inv(void) const; + DQuat K(void) const; /* conjugate */ +// DQuat S(void) const; /* scalar */ +// DQuat V(void) const; /* vector */ +// float T(void) const; /* tensor */ +// float N(void) const; /* norm = tensor^2 */ +// DQuat U(void) const; /* versor */ +// DQuat wedge(const Quat &rhs) const; +// float inner(const Quat &rhs) const; +// DQuat slerp(const Quat &rhs, float t) const; + + void print(std::ostream &of) const; +}; + +#endif + diff --git a/tests/gl/math/mat3.h b/tests/gl/math/mat3.h new file mode 100755 index 0000000..e1c6034 --- /dev/null +++ b/tests/gl/math/mat3.h @@ -0,0 +1,43 @@ +#ifndef MATH_MATRIX3_H +#define MATH_MATRIX3_H + +#include +#include + +class Mat4; + +class Mat3 { +public: + union { + float e[3][3]; + float cr[9]; + }; + + Mat3(void); + Mat3(float f); + Mat3(float *f); + Mat3(float e00, float e10, float e20, + float e01, float e11, float e21, + float e02, float e12, float e22); + Mat3(const Mat4 &m); + float *ptr(void); + static Mat3 rotation(float theta, const Vec3 &v); + static Mat3 rotation(const Quat &v); + static Mat3 scale(const Vec3 &v); + Mat3 transpose(void) const; + Mat3 operator+(const Mat3 &rhs) const; + Mat3 operator-(const Mat3 &rhs) const; + Mat3 operator*(float rhs) const; + Mat3 operator/(float rhs) const; + Mat3 operator*(const Mat3 &rhs) const; + Vec3 operator*(const Vec3 &rhs) const; + Mat3 &operator+=(const Mat3 &rhs); + Mat3 &operator-=(const Mat3 &rhs); + Mat3 &operator*=(float rhs); + Mat3 &operator/=(float rhs); + Mat3 &operator*=(const Mat3 &rhs); + void print(std::ostream &of) const; +}; + +#endif + diff --git a/tests/gl/math/mat4.h b/tests/gl/math/mat4.h new file mode 100755 index 0000000..1bac359 --- /dev/null +++ b/tests/gl/math/mat4.h @@ -0,0 +1,52 @@ +#ifndef MATH_MATRIX4_H +#define MATH_MATRIX4_H + +#include +#include + +class Mat3; + +class Mat4 { +public: + union { + float e[4][4]; + float cr[16]; + }; + + Mat4(void); + Mat4(float f); + Mat4(float *f); + Mat4(float e00, float e10, float e20, float e30, + float e01, float e11, float e21, float e31, + float e02, float e12, float e22, float e32, + float e03, float e13, float e23, float e33); + Mat4(const Mat3 &m); + float *ptr(void); + static Mat4 perspective(float fov, float aspect, float n, float f); + static Mat4 frustum(float l, float r, float b, float t, + float n, float f); + static Mat4 ortho(float l, float r, float b, float t, + float n, float f); + static Mat4 lookat(const Vec3 &pos, const Vec3 &target, const Vec3 &up); + static Mat4 translation(const Vec3 &v); + static Mat4 rotation(float theta, const Vec3 &v); + static Mat4 rotation(const Quat &q); + static Mat4 transrot(const DQuat &q); + static Mat4 scale(const Vec3 &v); + Mat4 transpose(void) const; + Mat4 operator+(const Mat4 &rhs) const; + Mat4 operator-(const Mat4 &rhs) const; + Mat4 operator*(float rhs) const; + Mat4 operator/(float rhs) const; + Mat4 operator*(const Mat4 &rhs) const; + Vec4 operator*(const Vec4 &rhs) const; + Mat4 &operator+=(const Mat4 &rhs); + Mat4 &operator-=(const Mat4 &rhs); + Mat4 &operator*=(float rhs); + Mat4 &operator/=(float rhs); + Mat4 &operator*=(const Mat4 &rhs); + void print(std::ostream &of) const; +}; + +#endif + diff --git a/tests/gl/math/math.h b/tests/gl/math/math.h new file mode 100755 index 0000000..0c04fa3 --- /dev/null +++ b/tests/gl/math/math.h @@ -0,0 +1,21 @@ +#ifndef MATH_H +#define MATH_H + +#include "vec3.h" +#include "vec4.h" +#include "quat.h" +#include "dquat.h" +#include "mat3.h" +#include "mat4.h" + +std::ostream &operator<<(std::ostream& of, const Vec3 &v); +std::ostream &operator<<(std::ostream& of, const Vec4 &v); +std::ostream &operator<<(std::ostream& of, const Quat &v); +std::ostream &operator<<(std::ostream& of, const DQuat &v); +std::ostream &operator<<(std::ostream& of, const Mat3 &v); +std::ostream &operator<<(std::ostream& of, const Mat4 &v); + +#define PI 3.14159265359f + + +#endif diff --git a/tests/gl/math/quat.h b/tests/gl/math/quat.h new file mode 100755 index 0000000..7da753a --- /dev/null +++ b/tests/gl/math/quat.h @@ -0,0 +1,54 @@ +#ifndef MATH_QUAT_H +#define MATH_QUAT_H + +#include +#include + +class Vec3; +class Vec4; +class Mat3; + +/* Hamilton style */ + +class Quat { +public: + float w, x, y, z; + + Quat(void); + Quat(float w); + Quat(float x, float y, float z); + Quat(float w, float x, float y, float z); + Quat(float w, const Vec3 &v); + Quat(const Vec3 &v); + Quat(const Vec4 &v); + Quat(const Mat3 &m); + float *ptr(void); + Quat operator-(void) const; + Quat operator+(const Quat &rhs) const; + Quat operator-(const Quat &rhs) const; + Quat operator*(const Quat &rhs) const; + Quat operator*(float rhs) const; + Quat operator/(float rhs) const; + Quat &operator+=(const Quat &rhs); + Quat &operator-=(const Quat &rhs); + Quat &operator*=(const Quat &rhs); + Quat &operator*=(float rhs); + Quat &operator/=(float rhs); + bool operator==(const Quat &rhs) const; + bool operator!=(const Quat &rhs) const; + Quat inv(void) const; + Quat K(void) const; /* conjugate */ + Quat S(void) const; /* scalar */ + Quat V(void) const; /* vector */ + float T(void) const; /* tensor */ + float N(void) const; /* norm = tensor^2 */ + Quat U(void) const; /* versor */ + Quat wedge(const Quat &rhs) const; + float inner(const Quat &rhs) const; + Quat lerp(const Quat &rhs, float t) const; + Quat slerp(const Quat &rhs, float t) const; + void print(std::ostream &of) const; +}; + +#endif + diff --git a/tests/gl/math/vec3.h b/tests/gl/math/vec3.h new file mode 100755 index 0000000..5b21593 --- /dev/null +++ b/tests/gl/math/vec3.h @@ -0,0 +1,40 @@ +#ifndef MATH_VECTOR3_H +#define MATH_VECTOR3_H + +#include +#include + +class Vec4; +class Quat; + +class Vec3 { +public: + float x, y, z; + + Vec3(void); + Vec3(float x, float y, float z); + Vec3(float *v); + Vec3(const Vec4 &v); + Vec3(const Quat &q); + float *ptr(void); + Vec3 operator-(void) const; + Vec3 operator+(const Vec3 &rhs) const; + Vec3 operator-(const Vec3 &rhs) const; + Vec3 operator*(float rhs) const; + Vec3 operator/(float rhs) const; + Vec3 &operator+=(const Vec3 &rhs); + Vec3 &operator-=(const Vec3 &rhs); + Vec3 &operator*=(float rhs); + Vec3 &operator/=(float rhs); + bool operator==(const Vec3 &rhs) const; + bool operator!=(const Vec3 &rhs) const; + float norm(void) const; + float normsq(void) const; + Vec3 normalized(void) const; + float dot(const Vec3 &rhs) const; + Vec3 cross(const Vec3 &rhs) const; + void print(std::ostream &of) const; +}; + +#endif + diff --git a/tests/gl/math/vec4.h b/tests/gl/math/vec4.h new file mode 100755 index 0000000..90920f7 --- /dev/null +++ b/tests/gl/math/vec4.h @@ -0,0 +1,39 @@ +#ifndef MATH_VECTOR4_H +#define MATH_VECTOR4_H + +#include +#include + +class Vec3; +class Quat; + +class Vec4 { +public: + float x, y, z, w; + + Vec4(void); + Vec4(float x, float y, float z, float w); + Vec4(float *v); + Vec4(const Vec3 &v, float w = 0.0f); + Vec4(const Quat &w); + float *ptr(void); + Vec4 operator-(void) const; + Vec4 operator+(const Vec4 &rhs) const; + Vec4 operator-(const Vec4 &rhs) const; + Vec4 operator*(float rhs) const; + Vec4 operator/(float rhs) const; + Vec4 &operator+=(const Vec4 &rhs); + Vec4 &operator-=(const Vec4 &rhs); + Vec4 &operator*=(float rhs); + Vec4 &operator/=(float rhs); + bool operator==(const Vec4 &rhs) const; + bool operator!=(const Vec4 &rhs) const; + float norm(void) const; + float normsq(void) const; + Vec4 normalized(void) const; + float dot(const Vec4 &rhs) const; + void print(std::ostream &of) const; +}; + +#endif + diff --git a/tests/gl/rwtest.h b/tests/gl/rwtest.h new file mode 100755 index 0000000..50eb005 --- /dev/null +++ b/tests/gl/rwtest.h @@ -0,0 +1,15 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "../librw/rw.h" +#include "../librw/src/gtaplg.h" +#include "math/math.h" +#include "camera.h" + +#include "gl.h" +