Completed A6

This commit is contained in:
Alex 2017-04-29 23:01:21 -05:00
parent c92bb00601
commit 9768278cf1
29 changed files with 3821 additions and 55 deletions

View file

@ -1 +1,9 @@
Alexander Huddleston
This mesh was initially created using Cosmic Blobs software developed by Dassault Systemes SolidWorks Corp.
Stage 2
None.
Persona 5 is a really good game tbh.

View file

@ -1,8 +0,0 @@
#version 120
varying vec3 vColor;
void main()
{
gl_FragColor = vec4(vColor, 1.0);
}

View file

@ -1,11 +0,0 @@
#version 120
uniform mat4 P;
uniform mat4 MV;
varying vec3 vColor;
void main()
{
gl_Position = P * (MV * gl_Vertex);
vColor = gl_Color.rgb;
}

View file

@ -1,8 +0,0 @@
#version 120
varying vec3 vColor;
void main()
{
gl_FragColor = vec4(vColor, 1.0);
}

View file

@ -1,15 +0,0 @@
#version 120
attribute vec4 aPos;
attribute vec3 aNor;
uniform mat4 P;
uniform mat4 MV;
varying vec3 vColor;
void main()
{
gl_Position = P * (MV * aPos);
vColor = 0.5*aNor + 0.5;
}

BIN
A6/shadow8t4.zip Normal file

Binary file not shown.

View file

@ -0,0 +1,127 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# Name of the project
PROJECT(A6)
# FOR LAB MACHINES ONLY!
# DO NOT EDIT
SET(DEF_DIR_GLM "C:\\c++\\glm")
SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1")
SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0")
# Is this the solution?
# Override with `cmake -DSOL=ON ..`
OPTION(SOL "Solution" OFF)
# Use glob to get the list of all source files.
# We don't really need to include header and resource files to build, but it's
# nice to have them also show up in IDEs.
IF(${SOL})
FILE(GLOB_RECURSE SOURCES "src0/*.cpp")
FILE(GLOB_RECURSE HEADERS "src0/*.h")
FILE(GLOB_RECURSE GLSL "resources0/*.glsl")
ELSE()
FILE(GLOB_RECURSE SOURCES "src/*.cpp")
FILE(GLOB_RECURSE HEADERS "src/*.h")
FILE(GLOB_RECURSE GLSL "resources/*.glsl")
ENDIF()
# Set the executable.
ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL})
# Get the GLM environment variable. Since GLM is a header-only library, we
# just need to add it to the include directory.
SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}")
IF(NOT GLM_INCLUDE_DIR)
# The environment variable was not set
SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.")
IF(WIN32)
# On Windows, try the default location
MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}")
IF(IS_DIRECTORY ${DEF_DIR_GLM})
MESSAGE(STATUS "Found!")
SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM})
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ENDIF()
INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR})
# Get the GLFW environment variable. There should be a CMakeLists.txt in the
# specified directory.
SET(GLFW_DIR "$ENV{GLFW_DIR}")
IF(NOT GLFW_DIR)
# The environment variable was not set
SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.")
IF(WIN32)
# On Windows, try the default location
MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}")
IF(IS_DIRECTORY ${DEF_DIR_GLFW})
MESSAGE(STATUS "Found!")
SET(GLFW_DIR ${DEF_DIR_GLFW})
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ENDIF()
OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF)
OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF)
OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF)
IF(CMAKE_BUILD_TYPE MATCHES Release)
ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release)
ELSE()
ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug)
ENDIF()
INCLUDE_DIRECTORIES(${GLFW_DIR}/include)
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES})
# Get the GLEW environment variable.
SET(GLEW_DIR "$ENV{GLEW_DIR}")
IF(NOT GLEW_DIR)
# The environment variable was not set
SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.")
IF(WIN32)
# On Windows, try the default location
MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}")
IF(IS_DIRECTORY ${DEF_DIR_GLEW})
MESSAGE(STATUS "Found!")
SET(GLEW_DIR ${DEF_DIR_GLEW})
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ENDIF()
INCLUDE_DIRECTORIES(${GLEW_DIR}/include)
IF(WIN32)
# With prebuilt binaries
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib)
ELSE()
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a)
ENDIF()
# OS specific options and libraries
IF(WIN32)
# c++11 is enabled by default.
# -Wall produces way too many warnings.
# -pedantic is not supported.
# Disable warning 4996.
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996")
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib)
ELSE()
# Enable all pedantic warnings.
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic")
IF(APPLE)
# Add required frameworks for GLFW.
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo")
ELSE()
#Link the Linux OpenGL library
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL")
ENDIF()
ENDIF()

View file

@ -0,0 +1,9 @@
Alexander Huddleston
This mesh was initially created using Cosmic Blobs software developed by Dassault Systemes SolidWorks Corp.
Stage 2
None.
Persona 5 is a really good game tbh.

View file

@ -0,0 +1,37 @@
#version 120
uniform mat4 MVL;
uniform vec3 lightPos1;
uniform vec3 lightPos2;
uniform vec3 ka;
uniform vec3 kd;
uniform vec3 ks;
uniform float s;
uniform float i1;
uniform float i2;
varying vec3 color; // passed from the vertex shader
varying vec4 p;
varying vec4 n;
void main()
{
vec4 normal = normalize(n);
vec3 norm = vec3(normal.x, normal.y, normal.z);
vec4 npos = normalize(p);
vec3 pos = vec3(npos.x, npos.y, npos.z);
vec3 lightnorm = vec3(MVL[3].x, MVL[3].y, MVL[3].z);
vec3 light = lightnorm - vec3(p.x, p.y, p.z);
vec3 lnorm = normalize(vec3(light.x,light.y,light.z));
float temp = dot(lnorm, norm);
vec3 cd = kd*max(0, temp);
vec3 h = normalize(lnorm - pos);
vec3 cs = ks*pow(max(0, dot(h, norm)), s);
vec4 c = vec4(ka.r + cd.r + cs.r, ka.g + cd.g + cs.g, ka.b + cd.b + cs.b, 1.0);
gl_FragColor = c;
}

View file

@ -0,0 +1,24 @@
#version 120
uniform mat4 P;
uniform mat4 MV;
uniform mat4 MVL;
uniform vec3 lightPos1;
uniform vec3 lightPos2;
uniform float i1;
uniform float i2;
attribute vec4 aPos; // in object space
attribute vec3 aNor; // in object space
varying vec3 color; // Pass to fragment shader
varying vec4 p;
varying vec4 n;
void main()
{
gl_Position = P * MV * aPos;
p = MV * aPos;
n = MV * vec4(aNor, 0.0);
color = vec3(0.5, 0.5, 0.5);
}

View file

@ -0,0 +1,68 @@
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
#include <glm/gtc/matrix_transform.hpp>
#include "Camera.h"
#include "MatrixStack.h"
Camera::Camera() :
aspect(1.0f),
fovy((float)(45.0*M_PI/180.0)),
znear(0.1f),
zfar(1000.0f),
rotations(0.0, 0.0),
translations(0.0f, 0.0f, -5.0f),
rfactor(0.01f),
tfactor(0.001f),
sfactor(0.005f)
{
}
Camera::~Camera()
{
}
void Camera::mouseClicked(float x, float y, bool shift, bool ctrl, bool alt)
{
mousePrev.x = x;
mousePrev.y = y;
if(shift) {
state = Camera::TRANSLATE;
} else if(ctrl) {
state = Camera::SCALE;
} else {
state = Camera::ROTATE;
}
}
void Camera::mouseMoved(float x, float y)
{
glm::vec2 mouseCurr(x, y);
glm::vec2 dv = mouseCurr - mousePrev;
switch(state) {
case Camera::ROTATE:
rotations += rfactor * dv;
break;
case Camera::TRANSLATE:
translations.x -= translations.z * tfactor * dv.x;
translations.y += translations.z * tfactor * dv.y;
break;
case Camera::SCALE:
translations.z *= (1.0f - sfactor * dv.y);
break;
}
mousePrev = mouseCurr;
}
void Camera::applyProjectionMatrix(std::shared_ptr<MatrixStack> P) const
{
// Modify provided MatrixStack
P->multMatrix(glm::perspective(fovy, aspect, znear, zfar));
}
void Camera::applyViewMatrix(std::shared_ptr<MatrixStack> MV) const
{
MV->translate(translations);
MV->rotate(rotations.y, glm::vec3(1.0f, 0.0f, 0.0f));
MV->rotate(rotations.x, glm::vec3(0.0f, 1.0f, 0.0f));
}

View file

@ -0,0 +1,47 @@
#pragma once
#ifndef __Camera__
#define __Camera__
#include <memory>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
class MatrixStack;
class Camera
{
public:
enum {
ROTATE = 0,
TRANSLATE,
SCALE
};
Camera();
virtual ~Camera();
void setInitDistance(float z) { translations.z = -std::abs(z); }
void setAspect(float a) { aspect = a; };
void setRotationFactor(float f) { rfactor = f; };
void setTranslationFactor(float f) { tfactor = f; };
void setScaleFactor(float f) { sfactor = f; };
void mouseClicked(float x, float y, bool shift, bool ctrl, bool alt);
void mouseMoved(float x, float y);
void applyProjectionMatrix(std::shared_ptr<MatrixStack> P) const;
void applyViewMatrix(std::shared_ptr<MatrixStack> MV) const;
private:
float aspect;
float fovy;
float znear;
float zfar;
glm::vec2 rotations;
glm::vec3 translations;
glm::vec2 mousePrev;
int state;
float rfactor;
float tfactor;
float sfactor;
};
#endif

View file

@ -0,0 +1,152 @@
//
// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book
// Created by zwood on 2/21/10.
// Modified by sueda 10/15/15.
//
#include "GLSL.h"
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <cstring>
using namespace std;
namespace GLSL {
const char * errorString(GLenum err)
{
switch(err) {
case GL_NO_ERROR:
return "No error";
case GL_INVALID_ENUM:
return "Invalid enum";
case GL_INVALID_VALUE:
return "Invalid value";
case GL_INVALID_OPERATION:
return "Invalid operation";
case GL_STACK_OVERFLOW:
return "Stack overflow";
case GL_STACK_UNDERFLOW:
return "Stack underflow";
case GL_OUT_OF_MEMORY:
return "Out of memory";
default:
return "No error";
}
}
void checkVersion()
{
int major, minor;
major = minor = 0;
const char *verstr = (const char *)glGetString(GL_VERSION);
if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) {
printf("Invalid GL_VERSION format %d.%d\n", major, minor);
}
if(major < 2) {
printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor);
exit(0);
}
}
void checkError(const char *str)
{
GLenum glErr = glGetError();
if(glErr != GL_NO_ERROR) {
if(str) {
printf("%s: ", str);
}
printf("GL_ERROR = %s.\n", errorString(glErr));
assert(false);
}
}
void printShaderInfoLog(GLuint shader)
{
GLint infologLength = 0;
GLint charsWritten = 0;
GLchar *infoLog = 0;
checkError(GET_FILE_LINE);
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength);
checkError(GET_FILE_LINE);
if(infologLength > 0) {
infoLog = (GLchar *)malloc(infologLength);
if(infoLog == NULL) {
puts("ERROR: Could not allocate InfoLog buffer");
exit(1);
}
glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog);
checkError(GET_FILE_LINE);
printf("Shader InfoLog:\n%s\n\n", infoLog);
free(infoLog);
}
}
void printProgramInfoLog(GLuint program)
{
GLint infologLength = 0;
GLint charsWritten = 0;
GLchar *infoLog = 0;
checkError(GET_FILE_LINE);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength);
checkError(GET_FILE_LINE);
if(infologLength > 0) {
infoLog = (GLchar *)malloc(infologLength);
if(infoLog == NULL) {
puts("ERROR: Could not allocate InfoLog buffer");
exit(1);
}
glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog);
checkError(GET_FILE_LINE);
printf("Program InfoLog:\n%s\n\n", infoLog);
free(infoLog);
}
}
char *textFileRead(const char *fn)
{
FILE *fp;
char *content = NULL;
int count = 0;
if(fn != NULL) {
fp = fopen(fn,"rt");
if(fp != NULL) {
fseek(fp, 0, SEEK_END);
count = (int)ftell(fp);
rewind(fp);
if(count > 0) {
content = (char *)malloc(sizeof(char) * (count+1));
count = (int)fread(content,sizeof(char),count,fp);
content[count] = '\0';
}
fclose(fp);
} else {
printf("error loading %s\n", fn);
}
}
return content;
}
int textFileWrite(const char *fn, const char *s)
{
FILE *fp;
int status = 0;
if(fn != NULL) {
fp = fopen(fn,"w");
if(fp != NULL) {
if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) {
status = 1;
}
fclose(fp);
}
}
return(status);
}
}

View file

@ -0,0 +1,40 @@
//
// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book
// Created by zwood on 2/21/10.
// Modified by sueda 10/15/15.
//
#pragma once
#ifndef __GLSL__
#define __GLSL__
#define GLEW_STATIC
#include <GL/glew.h>
///////////////////////////////////////////////////////////////////////////////
// For printing out the current file and line number //
///////////////////////////////////////////////////////////////////////////////
#include <sstream>
template <typename T>
std::string NumberToString(T x)
{
std::ostringstream ss;
ss << x;
return ss.str();
}
#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str()
///////////////////////////////////////////////////////////////////////////////
namespace GLSL {
void checkVersion();
void checkError(const char *str = 0);
void printProgramInfoLog(GLuint program);
void printShaderInfoLog(GLuint shader);
int textFileWrite(const char *filename, const char *s);
char *textFileRead(const char *filename);
}
#endif

View file

@ -0,0 +1,39 @@
#include "Material.h"
using namespace std;
Material::Material()
{
this->ca = glm::vec3(0.3f,0.3f,0.3f);
this->cd = glm::vec3(0.3f,0.3f,0.3f);
this->cs = glm::vec3(1.0f,1.0f,1.0f);
this->shine = 0.0f;
}
void Material::setMaterial(glm::vec3 a, glm::vec3 d, glm::vec3 s, float sh)
{
this->ca = a;
this->cd = d;
this->cs = s;
this->shine = sh;
}
glm::vec3 Material::getAmbient() const
{
return this->ca;
}
glm::vec3 Material::getDiffuse() const
{
return this->cd;
}
glm::vec3 Material::getSpecular() const
{
return this->cs;
}
float Material::getShiny() const
{
return this->shine;
}

View file

@ -0,0 +1,46 @@
#pragma once
#ifndef _MATERIAL_H_
#define _MATERIAL_H_
#include <cmath>
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "GLSL.h"
#include "Camera.h"
#include "MatrixStack.h"
class Material
{
private:
glm::vec3 ca;
glm::vec3 cd;
glm::vec3 cs;
float shine;
public:
Material();
Material(const Material &m)
{
ca = m.ca;
cd = m.cd;
cs = m.cs;
}
Material(glm::vec3 a, glm::vec3 d, glm::vec3 s, float sh)
{
ca = a;
cd = d;
cs = s;
shine = sh;
}
void setMaterial(glm::vec3 a, glm::vec3 d, glm::vec3 s, float sh);
glm::vec3 getAmbient() const;
glm::vec3 getDiffuse() const;
glm::vec3 getSpecular() const;
float getShiny() const;
};
#endif

View file

@ -0,0 +1,114 @@
#include "MatrixStack.h"
#include <stdio.h>
#include <cassert>
#include <vector>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
using namespace std;
MatrixStack::MatrixStack()
{
mstack = make_shared< stack<glm::mat4> >();
mstack->push(glm::mat4(1.0));
}
MatrixStack::~MatrixStack()
{
}
void MatrixStack::pushMatrix()
{
const glm::mat4 &top = mstack->top();
mstack->push(top);
assert(mstack->size() < 100);
}
void MatrixStack::popMatrix()
{
assert(!mstack->empty());
mstack->pop();
// There should always be one matrix left.
assert(!mstack->empty());
}
void MatrixStack::loadIdentity()
{
glm::mat4 &top = mstack->top();
top = glm::mat4(1.0);
}
void MatrixStack::translate(const glm::vec3 &t)
{
glm::mat4 &top = mstack->top();
top *= glm::translate(t);
}
void MatrixStack::translate(float x, float y, float z)
{
translate(glm::vec3(x, y, z));
}
void MatrixStack::scale(const glm::vec3 &s)
{
glm::mat4 &top = mstack->top();
top *= glm::scale(s);
}
void MatrixStack::scale(float x, float y, float z)
{
scale(glm::vec3(x, y, z));
}
void MatrixStack::scale(float s)
{
scale(glm::vec3(s, s, s));
}
void MatrixStack::rotate(float angle, const glm::vec3 &axis)
{
glm::mat4 &top = mstack->top();
top *= glm::rotate(angle, axis);
}
void MatrixStack::rotate(float angle, float x, float y, float z)
{
rotate(angle, glm::vec3(x, y, z));
}
void MatrixStack::multMatrix(const glm::mat4 &matrix)
{
glm::mat4 &top = mstack->top();
top *= matrix;
}
const glm::mat4 &MatrixStack::topMatrix() const
{
return mstack->top();
}
void MatrixStack::print(const glm::mat4 &mat, const char *name)
{
if(name) {
printf("%s = [\n", name);
}
for(int i = 0; i < 4; ++i) {
for(int j = 0; j < 4; ++j) {
// mat[j] returns the jth column
printf("%- 5.2f ", mat[j][i]);
}
printf("\n");
}
if(name) {
printf("];");
}
printf("\n");
}
void MatrixStack::print(const char *name) const
{
print(mstack->top(), name);
}

View file

@ -0,0 +1,50 @@
#pragma once
#ifndef _MatrixStack_H_
#define _MatrixStack_H_
#include <stack>
#include <memory>
#include <glm/fwd.hpp>
class MatrixStack
{
public:
MatrixStack();
virtual ~MatrixStack();
// glPushMatrix(): Copies the current matrix and adds it to the top of the stack
void pushMatrix();
// glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top
void popMatrix();
// glLoadIdentity(): Sets the top matrix to be the identity
void loadIdentity();
// glMultMatrix(): Right multiplies the top matrix
void multMatrix(const glm::mat4 &matrix);
// glTranslate(): Right multiplies the top matrix by a translation matrix
void translate(const glm::vec3 &trans);
void translate(float x, float y, float z);
// glScale(): Right multiplies the top matrix by a scaling matrix
void scale(const glm::vec3 &scale);
void scale(float x, float y, float z);
// glScale(): Right multiplies the top matrix by a scaling matrix
void scale(float size);
// glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians)
void rotate(float angle, const glm::vec3 &axis);
void rotate(float angle, float x, float y, float z);
// glGet(GL_MODELVIEW_MATRIX): Gets the top matrix
const glm::mat4 &topMatrix() const;
// Prints out the specified matrix
static void print(const glm::mat4 &mat, const char *name = 0);
// Prints out the top matrix
void print(const char *name = 0) const;
private:
std::shared_ptr< std::stack<glm::mat4> > mstack;
};
#endif

View file

