initial commit
Everything works correctly so far. Only the basics though. There's a light at the viewer (+z-axis) and the object gets loaded in the center. You can move with the keyboard ('wasd' and 'qe' do translation, 'ijkl' and 'ou' do rotations). Planning on changing that to use mouse input. Also hoping to add a way to move the lighting around.master
commit
a7b124996e
|
@ -0,0 +1,190 @@
|
|||
#### PROJECT SETTINGS ####
|
||||
# The name of the executable to be created
|
||||
BIN_NAME := obj-loader
|
||||
# Compiler used
|
||||
CXX ?= g++
|
||||
# Extension of source files used in the project
|
||||
SRC_EXT = cpp
|
||||
# Path to the source directory, relative to the makefile
|
||||
SRC_PATH = src
|
||||
# General compiler flags
|
||||
COMPILE_FLAGS = -Wall -Wextra -g -O2
|
||||
# Additional release-specific flags
|
||||
RCOMPILE_FLAGS = -D NDEBUG
|
||||
# Additional debug-specific flags
|
||||
DCOMPILE_FLAGS = -D DEBUG
|
||||
# Add additional include paths
|
||||
INCLUDES = -I $(SRC_PATH)/ -IGL -IGLEW -IGLM -IGLFW
|
||||
# General linker settings
|
||||
LINK_FLAGS = -lGL -lGLEW -lglfw
|
||||
# Additional release-specific linker settings
|
||||
RLINK_FLAGS =
|
||||
# Additional debug-specific linker settings
|
||||
DLINK_FLAGS =
|
||||
# Destination directory, like a jail or mounted system
|
||||
DESTDIR = /
|
||||
# Install path (bin/ is appended automatically)
|
||||
INSTALL_PREFIX = usr/local
|
||||
#### END PROJECT SETTINGS ####
|
||||
|
||||
# Generally should not need to edit below this line
|
||||
|
||||
# Shell used in this makefile
|
||||
# bash is used for 'echo -en'
|
||||
SHELL = /bin/bash
|
||||
# Clear built-in rules
|
||||
.SUFFIXES:
|
||||
# Programs for installation
|
||||
INSTALL = install
|
||||
INSTALL_PROGRAM = $(INSTALL)
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
|
||||
# Verbose option, to output compile and link commands
|
||||
export V := false
|
||||
export CMD_PREFIX := @
|
||||
ifeq ($(V),true)
|
||||
CMD_PREFIX :=
|
||||
endif
|
||||
|
||||
# Combine compiler and linker flags
|
||||
release: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(RCOMPILE_FLAGS)
|
||||
release: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(RLINK_FLAGS)
|
||||
debug: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(DCOMPILE_FLAGS)
|
||||
debug: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(DLINK_FLAGS)
|
||||
|
||||
# Build and output paths
|
||||
release: export BUILD_PATH := build/release
|
||||
release: export BIN_PATH := bin/release
|
||||
debug: export BUILD_PATH := build/debug
|
||||
debug: export BIN_PATH := bin/debug
|
||||
install: export BIN_PATH := bin/release
|
||||
|
||||
# Find all source files in the source directory, sorted by most
|
||||
# recently modified
|
||||
SOURCES = $(shell find $(SRC_PATH)/ -name '*.$(SRC_EXT)' -printf '%T@\t%p\n' \
|
||||
| sort -k 1nr | cut -f2-)
|
||||
# fallback in case the above fails
|
||||
rwildcard = $(foreach d, $(wildcard $1*), $(call rwildcard,$d/,$2) \
|
||||
$(filter $(subst *,%,$2), $d))
|
||||
ifeq ($(SOURCES),)
|
||||
SOURCES := $(call rwildcard, $(SRC_PATH)/, *.$(SRC_EXT))
|
||||
endif
|
||||
|
||||
# Set the object file names, with the source directory stripped
|
||||
# from the path, and the build path prepended in its place
|
||||
OBJECTS = $(SOURCES:$(SRC_PATH)/%.$(SRC_EXT)=$(BUILD_PATH)/%.o)
|
||||
# Set the dependency files that will be used to add header dependencies
|
||||
DEPS = $(OBJECTS:.o=.d)
|
||||
|
||||
# Macros for timing compilation
|
||||
TIME_FILE = $(dir $@).$(notdir $@)_time
|
||||
START_TIME = date '+%s' > $(TIME_FILE)
|
||||
END_TIME = read st < $(TIME_FILE) ; \
|
||||
$(RM) $(TIME_FILE) ; \
|
||||
st=$$((`date '+%s'` - $$st - 86400)) ; \
|
||||
echo `date -u -d @$$st '+%H:%M:%S'`
|
||||
|
||||
# Version macros
|
||||
# Comment/remove this section to remove versioning
|
||||
USE_VERSION := false
|
||||
# If this isn't a git repo or the repo has no tags, git describe will return non-zero
|
||||
ifeq ($(shell git describe > /dev/null 2>&1 ; echo $$?), 0)
|
||||
USE_VERSION := true
|
||||
VERSION := $(shell git describe --tags --long --dirty --always | \
|
||||
sed 's/v\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)-\?.*-\([0-9]*\)-\(.*\)/\1 \2 \3 \4 \5/g')
|
||||
VERSION_MAJOR := $(word 1, $(VERSION))
|
||||
VERSION_MINOR := $(word 2, $(VERSION))
|
||||
VERSION_PATCH := $(word 3, $(VERSION))
|
||||
VERSION_REVISION := $(word 4, $(VERSION))
|
||||
VERSION_HASH := $(word 5, $(VERSION))
|
||||
VERSION_STRING := \
|
||||
"$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH).$(VERSION_REVISION)-$(VERSION_HASH)"
|
||||
override CXXFLAGS := $(CXXFLAGS) \
|
||||
-D VERSION_MAJOR=$(VERSION_MAJOR) \
|
||||
-D VERSION_MINOR=$(VERSION_MINOR) \
|
||||
-D VERSION_PATCH=$(VERSION_PATCH) \
|
||||
-D VERSION_REVISION=$(VERSION_REVISION) \
|
||||
-D VERSION_HASH=\"$(VERSION_HASH)\"
|
||||
endif
|
||||
|
||||
# Standard, non-optimized release build
|
||||
.PHONY: release
|
||||
release: dirs
|
||||
ifeq ($(USE_VERSION), true)
|
||||
@echo "Beginning release build v$(VERSION_STRING)"
|
||||
else
|
||||
@echo "Beginning release build"
|
||||
endif
|
||||
@$(START_TIME)
|
||||
@$(MAKE) all --no-print-directory
|
||||
@echo -n "Total build time: "
|
||||
@$(END_TIME)
|
||||
|
||||
# Debug build for gdb debugging
|
||||
.PHONY: debug
|
||||
debug: dirs
|
||||
ifeq ($(USE_VERSION), true)
|
||||
@echo "Beginning debug build v$(VERSION_STRING)"
|
||||
else
|
||||
@echo "Beginning debug build"
|
||||
endif
|
||||
@$(START_TIME)
|
||||
@$(MAKE) all --no-print-directory
|
||||
@echo -n "Total build time: "
|
||||
@$(END_TIME)
|
||||
|
||||
# Create the directories used in the build
|
||||
.PHONY: dirs
|
||||
dirs:
|
||||
@echo "Creating directories"
|
||||
@mkdir -p $(dir $(OBJECTS))
|
||||
@mkdir -p $(BIN_PATH)
|
||||
|
||||
# Installs to the set path
|
||||
.PHONY: install
|
||||
install:
|
||||
@echo "Installing to $(DESTDIR)$(INSTALL_PREFIX)/bin"
|
||||
@$(INSTALL_PROGRAM) $(BIN_PATH)/$(BIN_NAME) $(DESTDIR)$(INSTALL_PREFIX)/bin
|
||||
|
||||
# Uninstalls the program
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
||||
@echo "Removing $(DESTDIR)$(INSTALL_PREFIX)/bin/$(BIN_NAME)"
|
||||
@$(RM) $(DESTDIR)$(INSTALL_PREFIX)/bin/$(BIN_NAME)
|
||||
|
||||
# Removes all build files
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@echo "Deleting $(BIN_NAME) symlink"
|
||||
@$(RM) $(BIN_NAME)
|
||||
@echo "Deleting directories"
|
||||
@$(RM) -r build
|
||||
@$(RM) -r bin
|
||||
|
||||
# Main rule, checks the executable and symlinks to the output
|
||||
all: $(BIN_PATH)/$(BIN_NAME)
|
||||
@echo "Making symlink: $(BIN_NAME) -> $<"
|
||||
@$(RM) $(BIN_NAME)
|
||||
@ln -s $(BIN_PATH)/$(BIN_NAME) $(BIN_NAME)
|
||||
|
||||
# Link the executable
|
||||
$(BIN_PATH)/$(BIN_NAME): $(OBJECTS)
|
||||
@echo "Linking: $@"
|
||||
@$(START_TIME)
|
||||
$(CMD_PREFIX)$(CXX) $(OBJECTS) $(LDFLAGS) -o $@
|
||||
@echo -en "\t Link time: "
|
||||
@$(END_TIME)
|
||||
|
||||
# Add dependency files, if they exist
|
||||
-include $(DEPS)
|
||||
|
||||
# Source file rules
|
||||
# After the first compilation they will be joined with the rules from the
|
||||
# dependency files to provide header dependencies
|
||||
$(BUILD_PATH)/%.o: $(SRC_PATH)/%.$(SRC_EXT)
|
||||
@echo "Compiling: $< -> $@"
|
||||
@$(START_TIME)
|
||||
$(CMD_PREFIX)$(CXX) $(CXXFLAGS) $(INCLUDES) -MP -MMD -c $< -o $@
|
||||
@echo -en "\t Compile time: "
|
||||
@$(END_TIME)
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
|
@ -0,0 +1,10 @@
|
|||
# Blender MTL File: 'None'
|
||||
# Material Count: 1
|
||||
|
||||
newmtl None
|
||||
Ns 0
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.8 0.8 0.8
|
||||
Ks 0.8 0.8 0.8
|
||||
d 1
|
||||
illum 2
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,10 @@
|
|||
# Blender MTL File: 'None'
|
||||
# Material Count: 1
|
||||
|
||||
newmtl None
|
||||
Ns 0
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.8 0.8 0.8
|
||||
Ks 0.8 0.8 0.8
|
||||
d 1
|
||||
illum 2
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
|||
Here's where I got it from
|
||||
|
||||
http://www.blender-models.com/model-downloads/animals/mammals/id/sheep-comic-style/
|
Binary file not shown.
|
@ -0,0 +1,90 @@
|
|||
# Blender MTL File: 'sheep.blend'
|
||||
# Material Count: 9
|
||||
|
||||
newmtl Material.001
|
||||
Ns 96.078431
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.640000 0.640000 0.640000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
map_Kd C:/Dokumente und Einstellungen/Robbi/Anwendungsdaten/Blender Foundation/Blender/.blender/Braun.JPG
|
||||
|
||||
newmtl Material.002
|
||||
Ns 96.078431
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.640000 0.640000 0.640000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
map_Kd C:/Dokumente und Einstellungen/Robbi/Anwendungsdaten/Blender Foundation/Blender/.blender/Braun.JPG
|
||||
|
||||
newmtl Material.003
|
||||
Ns 96.078431
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.640000 0.640000 0.640000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
map_Kd C:/Dokumente und Einstellungen/Robbi/Anwendungsdaten/Blender Foundation/Blender/.blender/wei\udcdf.bmp
|
||||
|
||||
newmtl Material.004
|
||||
Ns 96.078431
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.640000 0.640000 0.640000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
map_Kd C:/Dokumente und Einstellungen/Robbi/Anwendungsdaten/Blender Foundation/Blender/.blender/wei\udcdf.bmp
|
||||
|
||||
newmtl Material.005
|
||||
Ns 96.078431
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.640000 0.640000 0.640000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
map_Kd C:/Dokumente und Einstellungen/Robbi/Anwendungsdaten/Blender Foundation/Blender/.blender/schwarz.bmp
|
||||
|
||||
newmtl Material.006
|
||||
Ns 96.078431
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.640000 0.640000 0.640000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
map_Kd C:/Dokumente und Einstellungen/Robbi/Anwendungsdaten/Blender Foundation/Blender/.blender/schwarz.bmp
|
||||
|
||||
newmtl Material.007
|
||||
Ns 96.078431
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.640000 0.640000 0.640000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
map_Kd C:/Dokumente und Einstellungen/Robbi/Anwendungsdaten/Blender Foundation/Blender/.blender/schwarz.bmp
|
||||
|
||||
newmtl Material.008
|
||||
Ns 96.078431
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.640000 0.640000 0.640000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
map_Kd C:/Dokumente und Einstellungen/Robbi/Anwendungsdaten/Blender Foundation/Blender/.blender/schwarz.bmp
|
||||
|
||||
newmtl None
|
||||
Ns 0
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.8 0.8 0.8
|
||||
Ks 0.8 0.8 0.8
|
||||
d 1
|
||||
illum 2
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,11 @@
|
|||
size 100 100
|
||||
|
||||
camera 0 0 10 0 0 0 0 1 0 30
|
||||
|
||||
point 10 10 10 1 1 1
|
||||
|
||||
ambient .1 .1 .1
|
||||
diffuse .4 .4 .4
|
||||
specular .8 .8 .8
|
||||
shininess 16
|
||||
object sheep.obj
|
Binary file not shown.
|
@ -0,0 +1,10 @@
|
|||
# Blender MTL File: 'suzanne.blend'
|
||||
# Material Count: 1
|
||||
|
||||
newmtl None
|
||||
Ns 0
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 0.8 0.8 0.8
|
||||
Ks 0.8 0.8 0.8
|
||||
d 1
|
||||
illum 2
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Michael Crawford
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
Simple fragment shader
|
||||
*/
|
||||
|
||||
#version 150
|
||||
|
||||
in vec4 Color;
|
||||
|
||||
out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = Color;
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
vertexShader - an OpenGL shader that implements Phong shading.
|
||||
*/
|
||||
|
||||
#version 150
|
||||
|
||||
// vertex properties
|
||||
in vec3 vPosition;
|
||||
in vec3 vNormal;
|
||||
in vec3 ambientColor;
|
||||
in vec3 diffuseColor;
|
||||
in vec3 specularColor;
|
||||
in float shininess;
|
||||
|
||||
// light properties
|
||||
uniform vec3 lightPosition;
|
||||
uniform vec3 lightColor;
|
||||
uniform vec3 lightDirection; // if directional
|
||||
|
||||
// viewer properties
|
||||
uniform vec3 viewPosition;
|
||||
uniform vec3 viewDirection;
|
||||
|
||||
// matrices
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 proj;
|
||||
|
||||
// outputs the color for this vertex
|
||||
out vec4 Color;
|
||||
|
||||
void main() {
|
||||
/**
|
||||
Calculate the position after matrix transformations
|
||||
*/
|
||||
mat4 modelView = view * model;
|
||||
mat3 normalMatrix;
|
||||
normalMatrix[0] = modelView[0].xyz;
|
||||
normalMatrix[1] = modelView[1].xyz;
|
||||
normalMatrix[2] = modelView[2].xyz;
|
||||
|
||||
// output the position to the special gl_Position variable
|
||||
gl_Position = proj * modelView * vec4(vPosition, 1.0);
|
||||
|
||||
|
||||
/**
|
||||
Phong shading calculations for color
|
||||
*/
|
||||
vec3 tempColor = vec3(0,0,0);
|
||||
vec3 d = lightDirection;
|
||||
vec3 n = vNormal;
|
||||
|
||||
// point light needs to calculate direction
|
||||
if (lightDirection == vec3(0.0,0.0,0.0)) {
|
||||
d = normalize(vPosition - lightPosition);
|
||||
}
|
||||
|
||||
d = vec3(0,0,1);
|
||||
|
||||
|
||||
// ambient
|
||||
tempColor += ambientColor;
|
||||
|
||||
// diffuse
|
||||
vec3 tempDiffColor = diffuseColor * dot(d, n);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (tempDiffColor[i] < 0.0) {
|
||||
tempDiffColor[i] = 0.0;
|
||||
}
|
||||
}
|
||||
tempColor += tempDiffColor;
|
||||
|
||||
// specular
|
||||
vec3 r = d + 2*(dot(-1*d,n)) * n;
|
||||
float re = dot(r,viewDirection);
|
||||
if (re < 0) {
|
||||
re = 0;
|
||||
}
|
||||
re = pow(re, shininess);
|
||||
|
||||
vec3 tempSpecColor = specularColor * re;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (tempSpecColor[i] < 0.0) {
|
||||
tempSpecColor[i] = 0.0;
|
||||
}
|
||||
}
|
||||
tempColor += tempSpecColor;
|
||||
|
||||
// fix the color to fit constraints
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (tempColor[i] > 1) {
|
||||
tempColor[i] = 1;
|
||||
}
|
||||
if (tempColor[i] < 0) {
|
||||
tempColor[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// output color
|
||||
Color = vec4(tempColor,1.0);
|
||||
//Color = vec4(1.0,1.0,1.0,1.0);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
Camera - storage class for the viewer's camera
|
||||
|
||||
Contains position, viewing direction, and up direction.
|
||||
*/
|
||||
|
||||
#include "Camera.h"
|
||||
|
||||
using namespace glm;
|
||||
|
||||
int Camera::init(vec3 pos, vec3 target, vec3 up) {
|
||||
this->position = pos;
|
||||
this->target = target;
|
||||
this->up = up;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Camera::Camera() {
|
||||
// default to looking down negative z-axis
|
||||
vec3 p (0.0f, 0.0f, 5.0f);
|
||||
vec3 t (0.0f, 0.0f, 0.0f);
|
||||
vec3 up (0.0f, 1.0f, 0.0f);
|
||||
init(p, t, up);
|
||||
}
|
||||
|
||||
Camera::Camera(vec3 pos, vec3 dir, vec3 up) {
|
||||
init(pos, dir, up);
|
||||
}
|
||||
|
||||
vec3 Camera::getPosition() const {
|
||||
return this->position;
|
||||
}
|
||||
|
||||
vec3 Camera::getTarget() const {
|
||||
return this->target;
|
||||
}
|
||||
|
||||
vec3 Camera::getUpDir() const {
|
||||
return this->up;
|
||||
}
|
||||
|
||||
vec3 Camera::getViewDir() const {
|
||||
return normalize(this->target - this->position);
|
||||
}
|
||||
|
||||
void Camera::translate(vec3 v) {
|
||||
this->position += v;
|
||||
this->target += v; // keep the view direction constant
|
||||
}
|
||||
|
||||
// axis-angle rotation
|
||||
void Camera::rotate(vec3 v) {
|
||||
float angle = length(v);
|
||||
vec3 w = normalize(v);
|
||||
vec3 a = this->getViewDir();
|
||||
|
||||
// rodrigues formula to rotate
|
||||
vec3 b =
|
||||
a*cos(angle) + cross(w,a)*sin(angle) + w*dot(w,a)*(1-cos(angle));
|
||||
vec3 view = this->target - this->position;
|
||||
this->target = this->position + b*length(view);
|
||||
|
||||
a = this->getUpDir();
|
||||
this->up =
|
||||
a*cos(angle) + cross(w,a)*sin(angle) + w*dot(w,a)*(1-cos(angle));
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
Camera - storage class for the viewer's camera
|
||||
|
||||
Contains position, viewing direction, and up direction.
|
||||
*/
|
||||
|
||||
#ifndef CAMERA_H
|
||||
#define CAMERA_H
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
using namespace glm;
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
Camera();
|
||||
Camera(vec3 pos, vec3 dir, vec3 up);
|
||||
|
||||
vec3 getPosition() const;
|
||||
vec3 getTarget() const;
|
||||
vec3 getViewDir() const;
|
||||
vec3 getUpDir() const;
|
||||
|
||||
void translate(vec3 v);
|
||||
void rotate(vec3 v);
|
||||
|
||||
private:
|
||||
vec3 position;
|
||||
vec3 target;
|
||||
vec3 up;
|
||||
|
||||
int init(vec3 pos, vec3 dir, vec3 up);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,414 @@
|
|||
/**
|
||||
Object - a storage class for a .obj file
|
||||
*/
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int Object::init(string filename, Shader* s) {
|
||||
if (s == NULL) {
|
||||
cerr << "Shader was null in Object::init(). Object not created.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
this->parseObjectFile(filename);
|
||||
glm::mat4 id (1.0f); // identity
|
||||
this->transformation = id;
|
||||
this->shader = s;
|
||||
this->vao = 0;
|
||||
|
||||
this->elms = 16; // 3 pos, 3 norm, 3*3 color, 1 shine
|
||||
|
||||
// default to white/greyish
|
||||
glm::vec3 white (1.0f,1.0f,1.0f);
|
||||
this->ambient = white * 0.1f;
|
||||
this->diffuse = white * 0.4f;
|
||||
this->specular = white * 0.8f;
|
||||
this->shininess = 16.0f;
|
||||
|
||||
openglInitialization();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Object::Object() {
|
||||
init(NULL, NULL);
|
||||
}
|
||||
|
||||
Object::Object(string filename, Shader* s) {
|
||||
init(filename, s);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Loads a .obj file and parses it.
|
||||
|
||||
Note: I did not implement the entire .obj specification.
|
||||
I only implemented vertices, vertex normals, and faces under the
|
||||
assumption that each face is a triangle.
|
||||
*/
|
||||
void Object::parseObjectFile(string filename) {
|
||||
if (this->vertices.size() > 0) {
|
||||
cerr << "Object has already been loaded from file.\n"
|
||||
<< "Loading again is undefined and not allowed.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
ifstream file (filename.c_str());
|
||||
if (!file) {
|
||||
cerr << "Failed to open object file: " << filename << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
string line;
|
||||
while (getline(file,line)) {
|
||||
stringstream ss (line);
|
||||
|
||||
if (line.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string op;
|
||||
ss >> op;
|
||||
|
||||
// vertices
|
||||
if (op == "v") {
|
||||
float x,y,z;
|
||||
ss >> x >> y >> z;
|
||||
glm::vec3 v (x,y,z);
|
||||
this->vertices.push_back(v);
|
||||
}
|
||||
|
||||
// vertex normals
|
||||
if (op == "vn") {
|
||||
float x,y,z;
|
||||
ss >> x >> y >> z;
|
||||
glm::vec3 v (x,y,z);
|
||||
this->vertexNormals.push_back(v);
|
||||
}
|
||||
|
||||
// parse a triangle face
|
||||
if (op == "f") {
|
||||
string s1,s2,s3;
|
||||
|
||||
// strings should be like
|
||||
// "f 6//1 7//1 4//1"
|
||||
// or "f 2 3 4"
|
||||
ss >> s1 >> s2 >> s3;
|
||||
|
||||
int a,b,c;
|
||||
int an,bn,cn;
|
||||
a = parseOBJVertex(s1);
|
||||
b = parseOBJVertex(s2);
|
||||
c = parseOBJVertex(s3);
|
||||
an = parseOBJVertexNormal(s1);
|
||||
bn = parseOBJVertexNormal(s2);
|
||||
cn = parseOBJVertexNormal(s3);
|
||||
|
||||
Triangle t;
|
||||
if (an != -1 && bn != -1 && cn != -1) {
|
||||
Triangle tr (a,b,c,an,bn,cn);
|
||||
t = tr;
|
||||
} else {
|
||||
Triangle tr (a,b,c);
|
||||
t = tr;
|
||||
}
|
||||
this->triangles.push_back(t);
|
||||
}
|
||||
|
||||
// I didn't implement the entire .obj specification
|
||||
// rest is garbled gooky shit.
|
||||
}
|
||||
}
|
||||
|
||||
void Object::glDraw() {
|
||||
this->applyModelMatrix();
|
||||
|
||||
glBindVertexArray(this->vao);
|
||||
glDrawElements(GL_TRIANGLES, this->triangles.size()*3,
|
||||
GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
void Object::setShader(Shader* shader) {
|
||||
this->shader = shader;
|
||||
}
|
||||
|
||||
void Object::openglInitialization() {
|
||||
|
||||
// initialize the vao, vbo, and ebo
|
||||
GLuint vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
this->vao = vao;
|
||||
|
||||
GLuint vbo;
|
||||
glGenBuffers(1, &vbo);
|
||||
|
||||
GLuint ebo;
|
||||
glGenBuffers(1, &ebo);
|
||||
|
||||
|
||||
// create the vertex array
|
||||
GLfloat vertexArray[this->vertices.size()*this->elms];
|
||||
|
||||
/*
|
||||
The following for-loop got messy but was necessary because OpenGL
|
||||
expects all vertex information (including the vertex normal) to be
|
||||
in the vertex array (simply offset by however much we tell
|
||||
it). This means we needed to map the vertex to its vertex normal
|
||||
using the triangle faces (as they are the only things that have
|
||||
that information). Because we were grabbing the vertices out of
|
||||
the triangles, we needed new element indices as well, so that's
|
||||
where q comes in.
|
||||
*/
|
||||
Triangle* t;
|
||||
vector<uint> v, vn;
|
||||
map<uint,uint> vertexMap; // mapping of vertex index to element index
|
||||
uint q = 0; // element counter for current vertex
|
||||
for (uint i = 0; i < this->triangles.size(); i++) {
|
||||
t = &this->triangles[i];
|
||||
v = t->getVertices();
|
||||
vn = t->getVertexNormals();
|
||||
|
||||
for (uint k = 0; k < 3; k++) {
|
||||
uint a = q*this->elms;
|
||||
uint vi = v[k]-1;
|
||||
uint vni = vn[k]-1;
|
||||
if (vertexMap.find(vi) == vertexMap.end()) {
|
||||
// add the vertex to the set and increment the counter
|
||||
// the counter (q) is the element index
|
||||
q++;
|
||||
vertexMap.insert(pair<uint,uint>(vi,q));
|
||||
|
||||
// vertex position
|
||||
glm::vec3 vert = this->vertices[vi];
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
vertexArray[a+j] = vert[j];
|
||||
}
|
||||
a += 3;
|
||||
|
||||
// vertex normal
|
||||
glm::vec3 vertn = this->vertexNormals[vni];
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
vertexArray[a+j] = vertn[j];
|
||||
}
|
||||
a += 3;
|
||||
|
||||
// ambient color
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
vertexArray[a+j] = this->ambient[j];
|
||||
}
|
||||
a += 3;
|
||||
|
||||
// diffuse color
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
vertexArray[a+j] = this->diffuse[j];
|
||||
}
|
||||
a += 3;
|
||||
|
||||
// specular color
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
vertexArray[a+j] = this->specular[j];
|
||||
}
|
||||
a += 3;
|
||||
|
||||
// specular exponent (shininess)
|
||||
vertexArray[a] = this->shininess;
|
||||
a += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray),
|
||||
vertexArray, GL_STATIC_DRAW);
|
||||
|
||||
/*
|
||||
Here we finally create the element array that maps element indices
|
||||
to vertices in the vertex array.
|
||||
*/
|
||||
uint elementArray[this->triangles.size()*3];
|
||||
for (uint i = 0; i < this->triangles.size(); i++) {
|
||||
uint a = i*3;
|
||||
vector<uint> v = this->triangles[i].getVertices();
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
elementArray[a+j] = vertexMap.find(v[j]-1)->second - 1;
|
||||
}
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementArray),
|
||||
elementArray, GL_STATIC_DRAW);
|
||||
|
||||
|
||||
// setup the shaders
|
||||
GLuint shaderProgram = this->shader->getProgram();
|
||||
glUseProgram(shaderProgram);
|
||||
|
||||
// shader attributes
|
||||
uint offset = 0;
|
||||
GLint posAttrib = glGetAttribLocation(shaderProgram, "vPosition");
|
||||
glEnableVertexAttribArray(posAttrib);
|
||||
// (input, # of values, type, normalize, stride, offset)
|
||||
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE,
|
||||
this->elms*sizeof(float),
|
||||
(void*)(offset*sizeof(float)));
|
||||
offset += 3;
|
||||
|
||||
GLint normalAttrib = glGetAttribLocation(shaderProgram, "vNormal");
|
||||
glEnableVertexAttribArray(normalAttrib);
|
||||
glVertexAttribPointer(normalAttrib, 3, GL_FLOAT, GL_TRUE,
|
||||
this->elms*sizeof(float),
|
||||
(void*)(offset*sizeof(float)));
|
||||
offset += 3;
|
||||
|
||||
GLint ambientAttrib = glGetAttribLocation(shaderProgram,
|
||||
"ambientColor");
|
||||
glEnableVertexAttribArray(ambientAttrib);
|
||||
glVertexAttribPointer(ambientAttrib, 3, GL_FLOAT, GL_FALSE,
|
||||
this->elms*sizeof(float),
|
||||
(void*)(offset*sizeof(float)));
|
||||
offset += 3;
|
||||
|
||||
GLint diffuseAttrib = glGetAttribLocation(shaderProgram,
|
||||
"diffuseColor");
|
||||
glEnableVertexAttribArray(diffuseAttrib);
|
||||
glVertexAttribPointer(diffuseAttrib, 3, GL_FLOAT, GL_FALSE,
|
||||
this->elms*sizeof(float),
|
||||
(void*)(offset*sizeof(float)));
|
||||
offset += 3;
|
||||
|
||||
GLint specularAttrib = glGetAttribLocation(shaderProgram,
|
||||
"specularColor");
|
||||
glEnableVertexAttribArray(specularAttrib);
|
||||
glVertexAttribPointer(specularAttrib, 3, GL_FLOAT, GL_FALSE,
|
||||
this->elms*sizeof(float),
|
||||
(void*)(offset*sizeof(float)));
|
||||
offset += 3;
|
||||
|
||||
GLint shininessAttrib = glGetAttribLocation(shaderProgram,
|
||||
"shininess");
|
||||
glEnableVertexAttribArray(shininessAttrib);
|
||||
glVertexAttribPointer(shininessAttrib, 1, GL_FLOAT, GL_FALSE,
|
||||
this->elms*sizeof(float),
|
||||
(void*)(offset*sizeof(float)));
|
||||
offset += 1;
|
||||
}
|
||||
|
||||
GLuint Object::getVao() const {
|
||||
return this->vao;
|
||||
}
|
||||
|
||||
void Object::applyModelMatrix() const {
|
||||
GLint uniModel = glGetUniformLocation(this->shader->getProgram(),
|
||||
"model");
|
||||
glUniformMatrix4fv(uniModel, 1, GL_FALSE,
|
||||
glm::value_ptr(this->transformation));
|
||||
}
|
||||
|
||||
void Object::setTransform(glm::mat4 t) {
|
||||
this->transformation = t;
|
||||
}
|
||||
|
||||
glm::mat4 Object::getTransform() const {
|
||||
return this->transformation;
|
||||
}
|
||||
|
||||
void Object::setAmbientColor(glm::vec3 c) {
|
||||
this->ambient = c;
|
||||
}
|
||||
|
||||
void Object::setDiffuseColor(glm::vec3 c) {
|
||||
this->diffuse = c;
|
||||
}
|
||||
|
||||
void Object::setSpecularColor(glm::vec3 c) {
|
||||
this->specular = c;
|
||||
}
|
||||
|
||||
void Object::setShininess(float s) {
|
||||
this->shininess = s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This outputToObj function was part a school project on Bezier
|
||||
Surfaces, so I kept it in here just because. Kinda useless for this
|
||||
program though...
|
||||
*/
|
||||
void Object::outputToObj(string filename) const {
|
||||
ofstream file;
|
||||
file.open(filename.c_str());
|
||||
file << "# " << filename
|
||||
<< "\n\n";
|
||||
|
||||
file << "# vertices: should have " << this->vertices.size() << "\n";
|
||||
// vertices
|
||||
for (uint i = 0; i < this->vertices.size(); i++) {
|
||||
glm::vec3 vert = this->vertices[i];
|
||||
file << "v "
|
||||
<< vert[0] << " " << vert[1] << " " << vert[2] << " " << "\n";
|
||||
}
|
||||
|
||||
file << "\n\n\n";
|
||||
|
||||
file << "# vertex normals: " << this->vertexNormals.size() << "\n";
|
||||
// vertex normals
|
||||
for (uint i = 0; i < this->vertexNormals.size(); i++) {
|
||||
glm::vec3 vert = this->vertexNormals[i];
|
||||
file << "vn "
|
||||
<< vert[0] << " " << vert[1] << " " << vert[2] << " " << "\n";
|
||||
}
|
||||
|
||||
file << "\n\n\n";
|
||||
|
||||
file << "# triangle faces: should have " << this->triangles.size()
|
||||
<< "\n";
|
||||
// faces
|
||||
for (uint i = 0; i < this->triangles.size(); i++) {
|
||||
vector<uint> v = this->triangles[i].getVertices();
|
||||
vector<uint> vn = this->triangles[i].getVertexNormals();
|
||||
file << "f "
|
||||
<< v[0] << "//" << vn[0] << " "
|
||||
<< v[1] << "//" << vn[1] << " "
|
||||
<< v[2] << "//" << vn[2] << "\n";
|
||||
}
|
||||
|
||||
file << "\n\n# May the Llamas spit upon ye.";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Private
|
||||
*/
|
||||
|
||||
int Object::parseOBJVertex(string s) const {
|
||||
string split = "/";
|
||||
int slash = s.find(split);
|
||||
if (!slash) {
|
||||
return atoi(s.c_str());
|
||||
}
|
||||
string v = s.substr(0,slash);
|
||||
return atoi(v.c_str());
|
||||
}
|
||||
|
||||
int Object::parseOBJVertexNormal(string s) const {
|
||||
string split = "//";
|
||||
int slashes = s.find(split);
|
||||
if (!slashes) {
|
||||
return -1;
|
||||
}
|
||||
string n = s.substr(slashes + split.length());
|
||||
return atoi(n.c_str());
|
||||
}
|
||||
|
||||
glm::vec3 Object::surfaceNormal(Triangle t) const {
|
||||
vector<uint> v = t.getVertices();
|
||||
glm::vec3 a = this->vertices[v[0]];
|
||||
glm::vec3 b = this->vertices[v[1]];
|
||||
glm::vec3 c = this->vertices[v[2]];
|
||||
|
||||
glm::vec3 p = a - b;
|
||||
glm::vec3 q = a - c;
|
||||
|
||||
return glm::cross(p,q);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
Object - a storage class for a .obj file
|
||||
|
||||
Uses Triangle.h to keep track of faces.
|
||||
Keeps a list of vertices and vertex normals here in the Object.
|
||||
|
||||
Shader attribute order in the Vertex Array:
|
||||
(number of values in parentheses)
|
||||
position 3
|
||||
normal 3
|
||||
ambient 3
|
||||
diffuse 3
|
||||
specular 3
|
||||
shininess 1
|
||||
*/
|
||||
|
||||
#ifndef OBJECT_H
|
||||
#define OBJECT_H
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "Triangle.h"
|
||||
#include "Shader.h"
|
||||
#include "utilities.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Object {
|
||||
public:
|
||||
Object();
|
||||
Object(string filename, Shader* s);
|
||||
|
||||
void outputToObj(string filename) const;
|
||||
void parseObjectFile(string filename);
|
||||
|
||||
void glDraw();
|
||||
void setShader(Shader* shader);
|
||||
void openglInitialization();
|
||||
GLuint getVao() const;
|
||||
|
||||
glm::mat4 getTransform() const;
|
||||
void setTransform(glm::mat4 t);
|
||||
void applyModelMatrix() const;
|
||||
|
||||
void setAmbientColor(glm::vec3 c);
|
||||
void setDiffuseColor(glm::vec3 c);
|
||||
void setSpecularColor(glm::vec3 c);
|
||||
void setShininess(float s);
|
||||
|
||||
private:
|
||||
vector<Triangle> triangles;
|
||||
vector<glm::vec3> vertices;
|
||||
vector<glm::vec3> vertexNormals;
|
||||
glm::mat4 transformation;
|
||||
Shader* shader;
|
||||
GLuint vao;
|
||||
|
||||
// shader elements
|
||||
uint elms; // total number of elements per vertex
|
||||
glm::vec3 ambient;
|
||||
glm::vec3 diffuse;
|
||||
glm::vec3 specular;
|
||||
float shininess;
|
||||
|
||||
int init(string filename, Shader* s);
|
||||
|
||||
int parseOBJVertex(string s) const;
|
||||
int parseOBJVertexNormal(string s) const;
|
||||
|
||||
glm::vec3 surfaceNormal(Triangle t) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
Shader - a storage class for the Vertex and Fragment Shader
|
||||
*/
|
||||
|
||||
#include "Shader.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int Shader::init(string vertFile, string fragFile) {
|
||||
GLint successful = GL_TRUE;
|
||||
string vertStr = this->loadSource(vertFile);
|
||||
string fragStr = this->loadSource(fragFile);
|
||||
const char* vertSource = vertStr.c_str();
|
||||
const char* fragSource = fragStr.c_str();
|
||||
|
||||
// create the shaders
|
||||
this->vert = glCreateShader(GL_VERTEX_SHADER);
|
||||
this->frag = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
// give opengl the sources
|
||||
glShaderSource(this->vert, 1, &vertSource, NULL);
|
||||
glShaderSource(this->frag, 1, &fragSource, NULL);
|
||||
|
||||
// compile them
|
||||
glCompileShader(this->vert);
|
||||
glCompileShader(this->frag);
|
||||
|
||||
// check for errors
|
||||
GLint status;
|
||||
glGetShaderiv(this->vert, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
cerr << "Failed to compile the vertex shader\n\n";
|
||||
char buffer[512];
|
||||
glGetShaderInfoLog(this->vert, 512, NULL, buffer);
|
||||
cerr << buffer << "\n\n";
|
||||
successful = status;
|
||||
}
|
||||
status = GL_FALSE;
|
||||
glGetShaderiv(this->frag, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
cerr << "Failed to compile the fragment shader\n\n";
|
||||
char buffer[512];
|
||||
glGetShaderInfoLog(this->frag, 512, NULL, buffer);
|
||||
cerr << buffer << "\n\n";
|
||||
successful = status;
|
||||
}
|
||||
|
||||
GLuint shaderProgram = glCreateProgram();
|
||||
this->program = shaderProgram;
|
||||
|
||||
glAttachShader(shaderProgram, this->vert);
|
||||
glAttachShader(shaderProgram, this->frag);
|
||||
|
||||
// links up with the variable "outColor" in the shader source
|
||||
glBindFragDataLocation(shaderProgram, 0, "outColor");
|
||||
|
||||
glLinkProgram(shaderProgram);
|
||||
glUseProgram(shaderProgram);
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
Shader::Shader(string vertFile, string fragFile) {
|
||||
init(vertFile, fragFile);
|
||||
}
|
||||
|
||||
Shader::Shader() {
|
||||
this->vert = -1;
|
||||
this->frag = -1;
|
||||
this->program = -1;
|
||||
}
|
||||
|
||||
GLuint Shader::getVert() const {
|
||||
return this->vert;
|
||||
}
|
||||
|
||||
GLuint Shader::getFrag() const {
|
||||
return this->frag;
|
||||
}
|
||||
|
||||
GLuint Shader::getProgram() const {
|
||||
return this->program;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Private
|
||||
*/
|
||||
string Shader::loadSource(string file) {
|
||||
ifstream shaderFile (file.c_str());
|
||||
|
||||
string line;
|
||||
stringstream ss;
|
||||
if (shaderFile.is_open()) {
|
||||
while (getline(shaderFile, line)) {
|
||||
ss << line << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
Shader - a storage class for an OpenGL shader
|
||||
*/
|
||||
#ifndef SHADER_H
|
||||
#define SHADER_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Shader {
|
||||
public:
|
||||
Shader();
|
||||
Shader(string vertFile, string fragFile);
|
||||
GLuint getVert() const;
|
||||
GLuint getFrag() const;
|
||||
GLuint getProgram() const;
|
||||
|
||||
private:
|
||||
GLuint vert,frag,program;
|
||||
|
||||
int init(string vertFile, string fragFile);
|
||||
string loadSource(string file);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
SimpleTriangleTest - a simple test case to make sure everything
|
||||
is working correctly. Draws a rectangle using 2 triangles.
|
||||
*/
|
||||
|
||||
#include "SimpleTriangleTest.h"
|
||||
|
||||
SimpleTriangleTest::SimpleTriangleTest() {
|
||||
|
||||
}
|
||||
|
||||
void SimpleTriangleTest::initialize(Shader* s) {
|
||||
GLuint shaderProgram = s->getProgram();
|
||||
|
||||
GLuint vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
GLuint vbo;
|
||||
glGenBuffers(1, &vbo);
|
||||
|
||||
GLfloat vertices[] = {
|
||||
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // Top-left
|
||||
0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Top-right
|
||||
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, // Bottom-right
|
||||
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f // Bottom-left
|
||||
};
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
GLuint ebo;
|
||||
glGenBuffers(1, &ebo);
|
||||
|
||||
GLuint elements[] = {
|
||||
0, 1, 2,
|
||||
2, 3, 0
|
||||
};
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements),
|
||||
elements, GL_STATIC_DRAW);
|
||||
|
||||
glUseProgram(shaderProgram);
|
||||
|
||||
GLint posAttrib = glGetAttribLocation(shaderProgram, "vPosition");
|
||||
glEnableVertexAttribArray(posAttrib);
|
||||
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE,
|
||||
6*sizeof(GLfloat), 0);
|
||||
|
||||
GLint color = glGetAttribLocation(shaderProgram, "diffuseColor");
|
||||
glEnableVertexAttribArray(color);
|
||||
glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE,
|
||||
6*sizeof(GLfloat), (void*)(3*sizeof(GLfloat)));
|
||||
|
||||
}
|
||||
|
||||
void SimpleTriangleTest::glDraw() {
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
SimpleTriangleTest - a simple test case to make sure everything
|
||||
is working correctly. Draws a rectangle using 2 triangles.
|
||||
*/
|
||||
|
||||
#ifndef SIMPLETRIANGLETEST_H
|
||||
#define SIMPLETRIANGLETEST_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "Shader.h"
|
||||
|
||||
class SimpleTriangleTest {
|
||||
public:
|
||||
SimpleTriangleTest ();
|
||||
void initialize(Shader* s);
|
||||
void glDraw();
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
Triangle - a storage class for a triangle face from a .obj file
|
||||
*/
|
||||
|
||||
#include "Triangle.h"
|
||||
|
||||
int Triangle::init(uint a, uint b, uint c,
|
||||
uint an, uint bn, uint cn) {
|
||||
std::vector<uint> v, vn;
|
||||
|
||||
// vertex indices
|
||||
v.push_back(a);
|
||||
v.push_back(b);
|
||||
v.push_back(c);
|
||||
// vertex normal indices
|
||||
vn.push_back(an);
|
||||
vn.push_back(bn);
|
||||
vn.push_back(cn);
|
||||
|
||||
this->vertices = v;
|
||||
this->vertexNormals = vn;
|
||||
|
||||
this->elementWasSet = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Triangle::Triangle() {
|
||||
init(0,0,0,0,0,0);
|
||||
}
|
||||
|
||||
Triangle::Triangle(uint a, uint b, uint c,
|
||||
uint an, uint bn, uint cn) {
|
||||
init(a,b,c,an,bn,cn);
|
||||
}
|
||||
|
||||
Triangle::Triangle(uint a, uint b, uint c) {
|
||||
init(a,b,c,0,0,0);
|
||||
}
|
||||
|
||||
std::vector<uint> Triangle::getVertices() const {
|
||||
return this->vertices;
|
||||
}
|
||||
|
||||
std::vector<uint> Triangle::getVertexNormals() const {
|
||||
return this->vertexNormals;
|
||||
}
|
||||
|
||||
void Triangle::setElementBase(uint e) {
|
||||
this->element = e;
|
||||
this->elementWasSet = true;
|
||||
}
|
||||
|
||||
uint Triangle::getElementBase() const {
|
||||
return this->element;
|
||||
}
|
||||
|
||||
bool Triangle::elementIsSet() const {
|
||||
return this->elementWasSet;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
Triangle - a storage class for a triangle
|
||||
*/
|
||||
|
||||
#ifndef TRIANGLE_H
|
||||
#define TRIANGLE_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
class Triangle {
|
||||
public:
|
||||
Triangle();
|
||||
Triangle(uint a, uint b, uint c,
|
||||
uint an, uint bn, uint cn);
|
||||
Triangle(uint a, uint b, uint c);
|
||||
|
||||
std::vector<uint> getVertices() const;
|
||||
std::vector<uint> getVertexNormals() const;
|
||||
|
||||
void setElementBase(uint e);
|
||||
uint getElementBase() const;
|
||||
bool elementIsSet() const;
|
||||
|
||||
private:
|
||||
std::vector<uint> vertices, vertexNormals;
|
||||
|
||||
// This is the element index for the first vertex.
|
||||
// The other two are e+1 and e+2 respectively
|
||||
uint element;
|
||||
bool elementWasSet;
|
||||
|
||||
int init(uint a, uint b, uint c,
|
||||
uint an, uint bn, uint cn);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,238 @@
|
|||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Shader.h"
|
||||
#include "Object.h"
|
||||
#include "utilities.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
Some global storage classes
|
||||
*/
|
||||
class Viewport {
|
||||
public:
|
||||
uint width, height;
|
||||
float fov, near, far;
|
||||
};
|
||||
Viewport viewport;
|
||||
|
||||
class Globals {
|
||||
public:
|
||||
vector<Object> objects;
|
||||
Camera camera;
|
||||
float translate_step, rotate_step;
|
||||
GLFWwindow* window;
|
||||
Shader shader;
|
||||
};
|
||||
Globals globals;
|
||||
|
||||
/**
|
||||
and the global initializations
|
||||
*/
|
||||
void initGlobals() {
|
||||
// viewport
|
||||
viewport.width = 800;
|
||||
viewport.height = 600;
|
||||
viewport.near = 0.1f;
|
||||
viewport.far = 100;
|
||||
viewport.fov = 45.0f;
|
||||
|
||||
// globals
|
||||
globals.translate_step = 0.05f;
|
||||
globals.rotate_step = 0.01f;
|
||||
}
|
||||
|
||||
// pre-declaration
|
||||
void updateViewMatrix();
|
||||
|
||||
void drawScene() {
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
updateViewMatrix();
|
||||
|
||||
for (uint i = 0; i < globals.objects.size(); i++) {
|
||||
globals.objects[i].glDraw();
|
||||
}
|
||||
}
|
||||
|
||||
void updateViewMatrix() {
|
||||
GLuint shaderProgram = globals.shader.getProgram();
|
||||
glm::mat4 view = glm::lookAt
|
||||
(globals.camera.getPosition(),
|
||||
globals.camera.getTarget(), // the position to look at
|
||||
globals.camera.getUpDir());
|
||||
GLint uniView = glGetUniformLocation(shaderProgram, "view");
|
||||
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));
|
||||
}
|
||||
|
||||
void initializeMatrices() {
|
||||
GLuint shaderProgram = globals.shader.getProgram();
|
||||
|
||||
glm::mat4 model;
|
||||
// example
|
||||
//model = glm::rotate(model, PI, glm::vec3(0.0f,0.0f,1.0f));
|
||||
|
||||
GLint uniModel = glGetUniformLocation(shaderProgram, "model");
|
||||
// (var, # of matrices, transpose, matrix as an array)
|
||||
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
|
||||
|
||||
glm::mat4 view = glm::lookAt
|
||||
(globals.camera.getPosition(),
|
||||
globals.camera.getTarget(), // the position to look at
|
||||
globals.camera.getUpDir());
|
||||
GLint uniView = glGetUniformLocation(shaderProgram, "view");
|
||||
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));
|
||||
|
||||
glm::mat4 proj =
|
||||
glm::perspective(viewport.fov,1.0f*viewport.width/viewport.height,
|
||||
viewport.near, viewport.far);
|
||||
GLint uniProj = glGetUniformLocation(shaderProgram, "proj");
|
||||
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void moveCamera() {
|
||||
float r = globals.rotate_step;
|
||||
float t = globals.translate_step;
|
||||
glm::vec3 up = globals.camera.getUpDir();
|
||||
glm::vec3 forward = globals.camera.getViewDir();
|
||||
glm::vec3 right = glm::cross(forward,up);
|
||||
|
||||
// rotation
|
||||
if (glfwGetKey(globals.window, 'J') == GLFW_PRESS) {
|
||||
globals.camera.rotate(r*up);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'L') == GLFW_PRESS) {
|
||||
globals.camera.rotate(-r*up);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'I') == GLFW_PRESS) {
|
||||
globals.camera.rotate(r*right);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'K') == GLFW_PRESS) {
|
||||
globals.camera.rotate(-r*right);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'U') == GLFW_PRESS) {
|
||||
globals.camera.rotate(-r*forward);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'O') == GLFW_PRESS) {
|
||||
globals.camera.rotate(r*forward);
|
||||
}
|
||||
|
||||
// translation
|
||||
if (glfwGetKey(globals.window, 'A') == GLFW_PRESS) {
|
||||
globals.camera.translate(-t*right);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'D') == GLFW_PRESS) {
|
||||
globals.camera.translate(t*right);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'W') == GLFW_PRESS) {
|
||||
globals.camera.translate(t*forward);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'S') == GLFW_PRESS) {
|
||||
globals.camera.translate(-t*forward);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'Q') == GLFW_PRESS) {
|
||||
globals.camera.translate(t*up);
|
||||
}
|
||||
if (glfwGetKey(globals.window, 'E') == GLFW_PRESS) {
|
||||
globals.camera.translate(-t*up);
|
||||
}
|
||||
}
|
||||
|
||||
GLFWwindow* initializeGlfw() {
|
||||
/**
|
||||
Basic GLFW initialization for OpenGL 3.2+ only
|
||||
with no backwards compatibility.
|
||||
*/
|
||||
glfwInit();
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
// windowed
|
||||
GLFWwindow* window =
|
||||
glfwCreateWindow(viewport.width, viewport.height,
|
||||
"Object Loader", NULL, NULL);
|
||||
|
||||
// fullscreen
|
||||
/*GLFWwindow* window =
|
||||
glfwCreateWindow(800, 600, "OpenGL",
|
||||
glfwGetPrimaryMonitor(), NULL); */
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
return window;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// initialize the global settings
|
||||
initGlobals();
|
||||
|
||||
// set up GLFW
|
||||
GLFWwindow* window = initializeGlfw();
|
||||
globals.window = window;
|
||||
|
||||
// GLEW setup
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// everything currently uses the same shader
|
||||
Shader shader ("shaders/vertexShader.c", "shaders/fragmentShader.c");
|
||||
globals.shader = shader;
|
||||
|
||||
// parse args
|
||||
int i;
|
||||
for (i = 1; i < argc; i++) {
|
||||
string s (argv[i]);
|
||||
Object obj (s, &globals.shader);
|
||||
globals.objects.push_back(obj);
|
||||
}
|
||||
i--;
|
||||
cout << "Loaded " << i << " ";
|
||||
if (i > 1) {
|
||||
cout << "objects ";
|
||||
} else {
|
||||
cout << "object ";
|
||||
}
|
||||
cout << "successfully\n";
|
||||
|
||||
initializeMatrices();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
/**
|
||||
the main, infinite loop
|
||||
*/
|
||||
while(!glfwWindowShouldClose(window)) {
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
|
||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
cout << "Quitting\n\n";
|
||||
}
|
||||
|
||||
moveCamera();
|
||||
drawScene();
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
utilities - extra functions that didn't really belong
|
||||
inside of a class or the main file.
|
||||
*/
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void printGlmMat4(glm::mat4 m) {
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
for (uint j = 0; j < 4; j++) {
|
||||
cout << m[i][j] << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
void printGlmVec3(glm::vec3 v) {
|
||||
for (uint i = 0; i < 3; i++) {
|
||||
cout << v[i] << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
utilities - extra functions that didn't really belong
|
||||
inside of a class or the main file.
|
||||
*/
|
||||
|
||||
#ifndef UTILITIES_H
|
||||
#define UTILITIES_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void printGlmMat4(glm::mat4 m);
|
||||
void printGlmVec3(glm::vec3 v);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue