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. 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]; shapes[s].mesh.material_ids[f];
} }
} }
posBufInit = posBuf;
} }
} }
void ShapeSkin::loadAttachment(const std::string &filename) void ShapeSkin::loadAttachment(const std::string &filename)
{ {
int nverts, nbones; unsigned int nverts, nbones;
ifstream in; ifstream in;
in.open(filename); in.open(filename);
if(!in.good()) { if(!in.good()) {
@ -79,7 +80,7 @@ void ShapeSkin::loadAttachment(const std::string &filename)
stringstream ss0(line); stringstream ss0(line);
ss0 >> nverts; ss0 >> nverts;
ss0 >> nbones; ss0 >> nbones;
assert(nverts == posBuf.size()/3); assert((unsigned int)nverts == posBuf.size()/3);
while(1) { while(1) {
getline(in, line); getline(in, line);
if(in.eof()) { if(in.eof()) {
@ -87,14 +88,97 @@ void ShapeSkin::loadAttachment(const std::string &filename)
} }
// Parse line // Parse line
stringstream ss(line); stringstream ss(line);
float temp;
// std::vector<float> tempVec;
// IMPLEMENT ME 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(); 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() void ShapeSkin::init()
{ {
// Send the position array to the GPU // Send the position array to the GPU
@ -122,7 +206,7 @@ void ShapeSkin::init()
assert(glGetError() == GL_NO_ERROR); assert(glGetError() == GL_NO_ERROR);
} }
void ShapeSkin::draw() const void ShapeSkin::draw(float t, std::shared_ptr<MatrixStack> MV) const
{ {
assert(prog); assert(prog);
@ -144,5 +228,89 @@ void ShapeSkin::draw() const
glDisableVertexAttribArray(h_pos); glDisableVertexAttribArray(h_pos);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_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_ #ifndef _SHAPESKIN_H_
#define _SHAPESKIN_H_ #define _SHAPESKIN_H_
#include "MatrixStack.h"
#include <memory> #include <memory>
#include <vector>
#include <glm/glm.hpp>
#include "Material.h"
class MatrixStack;
class Program; class Program;
struct vert
{
glm::quat q;
glm::vec3 p;
};
class ShapeSkin class ShapeSkin
{ {
public: public:
@ -14,9 +23,13 @@ public:
virtual ~ShapeSkin(); virtual ~ShapeSkin();
void loadMesh(const std::string &meshName); void loadMesh(const std::string &meshName);
void loadAttachment(const std::string &filename); void loadAttachment(const std::string &filename);
void loadSkeleton(const std::string &filename);
void setProgram(std::shared_ptr<Program> p) { prog = p; } void setProgram(std::shared_ptr<Program> p) { prog = p; }
void init(); 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: private:
std::shared_ptr<Program> prog; std::shared_ptr<Program> prog;
@ -28,6 +41,12 @@ private:
unsigned posBufID; unsigned posBufID;
unsigned norBufID; unsigned norBufID;
unsigned texBufID; 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 #endif

View file

@ -17,6 +17,7 @@
#include "Camera.h" #include "Camera.h"
#include "MatrixStack.h" #include "MatrixStack.h"
#include "ShapeSkin.h" #include "ShapeSkin.h"
#include "Material.h"
using namespace std; using namespace std;
@ -87,6 +88,7 @@ void loadScene(const string &meshFile, const string &attachmentFile)
shape = make_shared<ShapeSkin>(); shape = make_shared<ShapeSkin>();
shape->loadMesh(meshFile); shape->loadMesh(meshFile);
shape->loadAttachment(attachmentFile); shape->loadAttachment(attachmentFile);
shape->loadSkeleton(SKELETON_FILE);
// For drawing the grid, etc. // For drawing the grid, etc.
progSimple = make_shared<Program>(); progSimple = make_shared<Program>();
@ -95,7 +97,7 @@ void loadScene(const string &meshFile, const string &attachmentFile)
// For skinned shape, CPU/GPU // For skinned shape, CPU/GPU
progSkin = make_shared<Program>(); 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); progSkin->setVerbose(true);
} }
@ -113,12 +115,20 @@ void init()
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shape->init(); 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->init();
progSimple->addUniform("P"); progSimple->addUniform("P");
progSimple->addUniform("MV"); progSimple->addUniform("MV");
progSkin->init(); progSkin->init();
progSkin->addAttribute("aPos"); progSkin->addUniform("ka");
progSkin->addUniform("kd");
progSkin->addUniform("ks");
progSkin->addUniform("s");
progSkin->addAttribute("aPos");
progSkin->addAttribute("aNor"); progSkin->addAttribute("aNor");
progSkin->addUniform("P"); progSkin->addUniform("P");
progSkin->addUniform("MV"); progSkin->addUniform("MV");
@ -196,7 +206,19 @@ void render()
glUniformMatrix4fv(progSkin->getUniform("P"), 1, GL_FALSE, glm::value_ptr(P->topMatrix())); glUniformMatrix4fv(progSkin->getUniform("P"), 1, GL_FALSE, glm::value_ptr(P->topMatrix()));
glUniformMatrix4fv(progSkin->getUniform("MV"), 1, GL_FALSE, glm::value_ptr(MV->topMatrix())); glUniformMatrix4fv(progSkin->getUniform("MV"), 1, GL_FALSE, glm::value_ptr(MV->topMatrix()));
shape->setProgram(progSkin); 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(); progSkin->unbind();
MV->popMatrix(); MV->popMatrix();
@ -225,7 +247,7 @@ int main(int argc, char **argv)
return -1; return -1;
} }
// Create a windowed mode window and its OpenGL context. // 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) { if(!window) {
glfwTerminate(); glfwTerminate();
return -1; return -1;