@ -0,0 +1,127 @@
#include "Program.h"
#include <iostream>
#include <cassert>
#include "GLSL.h"
using namespace std;
Program::Program() :
name(""),
vShaderName(""),
fShaderName(""),
pid(0),
verbose(true)
{
}
Program::~Program()
{
}
void Program::setShaderNames(const string &v, const string &f)
{
vShaderName = v;
fShaderName = f;
}
bool Program::init()
{
GLint rc;
// Create shader handles
GLuint VS = glCreateShader(GL_VERTEX_SHADER);
GLuint FS = glCreateShader(GL_FRAGMENT_SHADER);
// Read shader sources
const char *vshader = GLSL::textFileRead(vShaderName.c_str());
const char *fshader = GLSL::textFileRead(fShaderName.c_str());
glShaderSource(VS, 1, &vshader, NULL);
glShaderSource(FS, 1, &fshader, NULL);
// Compile vertex shader
glCompileShader(VS);
glGetShaderiv(VS, GL_COMPILE_STATUS, &rc);
if(!rc) {
if(isVerbose()) {
GLSL::printShaderInfoLog(VS);
cout << "Error compiling vertex shader " << vShaderName << endl;
}
return false;
}
// Compile fragment shader
glCompileShader(FS);
glGetShaderiv(FS, GL_COMPILE_STATUS, &rc);
if(!rc) {
if(isVerbose()) {
GLSL::printShaderInfoLog(FS);
cout << "Error compiling fragment shader " << fShaderName << endl;
}
return false;
}
// Create the program and link
pid = glCreateProgram();
glAttachShader(pid, VS);
glAttachShader(pid, FS);
glLinkProgram(pid);
glGetProgramiv(pid, GL_LINK_STATUS, &rc);
if(!rc) {
if(isVerbose()) {
GLSL::printProgramInfoLog(pid);
cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl;
}
return false;
}
GLSL::checkError(GET_FILE_LINE);
return true;
}
void Program::bind()
{
glUseProgram(pid);
}
void Program::unbind()
{
glUseProgram(0);
}
void Program::addAttribute(const string &name)
{
attributes[name] = glGetAttribLocation(pid, name.c_str());
}
void Program::addUniform(const string &name)
{
uniforms[name] = glGetUniformLocation(pid, name.c_str());
}
GLint Program::getAttribute(const string &name) const
{
map<string,GLint>::const_iterator attribute = attributes.find(name.c_str());
if(attribute == attributes.end()) {
if(isVerbose()) {
cout << name << " is not an attribute variable" << endl;
}
return -1;
}
return attribute->second;
}
GLint Program::getUniform(const string &name) const
{
map<string,GLint>::const_iterator uniform = uniforms.find(name.c_str());
if(uniform == uniforms.end()) {
if(isVerbose()) {
cout << name << " is not a uniform variable" << endl;
}
return -1;
}
return uniform->second;
}

View file

@ -0,0 +1,45 @@
#pragma once
#ifndef __Program__
#define __Program__
#include <map>
#include <string>
#define GLEW_STATIC
#include <GL/glew.h>
/**
* An OpenGL Program (vertex and fragment shaders)
*/
class Program
{
public:
Program();
virtual ~Program();
void setVerbose(bool v) { verbose = v; }
bool isVerbose() const { return verbose; }
void setShaderNames(const std::string &v, const std::string &f);
virtual bool init();
virtual void bind();
virtual void unbind();
void addAttribute(const std::string &name);
void addUniform(const std::string &name);
GLint getAttribute(const std::string &name) const;
GLint getUniform(const std::string &name) const;
protected:
std::string name;
std::string vShaderName;
std::string fShaderName;
private:
GLuint pid;
std::map<std::string,GLint> attributes;
std::map<std::string,GLint> uniforms;
bool verbose;
};
#endif

View file

@ -0,0 +1,316 @@
#include <iostream>
#include <fstream>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#define TINYOBJLOADER_IMPLEMENTATION
#include "tiny_obj_loader.h"
#include "ShapeSkin.h"
#include "GLSL.h"
#include "Program.h"
using namespace std;
ShapeSkin::ShapeSkin() :
prog(NULL),
elemBufID(0),
posBufID(0),
norBufID(0),
texBufID(0)
{
}
ShapeSkin::~ShapeSkin()
{
}
void ShapeSkin::loadMesh(const string &meshName)
{
// Load geometry
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
string errStr;
bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str());
if(!rc) {
cerr << errStr << endl;
} else {
posBuf = attrib.vertices;
norBuf = attrib.normals;
texBuf = attrib.texcoords;
assert(posBuf.size() == norBuf.size());
// Loop over shapes
for(size_t s = 0; s < shapes.size(); s++) {
// Loop over faces (polygons)
const tinyobj::mesh_t &mesh = shapes[s].mesh;
size_t index_offset = 0;
for(size_t f = 0; f < mesh.num_face_vertices.size(); f++) {
size_t fv = mesh.num_face_vertices[f];
// Loop over vertices in the face.
for(size_t v = 0; v < fv; v++) {
// access to vertex
tinyobj::index_t idx = mesh.indices[index_offset + v];
elemBuf.push_back(idx.vertex_index);
}
index_offset += fv;
// per-face material (IGNORE)
shapes[s].mesh.material_ids[f];
}
}
posBufInit = posBuf;
}
}
void ShapeSkin::loadAttachment(const std::string &filename)
{
unsigned int nverts, nbones;
ifstream in;
in.open(filename);
if(!in.good()) {
cout << "Cannot read " << filename << endl;
return;
}
string line;
getline(in, line); // comment
getline(in, line); // comment
getline(in, line);
stringstream ss0(line);
ss0 >> nverts;
ss0 >> nbones;
assert((unsigned int)nverts == posBuf.size()/3);
while(1) {
getline(in, line);
if(in.eof()) {
break;
}
// Parse line
stringstream ss(line);
float temp;
std::vector<float> tempVec;
std::vector<unsigned int> tempIndexes;
for(unsigned int i = 0; i < nbones; i++)
{
ss >> temp;
tempVec.push_back(temp);
if(temp > 0.0f)
{
tempIndexes.push_back((unsigned int) i);
}
}
indexes.push_back(tempIndexes);
boneInfluence.push_back(tempVec);
}
in.close();
}
void ShapeSkin::loadSkeleton(const std::string &filename)
{
unsigned int nframes, nbones;
ifstream in;
in.open(filename);
if(!in.good()) {
cout << "Cannot read " << filename << endl;
return;
}
string line;
getline(in, line); // comment
getline(in, line); // comment
getline(in, line); // comment
getline(in, line);
stringstream ss0(line);
ss0 >> nframes;
ss0 >> nbones;
while(1) {
getline(in, line);
if(in.eof()) {
break;
}
// Parse line
stringstream ss(line);
vert temp;
float tempx;
float tempy;
float tempz;
float tempw;
std::vector<vert> tempVec;
tempVec.clear();
for(unsigned int i = 0; i < nbones; i++)
{
tempVec.push_back(temp);
ss >> tempx;
ss >> tempy;
ss >> tempz;
ss >> tempw;
tempVec.at(tempVec.size() - 1).q = glm::quat(tempw, tempx, tempy, tempz);
ss >> tempx;
ss >> tempy;
ss >> tempz;
tempVec.at(tempVec.size() - 1).p = glm::vec3(tempx, tempy, tempz);
}
vertInfo.push_back(tempVec);
}
in.close();
glm::mat4 E;
std::vector<glm::mat4> tempMatVec;
for(unsigned int j = 0; j < vertInfo.size(); j++)
{
for(unsigned int k = 0; k < nbones; k++)
{
E = glm::mat4_cast(vertInfo[j][k].q);
E[3] = glm::vec4(vertInfo[j][k].p, 1.0f);
if(j == 0)
{
tempMatVec.push_back(glm::inverse(E));
}
else
tempMatVec.push_back(E);
}
transMats.push_back(tempMatVec);
tempMatVec.clear();
}
}
void ShapeSkin::init()
{
// Send the position array to the GPU
glGenBuffers(1, &posBufID);
glBindBuffer(GL_ARRAY_BUFFER, posBufID);
glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW);
// Send the normal array to the GPU
glGenBuffers(1, &norBufID);
glBindBuffer(GL_ARRAY_BUFFER, norBufID);
glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW);
// No texture info
texBufID = 0;
// Send the element array to the GPU
glGenBuffers(1, &elemBufID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elemBufID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, elemBuf.size()*sizeof(unsigned int), &elemBuf[0], GL_STATIC_DRAW);
// Unbind the arrays
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
assert(glGetError() == GL_NO_ERROR);
}
void ShapeSkin::draw(float t, std::shared_ptr<MatrixStack> MV) const
{
assert(prog);
int h_pos = prog->getAttribute("aPos");
glEnableVertexAttribArray(h_pos);
glBindBuffer(GL_ARRAY_BUFFER, posBufID);
glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0);
int h_nor = prog->getAttribute("aNor");
glEnableVertexAttribArray(h_nor);
glBindBuffer(GL_ARRAY_BUFFER, norBufID);
glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0);
// Draw
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elemBufID);
glDrawElements(GL_TRIANGLES, (int)elemBuf.size(), GL_UNSIGNED_INT, (const void *)0);
glDisableVertexAttribArray(h_nor);
glDisableVertexAttribArray(h_pos);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
float alpha = std::fmod(60.0f*t, (float)transMats.size() - 2);
float u = std::fmod(alpha, 1.0f);
int frame = std::ceil(alpha);
for(unsigned int j = 0; j < transMats[frame].size(); j++)
{
glm::mat4 p0 = transMats[frame][j];
glm::mat4 p1 = transMats[frame + 1][j];
MV->pushMatrix();
glm::mat4 temp((1 - u)*p0 + u*p1);
MV->multMatrix(glm::inverse(transMats[0][j]) + temp);
glm::vec3 pp = glm::vec3(0.0f, 0.0f, 0.0f);
glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, glm::value_ptr(MV->topMatrix()));
// Draw frenet frame
glBegin(GL_LINE_STRIP);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(pp.x, pp.y, pp.z);
glVertex3f(pp.x + 0.1f, pp.y + 0.0f, pp.z + 0.0f);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(pp.x, pp.y, pp.z);
glVertex3f(pp.x + 0.0f, pp.y + 0.1f, pp.z + 0.0f);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(pp.x, pp.y, pp.z);
glVertex3f(pp.x + 0.0f, pp.y + 0.0f, pp.z + 0.1f);
glEnd();
MV->popMatrix();
}
//
}
void ShapeSkin::skin(float t)
{
float alpha = std::fmod(60.0f*t, (float)transMats.size() - 2);
float u = std::fmod(alpha, 1.0f);
int frame = std::ceil(alpha);
std::vector<glm::mat4> tempInterpMats;
for(unsigned int j = 0 ; j < boneInfluence[0].size(); j++)
{
glm::mat4 p0 = transMats[frame][j];
glm::mat4 p1 = transMats[frame + 1][j];
glm::mat4 temp((1 - u)*p0 + u*p1);
tempInterpMats.push_back(temp);
}
for(unsigned int i = 0; i < indexes.size(); i++)
{
glm::vec4 temp(posBufInit[i*3], posBufInit[i*3 + 1], posBufInit[i*3 + 2], 1.0f);
glm::vec4 tempOutput(0.0f, 0.0f, 0.0f, 0.0f);
for(unsigned int j = 0; j < indexes[i].size(); j++)
{
glm::mat4 tempMat = transMats[0][indexes[i][j]];
glm::mat4 tempTransMat = tempInterpMats[indexes[i][j]];
float w = boneInfluence[i][indexes[i][j]];
glm::vec4 temp1 = tempMat*temp;
glm::vec4 temp2 = tempTransMat*temp1;
glm::vec4 temp3 = w*temp2;
tempOutput = tempOutput + temp3;
}
posBuf[i*3] = tempOutput.x;
posBuf[i*3 + 1] = tempOutput.y;
posBuf[i*3 + 2] = tempOutput.z;
}
glBindBuffer(GL_ARRAY_BUFFER, posBufID);
glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW);
}
void ShapeSkin::setMaterial(Material mat)
{
m = mat;
}
Material ShapeSkin::getMaterial()
{
return m;
}

View file

@ -0,0 +1,52 @@
#pragma once
#ifndef _SHAPESKIN_H_
#define _SHAPESKIN_H_
#include "MatrixStack.h"
#include <memory>
#include <vector>
#include <glm/glm.hpp>
#include "Material.h"
class Program;
struct vert
{
glm::quat q;
glm::vec3 p;
};
class ShapeSkin
{
public:
ShapeSkin();
virtual ~ShapeSkin();
void loadMesh(const std::string &meshName);
void loadAttachment(const std::string &filename);
void loadSkeleton(const std::string &filename);
void setProgram(std::shared_ptr<Program> p) { prog = p; }
void init();
void draw(float t, std::shared_ptr<MatrixStack> MV) const;
void skin(float t);
void setMaterial(Material m);
Material getMaterial();
private:
std::shared_ptr<Program> prog;
std::vector<unsigned int> elemBuf;
std::vector<float> posBuf;
std::vector<float> norBuf;
std::vector<float> texBuf;
unsigned elemBufID;
unsigned posBufID;
unsigned norBufID;
unsigned texBufID;
Material m;
std::vector<float> posBufInit;
std::vector<std::vector<float> > boneInfluence;
std::vector<std::vector<vert> > vertInfo;
std::vector<std::vector<glm::mat4> > transMats;
std::vector<std::vector<unsigned int> > indexes;
};
#endif

View file

@ -0,0 +1,291 @@
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <memory>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "GLSL.h"
#include "Program.h"
#include "Camera.h"
#include "MatrixStack.h"
#include "ShapeSkin.h"
#include "Material.h"
using namespace std;
GLFWwindow *window; // Main application window
string RESOURCE_DIR = ""; // Where the resources are loaded from
string MESH_FILE = "";
string ATTACHMENT_FILE = "";
string SKELETON_FILE = "";
bool keyToggles[256] = {false};
shared_ptr<Camera> camera = NULL;
shared_ptr<ShapeSkin> shape = NULL;
shared_ptr<Program> progSimple = NULL;
shared_ptr<Program> progSkin = NULL;
static void error_callback(int error, const char *description)
{
cerr << description << endl;
}
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
static void char_callback(GLFWwindow *window, unsigned int key)
{
keyToggles[key] = !keyToggles[key];
switch(key) {
case 'g':
break;
}
}
static void cursor_position_callback(GLFWwindow* window, double xmouse, double ymouse)
{
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
if(state == GLFW_PRESS) {
camera->mouseMoved(xmouse, ymouse);
}
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
// Get the current mouse position.
double xmouse, ymouse;
glfwGetCursorPos(window, &xmouse, &ymouse);
// Get current window size.
int width, height;
glfwGetWindowSize(window, &width, &height);
if(action == GLFW_PRESS) {
bool shift = mods & GLFW_MOD_SHIFT;
bool ctrl = mods & GLFW_MOD_CONTROL;
bool alt = mods & GLFW_MOD_ALT;
camera->mouseClicked(xmouse, ymouse, shift, ctrl, alt);
}
}
void loadScene(const string &meshFile, const string &attachmentFile)
{
keyToggles[(unsigned)'c'] = true;
camera = make_shared<Camera>();
// Single shape for all the animations.
shape = make_shared<ShapeSkin>();
shape->loadMesh(meshFile);
shape->loadAttachment(attachmentFile);
shape->loadSkeleton(SKELETON_FILE);
// For drawing the grid, etc.
progSimple = make_shared<Program>();
progSimple->setShaderNames(RESOURCE_DIR + "vert.glsl", RESOURCE_DIR + "frag.glsl");
progSimple->setVerbose(true);
// For skinned shape, CPU/GPU
progSkin = make_shared<Program>();
progSkin->setShaderNames(RESOURCE_DIR + "vert.glsl", RESOURCE_DIR + "frag.glsl");
progSkin->setVerbose(true);
}
void init()
{
// Non-OpenGL things
loadScene(MESH_FILE, ATTACHMENT_FILE);
// Set background color
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// Enable z-buffer test
glEnable(GL_DEPTH_TEST);
// Enable alpha blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shape->init();
Material m;
m.setMaterial(glm::vec3(0.1f, 0.1f, 0.3f), glm::vec3(0.2f, 0.2f, 0.5f), glm::vec3(0.2f, 0.2f, 0.6f), 50.0f);
shape->setMaterial(m);
progSimple->init();
progSimple->addUniform("P");
progSimple->addUniform("MV");
progSkin->init();
progSkin->addUniform("ka");
progSkin->addUniform("kd");
progSkin->addUniform("ks");
progSkin->addUniform("s");
progSkin->addAttribute("aPos");
progSkin->addAttribute("aNor");
progSkin->addUniform("P");
progSkin->addUniform("MV");
// Initialize time.
glfwSetTime(0.0);
GLSL::checkError(GET_FILE_LINE);
}
void render()
{
// Update time.
double t = glfwGetTime();
// Get current frame buffer size.
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Use the window size for camera.
glfwGetWindowSize(window, &width, &height);
camera->setAspect((float)width/(float)height);
// Clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(keyToggles[(unsigned)'c']) {
glEnable(GL_CULL_FACE);
} else {
glDisable(GL_CULL_FACE);
}
if(keyToggles[(unsigned)'z']) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
} else {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
auto P = make_shared<MatrixStack>();
auto MV = make_shared<MatrixStack>();
// Apply camera transforms
P->pushMatrix();
camera->applyProjectionMatrix(P);
MV->pushMatrix();
camera->applyViewMatrix(MV);
// Draw grid
progSimple->bind();
glUniformMatrix4fv(progSimple->getUniform("P"), 1, GL_FALSE, glm::value_ptr(P->topMatrix()));
glUniformMatrix4fv(progSimple->getUniform("MV"), 1, GL_FALSE, glm::value_ptr(MV->topMatrix()));
float gridSizeHalf = 5.0f;
int gridNx = 11;
int gridNz = 11;
glLineWidth(1);
glColor3f(0.8f, 0.8f, 0.8f);
glBegin(GL_LINES);
for(int i = 0; i < gridNx; ++i) {
float alpha = i / (gridNx - 1.0f);
float x = (1.0f - alpha) * (-gridSizeHalf) + alpha * gridSizeHalf;
glVertex3f(x, 0, -gridSizeHalf);
glVertex3f(x, 0, gridSizeHalf);
}
for(int i = 0; i < gridNz; ++i) {
float alpha = i / (gridNz - 1.0f);
float z = (1.0f - alpha) * (-gridSizeHalf) + alpha * gridSizeHalf;
glVertex3f(-gridSizeHalf, 0, z);
glVertex3f( gridSizeHalf, 0, z);
}
glEnd();
progSimple->unbind();
// Draw character
MV->pushMatrix();
progSkin->bind();
glUniformMatrix4fv(progSkin->getUniform("P"), 1, GL_FALSE, glm::value_ptr(P->topMatrix()));
glUniformMatrix4fv(progSkin->getUniform("MV"), 1, GL_FALSE, glm::value_ptr(MV->topMatrix()));
shape->setProgram(progSkin);
glm::vec3 ambient = shape->getMaterial().getAmbient();
glm::vec3 diffuse = shape->getMaterial().getDiffuse();
glm::vec3 specular = shape->getMaterial().getSpecular();
float shine = shape->getMaterial().getShiny();
glUniform3f(progSkin->getUniform("ka"), ambient.r, ambient.g, ambient.b);
glUniform3f(progSkin->getUniform("kd"), diffuse.r, diffuse.g, diffuse.b);
glUniform3f(progSkin->getUniform("ks"), specular.r, specular.g, specular.b);
glUniform1f(progSkin->getUniform("s"), shine);
shape->skin((float) t);
shape->draw((float) t, MV);
progSkin->unbind();
MV->popMatrix();
// Pop matrix stacks.
MV->popMatrix();
P->popMatrix();
GLSL::checkError(GET_FILE_LINE);
}
int main(int argc, char **argv)
{
if(argc < 5) {
cout << "Usage: Assignment2 <SHADER DIR> <MESH FILE> <ATTACHMENT FILE> <SKELETON FILE>" << endl;
return 0;
}
RESOURCE_DIR = argv[1] + string("/");
MESH_FILE = argv[2];
ATTACHMENT_FILE = argv[3];
SKELETON_FILE = argv[4];
// Set error callback.
glfwSetErrorCallback(error_callback);
// Initialize the library.
if(!glfwInit()) {
return -1;
}
// Create a windowed mode window and its OpenGL context.
window = glfwCreateWindow(640, 480, "Alexander Huddleston A6", NULL, NULL);
if(!window) {
glfwTerminate();
return -1;
}
// Make the window's context current.
glfwMakeContextCurrent(window);
// Initialize GLEW.
glewExperimental = true;
if(glewInit() != GLEW_OK) {
cerr << "Failed to initialize GLEW" << endl;
return -1;
}
glGetError(); // A bug in glewInit() causes an error that we can safely ignore.
cout << "OpenGL version: " << glGetString(GL_VERSION) << endl;
cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl;
// Set vsync.
glfwSwapInterval(1);
// Set keyboard callback.
glfwSetKeyCallback(window, key_callback);
// Set char callback.
glfwSetCharCallback(window, char_callback);
// Set cursor position callback.
glfwSetCursorPosCallback(window, cursor_position_callback);
// Set mouse button callback.
glfwSetMouseButtonCallback(window, mouse_button_callback);
// Initialize scene.
init();
// Loop until the user closes the window.
while(!glfwWindowShouldClose(window)) {
// Render scene.
render();
// Swap front and back buffers.
glfwSwapBuffers(window);
// Poll for and process events.
glfwPollEvents();
}
// Quit program.
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}

File diff suppressed because it is too large Load diff

39
A6/src/Material.cpp Normal file
View file

@ -0,0 +1,39 @@
#include "Material.h"
using namespace std;
Material::Material()
{
this->ca = glm::vec3(0.3f,0.3f,0.3f);
this->cd = glm::vec3(0.3f,0.3f,0.3f);
this->cs = glm::vec3(1.0f,1.0f,1.0f);
this->shine = 0.0f;
}
void Material::setMaterial(glm::vec3 a, glm::vec3 d, glm::vec3 s, float sh)
{
this->ca = a;
this->cd = d;
this->cs = s;
this->shine = sh;
}
glm::vec3 Material::getAmbient() const
{
return this->ca;
}
glm::vec3 Material::getDiffuse() const
{
return this->cd;
}
glm::vec3 Material::getSpecular() const
{
return this->cs;
}
float Material::getShiny() const
{
return this->shine;
}

46
A6/src/Material.h Normal file
View file

@ -0,0 +1,46 @@
#pragma once
#ifndef _MATERIAL_H_
#define _MATERIAL_H_
#include <cmath>
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "GLSL.h"
#include "Camera.h"
#include "MatrixStack.h"
class Material
{
private:
glm::vec3 ca;
glm::vec3 cd;
glm::vec3 cs;
float shine;
public:
Material();
Material(const Material &m)
{
ca = m.ca;
cd = m.cd;
cs = m.cs;
}
Material(glm::vec3 a, glm::vec3 d, glm::vec3 s, float sh)
{
ca = a;
cd = d;
cs = s;
shine = sh;
}
void setMaterial(glm::vec3 a, glm::vec3 d, glm::vec3 s, float sh);
glm::vec3 getAmbient() const;
glm::vec3 getDiffuse() const;
glm::vec3 getSpecular() const;
float getShiny() const;
};
#endif

View file

@ -60,12 +60,13 @@ void ShapeSkin::loadMesh(const string &meshName)
shapes[s].mesh.material_ids[f];
}
}
posBufInit = posBuf;
}
}
void ShapeSkin::loadAttachment(const std::string &filename)
{
int nverts, nbones;
unsigned int nverts, nbones;
ifstream in;
in.open(filename);
if(!in.good()) {
@ -79,7 +80,7 @@ void ShapeSkin::loadAttachment(const std::string &filename)
stringstream ss0(line);
ss0 >> nverts;
ss0 >> nbones;
assert(nverts == posBuf.size()/3);
assert((unsigned int)nverts == posBuf.size()/3);
while(1) {
getline(in, line);
if(in.eof()) {
@ -87,14 +88,97 @@ void ShapeSkin::loadAttachment(const std::string &filename)
}
// Parse line
stringstream ss(line);
//
// IMPLEMENT ME
//
float temp;
std::vector<float> tempVec;
std::vector<unsigned int> tempIndexes;
for(unsigned int i = 0; i < nbones; i++)
{
ss >> temp;
tempVec.push_back(temp);
if(temp > 0.0f)
{
tempIndexes.push_back((unsigned int) i);
}
}
indexes.push_back(tempIndexes);
boneInfluence.push_back(tempVec);
}
in.close();
}
void ShapeSkin::loadSkeleton(const std::string &filename)
{
unsigned int nframes, nbones;
ifstream in;
in.open(filename);
if(!in.good()) {
cout << "Cannot read " << filename << endl;
return;
}
string line;
getline(in, line); // comment
getline(in, line); // comment
getline(in, line); // comment
getline(in, line);
stringstream ss0(line);
ss0 >> nframes;
ss0 >> nbones;
while(1) {
getline(in, line);
if(in.eof()) {
break;
}
// Parse line
stringstream ss(line);
vert temp;
float tempx;
float tempy;
float tempz;
float tempw;
std::vector<vert> tempVec;
tempVec.clear();
for(unsigned int i = 0; i < nbones; i++)
{
tempVec.push_back(temp);
ss >> tempx;
ss >> tempy;
ss >> tempz;
ss >> tempw;
tempVec.at(tempVec.size() - 1).q = glm::quat(tempw, tempx, tempy, tempz);
ss >> tempx;
ss >> tempy;
ss >> tempz;
tempVec.at(tempVec.size() - 1).p = glm::vec3(tempx, tempy, tempz);
}
vertInfo.push_back(tempVec);
}
in.close();
glm::mat4 E;
std::vector<glm::mat4> tempMatVec;
for(unsigned int j = 0; j < vertInfo.size(); j++)
{
for(unsigned int k = 0; k < nbones; k++)
{
E = glm::mat4_cast(vertInfo[j][k].q);
E[3] = glm::vec4(vertInfo[j][k].p, 1.0f);
if(j == 0)
{
tempMatVec.push_back(glm::inverse(E));
}
else
tempMatVec.push_back(E);
}
transMats.push_back(tempMatVec);
tempMatVec.clear();
}
}
void ShapeSkin::init()
{
// Send the position array to the GPU
@ -122,7 +206,7 @@ void ShapeSkin::init()
assert(glGetError() == GL_NO_ERROR);
}
void ShapeSkin::draw() const
void ShapeSkin::draw(float t, std::shared_ptr<MatrixStack> MV) const
{
assert(prog);
@ -144,5 +228,89 @@ void ShapeSkin::draw() const
glDisableVertexAttribArray(h_pos);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
float alpha = std::fmod(60.0f*t, (float)transMats.size() - 2);
float u = std::fmod(alpha, 1.0f);
int frame = std::ceil(alpha);
for(unsigned int j = 0; j < transMats[frame].size(); j++)
{
glm::mat4 p0 = transMats[frame][j];
glm::mat4 p1 = transMats[frame + 1][j];
MV->pushMatrix();
glm::mat4 temp((1 - u)*p0 + u*p1);
MV->multMatrix(glm::inverse(transMats[0][j]) + temp);
glm::vec3 pp = glm::vec3(0.0f, 0.0f, 0.0f);
glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, glm::value_ptr(MV->topMatrix()));
// Draw frenet frame
glBegin(GL_LINE_STRIP);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(pp.x, pp.y, pp.z);
glVertex3f(pp.x + 0.1f, pp.y + 0.0f, pp.z + 0.0f);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(pp.x, pp.y, pp.z);
glVertex3f(pp.x + 0.0f, pp.y + 0.1f, pp.z + 0.0f);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(pp.x, pp.y, pp.z);
glVertex3f(pp.x + 0.0f, pp.y + 0.0f, pp.z + 0.1f);
glEnd();
MV->popMatrix();
}
//
}
void ShapeSkin::skin(float t)
{
float alpha = std::fmod(60.0f*t, (float)transMats.size() - 2);
float u = std::fmod(alpha, 1.0f);
int frame = std::ceil(alpha);
std::vector<glm::mat4> tempInterpMats;
for(unsigned int j = 0 ; j < boneInfluence[0].size(); j++)
{
glm::mat4 p0 = transMats[frame][j];
glm::mat4 p1 = transMats[frame + 1][j];
glm::mat4 temp((1 - u)*p0 + u*p1);
tempInterpMats.push_back(temp);
}
for(unsigned int i = 0; i < indexes.size(); i++)
{
glm::vec4 temp(posBufInit[i*3], posBufInit[i*3 + 1], posBufInit[i*3 + 2], 1.0f);
glm::vec4 tempOutput(0.0f, 0.0f, 0.0f, 0.0f);
for(unsigned int j = 0; j < indexes[i].size(); j++)
{
glm::mat4 tempMat = transMats[0][indexes[i][j]];
glm::mat4 tempTransMat = tempInterpMats[indexes[i][j]];
float w = boneInfluence[i][indexes[i][j]];
glm::vec4 temp1 = tempMat*temp;
glm::vec4 temp2 = tempTransMat*temp1;
glm::vec4 temp3 = w*temp2;
tempOutput = tempOutput + temp3;
}
posBuf[i*3] = tempOutput.x;
posBuf[i*3 + 1] = tempOutput.y;
posBuf[i*3 + 2] = tempOutput.z;
}
glBindBuffer(GL_ARRAY_BUFFER, posBufID);
glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW);
}
void ShapeSkin::setMaterial(Material mat)
{
m = mat;
}
Material ShapeSkin::getMaterial()
{
return m;
}

View file

@ -2,11 +2,20 @@
#ifndef _SHAPESKIN_H_
#define _SHAPESKIN_H_
#include "MatrixStack.h"
#include <memory>
#include <vector>
#include <glm/glm.hpp>
#include "Material.h"
class MatrixStack;
class Program;
struct vert
{
glm::quat q;
glm::vec3 p;
};
class ShapeSkin
{
public:
@ -14,9 +23,13 @@ public:
virtual ~ShapeSkin();
void loadMesh(const std::string &meshName);
void loadAttachment(const std::string &filename);
void loadSkeleton(const std::string &filename);
void setProgram(std::shared_ptr<Program> p) { prog = p; }
void init();
void draw() const;
void draw(float t, std::shared_ptr<MatrixStack> MV) const;
void skin(float t);
void setMaterial(Material m);
Material getMaterial();
private:
std::shared_ptr<Program> prog;
@ -28,6 +41,12 @@ private:
unsigned posBufID;
unsigned norBufID;
unsigned texBufID;
Material m;
std::vector<float> posBufInit;
std::vector<std::vector<float> > boneInfluence;
std::vector<std::vector<vert> > vertInfo;
std::vector<std::vector<glm::mat4> > transMats;
std::vector<std::vector<unsigned int> > indexes;
};
#endif

View file

@ -17,6 +17,7 @@
#include "Camera.h"
#include "MatrixStack.h"
#include "ShapeSkin.h"
#include "Material.h"
using namespace std;
@ -87,6 +88,7 @@ void loadScene(const string &meshFile, const string &attachmentFile)
shape = make_shared<ShapeSkin>();
shape->loadMesh(meshFile);
shape->loadAttachment(attachmentFile);
shape->loadSkeleton(SKELETON_FILE);
// For drawing the grid, etc.
progSimple = make_shared<Program>();
@ -95,7 +97,7 @@ void loadScene(const string &meshFile, const string &attachmentFile)
// For skinned shape, CPU/GPU
progSkin = make_shared<Program>();
progSkin->setShaderNames(RESOURCE_DIR + "skin_vert.glsl", RESOURCE_DIR + "skin_frag.glsl");
progSkin->setShaderNames(RESOURCE_DIR + "vert.glsl", RESOURCE_DIR + "frag.glsl");
progSkin->setVerbose(true);
}
@ -113,12 +115,20 @@ void init()
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shape->init();
Material m;
m.setMaterial(glm::vec3(0.1f, 0.1f, 0.3f), glm::vec3(0.2f, 0.2f, 0.5f), glm::vec3(0.2f, 0.2f, 0.6f), 50.0f);
shape->setMaterial(m);
progSimple->init();
progSimple->addUniform("P");
progSimple->addUniform("MV");
progSkin->init();
progSkin->addAttribute("aPos");
progSkin->addUniform("ka");
progSkin->addUniform("kd");
progSkin->addUniform("ks");
progSkin->addUniform("s");
progSkin->addAttribute("aPos");
progSkin->addAttribute("aNor");
progSkin->addUniform("P");
progSkin->addUniform("MV");
@ -196,7 +206,19 @@ void render()
glUniformMatrix4fv(progSkin->getUniform("P"), 1, GL_FALSE, glm::value_ptr(P->topMatrix()));
glUniformMatrix4fv(progSkin->getUniform("MV"), 1, GL_FALSE, glm::value_ptr(MV->topMatrix()));
shape->setProgram(progSkin);
shape->draw();
glm::vec3 ambient = shape->getMaterial().getAmbient();
glm::vec3 diffuse = shape->getMaterial().getDiffuse();
glm::vec3 specular = shape->getMaterial().getSpecular();
float shine = shape->getMaterial().getShiny();
glUniform3f(progSkin->getUniform("ka"), ambient.r, ambient.g, ambient.b);
glUniform3f(progSkin->getUniform("kd"), diffuse.r, diffuse.g, diffuse.b);
glUniform3f(progSkin->getUniform("ks"), specular.r, specular.g, specular.b);
glUniform1f(progSkin->getUniform("s"), shine);
shape->skin((float) t);
shape->draw((float) t, MV);
progSkin->unbind();
MV->popMatrix();
@ -225,7 +247,7 @@ int main(int argc, char **argv)
return -1;
}
// Create a windowed mode window and its OpenGL context.
window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL);
window = glfwCreateWindow(640, 480, "Alexander Huddleston A6", NULL, NULL);
if(!window) {
glfwTerminate();
return -1;