Compare commits

..

No commits in common. "master" and "v1.0" have entirely different histories.
master ... v1.0

16 changed files with 319 additions and 408 deletions

14
.gitmodules vendored
View File

@ -1,9 +1,9 @@
[submodule "wfobj"]
path = wfobj
url = ../util/wfobj.git
[submodule "loadTexture"]
path = loadTexture
url = ../util/loadTexture.git
[submodule "glslUtil"]
path = glslUtil
url = ../util/glslUtil.git
url = ../wfobj.git
[submodule "FileLoader"]
path = FileLoader
url = ../FileLoader.git
[submodule "TextureLoader"]
path = TextureLoader
url = ../TextureLoader.git

1
FileLoader Submodule

@ -0,0 +1 @@
Subproject commit 8abf3ff02b6a8cc7024006a9379fd7e8b07cd4a6

View File

@ -1,8 +1,39 @@
export SCONSFLAGS := -Q
WINCHECK := $(shell which msys-1.0.dll >/dev/null 2>&1; if [ $$? -eq 0 ]; then echo MSYS; fi)
ifeq ($(strip $(WINCHECK)),)
WINDOWS := 0
else
WINDOWS := 1
endif
all:
@scons
ifeq ($(WINDOWS),1)
GLLIBS := -lopengl32 -lglu32
WINDOWSLIBS := -lmingw32
else
GLLIBS := -lGL -lGLU
endif
export CXXFLAGS := -O2 $(shell sdl-config --cflags) -I$(CURDIR)
LDFLAGS := $(GLLIBS) $(WINDOWSLIBS) $(shell sdl-config --libs) -lSDL_image
TARGET := wfobj-view
.PHONY: all clean TextureCache wfobj
all: $(TARGET)
$(TARGET): $(TARGET).o TextureCache wfobj
$(CXX) -o $(TARGET) $< TextureCache/TextureCache.o wfobj/WFObj.o $(LDFLAGS)
%.o: %.cc
$(CXX) -c -o $@ $< $(CXXFLAGS)
TextureCache:
make -C TextureCache
wfobj:
make -C wfobj
clean:
@scons -c
make -C TextureCache clean
make -C wfobj clean
-rm -f *.o *~ $(TARGET)

View File

@ -1,17 +0,0 @@
# vim:filetype=python
import os
import sys
env = Environment(LIBS = ['GL', 'GLU', 'SDL_image'],
CFLAGS = ['-Wall', '-DGL_GLEXT_PROTOTYPES'],
CXXFLAGS = ['-Wall', '-DGL_GLEXT_PROTOTYPES'])
env.ParseConfig('sdl-config --cflags --libs')
sources = [Glob('*.cc'), Glob('wfobj/WFObj.cc'), Glob('loadTexture/*.c'),
Glob('glslUtil/*.c')]
env.Program('wfobj-view', sources)
if len(os.listdir('wfobj')) == 0:
sys.stderr.write('Warning: wfobj submodule not initialized\n')
sys.stderr.write('Warning: perhaps you should run `git submodule update --init`\n')

12
TextureCache/Makefile Normal file
View File

@ -0,0 +1,12 @@
CXX := g++
CXXFLAGS ?= -O2
OBJS := TextureCache.o
all: $(OBJS)
%.o: %.cc %.hh
$(CXX) -c -o $@ $< $(CXXFLAGS)
clean:
-rm -f *~ *.o

View File

@ -0,0 +1,94 @@
#include <SDL.h>
#include <SDL_image.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <iostream>
#include "TextureCache.h"
using namespace std;
GLuint TextureCache::load(const string & filename)
{
map<string,GLuint>::iterator it = m_cache.find(filename);
if (it != m_cache.end())
return it->second;
GLuint tex = loadTexture(filename.c_str());
m_cache[filename] = tex;
return tex;
}
GLuint TextureCache::loadTexture(const char * filename,
bool mipmaps,
int mode,
int quality)
{
GLuint texture;
SDL_Surface * temp = IMG_Load(filename);
if (!temp)
{
cerr << "Failed to load image '" << filename << "'!" << endl;
return 0;
}
SDL_PixelFormat fmt;
fmt.palette = NULL;
fmt.BitsPerPixel = 32;
fmt.BytesPerPixel = 4;
fmt.Rmask = 0x000000FF;
fmt.Gmask = 0x0000FF00;
fmt.Bmask = 0x00FF0000;
fmt.Amask = 0xFF000000;
fmt.Rshift = 0;
fmt.Gshift = 8;
fmt.Bshift = 16;
fmt.Ashift = 24;
SDL_Surface * texsurf = SDL_ConvertSurface(temp, &fmt, SDL_SWSURFACE);
SDL_FreeSurface(temp);
if (!texsurf)
{
cerr << '\'' << filename << "' was not converted properly!" << endl;
return 0;
}
unsigned int * pixels = new unsigned int[texsurf->w * texsurf->h];
int y;
unsigned int dstOffset = texsurf->w * (texsurf->h - 1);
unsigned int srcOffset = 0;
for (y = 0; y < texsurf->h; y++)
{
memcpy(pixels + dstOffset,
((unsigned int *)texsurf->pixels) + srcOffset,
texsurf->w << 2);
dstOffset -= texsurf->w;
srcOffset += texsurf->w;
}
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, 4, texsurf->w, texsurf->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pixels);
if (quality > 0)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
mipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
mipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
}
else
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
mipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
mipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
}
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
if (mipmaps)
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,
texsurf->w, texsurf->h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
SDL_FreeSurface(texsurf);
delete[] pixels;
return texture;
}

View File

@ -0,0 +1,20 @@
#include <GL/gl.h>
#include <map>
#include <string>
class TextureCache
{
public:
GLuint load(const std::string & filename);
private:
/* methods */
GLuint loadTexture(const char * filename,
bool mipmaps = false,
int mode = GL_DECAL,
int quality = 1);
/* data */
std::map< std::string, GLuint > m_cache;
};

1
TextureLoader Submodule

@ -0,0 +1 @@
Subproject commit 9855d3e577208d7c1ebc73f31489c7da9d6f7d07

View File

@ -1,33 +0,0 @@
uniform vec4 ambient, diffuse, specular;
uniform float shininess;
varying vec3 pos_i;
varying vec3 normal_i;
void main(void)
{
vec3 n, lightDir;
vec4 color;
float NdotL, RdotEye;
lightDir = normalize(vec3(-0.1, 0, -0.9));
color = vec4(0.2, 0.2, 0.2, 1.0) * ambient; /* ambient light */
n = normalize(normal_i);
NdotL = max(dot(n, -lightDir), 0.0);
if (NdotL > 0.0)
{
/* diffuse component */
color += diffuse * NdotL;
/* specular component */
RdotEye = dot(normalize(-pos_i), normalize(reflect(-lightDir, n)));
if (RdotEye > 0.0)
{
color += clamp(specular * pow(RdotEye, shininess), 0.0, 1.0);
}
}
gl_FragColor = color;
}

View File

@ -1,35 +0,0 @@
uniform vec4 ambient, specular;
uniform float shininess;
uniform sampler2D tex;
varying vec3 pos_i;
varying vec3 normal_i;
varying vec2 tex_coord_i;
void main(void)
{
vec3 n, lightDir;
vec4 color;
float NdotL, RdotEye;
lightDir = normalize(vec3(-0.1, 0, -0.9));
color = vec4(0.2, 0.2, 0.2, 1.0) * ambient; /* ambient light */
n = normalize(normal_i);
NdotL = max(dot(n, -lightDir), 0.0);
if (NdotL > 0.0)
{
/* diffuse component */
color += texture2D(tex, tex_coord_i) * NdotL;
/* specular component */
RdotEye = dot(normalize(-pos_i), normalize(reflect(-lightDir, n)));
if (RdotEye > 0.0)
{
color += clamp(specular * pow(RdotEye, shininess), 0.0, 1.0);
}
}
gl_FragColor = color;
}

@ -1 +0,0 @@
Subproject commit 060f3115bf0f1f659dd44ef3738c12327ec2ef43

@ -1 +0,0 @@
Subproject commit 87b5ff86910cc947fda91b271fa62b5b9276311d

View File

@ -1,13 +0,0 @@
attribute vec3 pos;
attribute vec3 normal;
varying vec3 pos_i;
varying vec3 normal_i;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1);
pos_i = gl_Position.xyz;
normal_i = gl_NormalMatrix * normal;
}

View File

@ -1,16 +0,0 @@
attribute vec3 pos;
attribute vec3 normal;
attribute vec2 tex_coord;
varying vec3 pos_i;
varying vec3 normal_i;
varying vec2 tex_coord_i;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1);
pos_i = gl_Position.xyz;
tex_coord_i = tex_coord;
normal_i = gl_NormalMatrix * normal;
}

2
wfobj

@ -1 +1 @@
Subproject commit 1ecc6d749be3bc3f5dc0de230b5e8e3ca079377a
Subproject commit d06888128c5a645a8815cb86bb4b3dfe1c76f454

View File

@ -1,15 +1,11 @@
/* Libraries we use */
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <iostream>
#include "wfobj/WFObj.h"
#include "loadTexture/loadTexture.h"
#include "glslUtil/glslUtil.h"
#include "TextureCache/TextureCache.h"
using namespace std;
/* Some definitions */
@ -17,316 +13,188 @@ using namespace std;
#define HEIGHT 800
#define TITLE "Josh's Wavefront Object Viewer"
enum Locations {
LOC_POSITION,
LOC_NORMAL,
LOC_TEXTURE
TextureCache textureCache;
class LoadTexture : public TextureLoader
{
public:
GLuint load(const FileLoader::Path & path,
FileLoader & fl, bool mipmaps, int mode, int quality)
{
return textureCache.load(path.fullPath);
}
};
class Viewer
{
public:
Viewer(const char * filename);
void run();
Viewer(const char * filename);
void run();
private:
void initgl();
void display();
void setProjection();
void initgl();
void display();
void setProjection();
WFObj m_obj;
GLuint m_list;
float m_rotationMatrix[16];
int m_startx, m_starty;
bool m_dragging;
float m_dist;
GLuint m_program, m_tex_program;
GLint m_ambient_loc, m_diffuse_loc, m_specular_loc, m_shininess_loc;
GLint m_tex_ambient_loc, m_tex_specular_loc, m_tex_shininess_loc,
m_tex_tex_loc;
GLuint m_list;
float m_rotationMatrix[16];
int m_startx, m_starty;
bool m_dragging;
float m_dist;
};
static GLuint load_texture(const char *fname)
{
GLuint id = loadTexture(fname);
if (id != 0)
{
int width, height;
glBindTexture(GL_TEXTURE_2D, id);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
char *data = (char *) malloc(4 * width * height);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA,
GL_UNSIGNED_BYTE, data);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
free(data);
}
return id;
}
/* The program's main entry point */
int main(int argc, char * argv[])
int main(int argc, char * argv[])
{
if (argc < 2)
{
cerr << "Usage: " << argv[0] << " <filename>" << endl;
return -1;
}
if (argc < 2)
{
cerr << "Usage: " << argv[0] << " <filename>" << endl;
return -1;
}
if (SDL_Init(SDL_INIT_VIDEO))
{
printf("Failed to initialize SDL!\n");
return -2;
}
if (SDL_Init(SDL_INIT_VIDEO))
{
printf("Failed to initialize SDL!\n");
return -2;
}
atexit(SDL_Quit);
atexit(SDL_Quit);
SDL_Surface * screen;
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if (!(screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_OPENGL)))
{
printf("Failed to set video mode!\n");
SDL_Quit();
return -3;
}
SDL_WM_SetCaption(TITLE, TITLE);
SDL_Surface * screen;
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if (!(screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_OPENGL)))
{
printf("Failed to set video mode!\n");
SDL_Quit();
return -3;
}
SDL_WM_SetCaption(TITLE, TITLE);
Viewer v(argv[1]);
v.run();
Viewer v(argv[1]);
v.run();
return 0;
return 0;
}
Viewer::Viewer(const char * filename)
{
m_dist = 5.0;
m_dragging = false;
if (!m_obj.load(filename, NULL, load_texture))
{
cerr << "Error loading " << filename << endl;
exit(1);
}
const static guAttribBinding bindings[] = {
{LOC_POSITION, "pos"},
{LOC_NORMAL, "normal"},
{0, NULL}
};
m_program = guMakeProgramFromFiles("v_shader.glsl", "f_shader.glsl",
bindings);
const static guAttribBinding tex_bindings[] = {
{LOC_POSITION, "pos"},
{LOC_NORMAL, "normal"},
{LOC_TEXTURE, "tex_coord"},
{0, NULL}
};
m_tex_program = guMakeProgramFromFiles("v_tex_shader.glsl",
"f_tex_shader.glsl", tex_bindings);
if (m_program == 0 || m_tex_program == 0)
{
exit(1);
}
guUniformLocation uniforms[] = {
{&m_ambient_loc, "ambient"},
{&m_diffuse_loc, "diffuse"},
{&m_specular_loc, "specular"},
{&m_shininess_loc, "shininess"},
{NULL, NULL}
};
guGetUniformLocations(m_program, uniforms);
guUniformLocation tex_uniforms[] = {
{&m_tex_ambient_loc, "ambient"},
{&m_tex_specular_loc, "specular"},
{&m_tex_shininess_loc, "shininess"},
{&m_tex_tex_loc, "tex"},
{NULL, NULL}
};
guGetUniformLocations(m_tex_program, tex_uniforms);
glUseProgram(m_program);
glUniform4f(m_ambient_loc, 0.2, 0.2, 0.2, 1.0);
glUniform4f(m_diffuse_loc, 1.0, 1.0, 1.0, 1.0);
glUniform4f(m_specular_loc, 1.0, 1.0, 1.0, 1.0);
glUniform1f(m_shininess_loc, 85.0);
glUseProgram(m_tex_program);
glUniform4f(m_tex_ambient_loc, 0.2, 0.2, 0.2, 1.0);
glUniform4f(m_tex_specular_loc, 1.0, 1.0, 1.0, 1.0);
glUniform1f(m_tex_shininess_loc, 85.0);
/* Print out the object's size */
const float * aabb = m_obj.getAABB();
cout << "Object width: " << (aabb[3]-aabb[0]) << endl;
cout << "Object depth: " << (aabb[4]-aabb[1]) << endl;
cout << "Object height: " << (aabb[5]-aabb[2]) << endl;
m_dist = 5.0;
m_dragging = false;
LoadTexture lt;
WFObj m_obj(lt);
m_obj.load(FileLoader::Path(filename, ""));
m_list = m_obj.render();
/* Print out the object's size */
const float * aabb = m_obj.getAABB();
cout << "Object width: " << (aabb[3]-aabb[0]) << endl;
cout << "Object depth: " << (aabb[4]-aabb[1]) << endl;
cout << "Object height: " << (aabb[5]-aabb[2]) << endl;
}
void Viewer::initgl()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, WIDTH, HEIGHT);
setProjection();
glLoadIdentity();
glGetFloatv(GL_MODELVIEW_MATRIX, m_rotationMatrix);
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_CULL_FACE);
glViewport(0, 0, WIDTH, HEIGHT);
setProjection();
glLoadIdentity();
glGetFloatv(GL_MODELVIEW_MATRIX, m_rotationMatrix);
// float pos[] = {0.0, -1.0, 0.0, 0.0};
// glLightfv(GL_LIGHT0, GL_POSITION, pos);
GLfloat lightAmbient[] = {0.2, 0.2, 0.2, 1};
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
}
void Viewer::setProjection()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)WIDTH/(GLfloat)WIDTH, 0.01, 10000.0);
// gluLookAt(0, m_dist, 0, 0, 0, 0, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)WIDTH/(GLfloat)WIDTH, 0.01, 10000.0);
// gluLookAt(0, m_dist, 0, 0, 0, 0, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
}
void Viewer::display()
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0, -m_dist, 0, 0, 0, 0, 0, 0, 1);
glMultMatrixf(m_rotationMatrix);
m_obj.bindBuffers();
GLuint program = m_program;
glUseProgram(m_program);
glEnableVertexAttribArray(LOC_POSITION);
glEnableVertexAttribArray(LOC_NORMAL);
int stride = m_obj.getStride();
glVertexAttribPointer(LOC_POSITION, 3, GL_FLOAT, GL_FALSE,
stride, (GLvoid *) m_obj.getVertexOffset());
glVertexAttribPointer(LOC_NORMAL, 3, GL_FLOAT, GL_FALSE,
stride, (GLvoid *) m_obj.getNormalOffset());
if (m_obj.doTextures())
{
glVertexAttribPointer(LOC_TEXTURE, 2, GL_FLOAT, GL_FALSE,
stride, (GLvoid *) m_obj.getTextureCoordOffset());
}
for (map<string, WFObj::Material>::iterator it =
m_obj.getMaterials().begin();
it != m_obj.getMaterials().end();
it++)
{
WFObj::Material & m = it->second;
if (m.flags & WFObj::Material::TEXTURE_BIT)
{
if (program != m_tex_program)
{
glUseProgram(m_tex_program);
program = m_tex_program;
glEnableVertexAttribArray(LOC_TEXTURE);
}
}
else
{
if (program != m_program)
{
glUseProgram(m_program);
program = m_program;
glDisableVertexAttribArray(LOC_TEXTURE);
}
}
if (m.flags & WFObj::Material::SHININESS_BIT)
{
if (program == m_tex_program)
glUniform1f(m_tex_shininess_loc, m.shininess);
else
glUniform1f(m_shininess_loc, m.shininess);
}
if (m.flags & WFObj::Material::AMBIENT_BIT)
{
if (program == m_tex_program)
glUniform4fv(m_tex_ambient_loc, 1, &m.ambient[0]);
else
glUniform4fv(m_ambient_loc, 1, &m.ambient[0]);
}
if (m.flags & WFObj::Material::DIFFUSE_BIT)
{
if (program != m_tex_program)
glUniform4fv(m_diffuse_loc, 1, &m.diffuse[0]);
}
if (m.flags & WFObj::Material::SPECULAR_BIT)
{
if (program == m_tex_program)
glUniform4fv(m_tex_specular_loc, 1, &m.specular[0]);
else
glUniform4fv(m_specular_loc, 1, &m.specular[0]);
}
glDrawElements(GL_TRIANGLES, m.num_vertices,
GL_UNSIGNED_SHORT,
(GLvoid *) (sizeof(GLushort) * m.first_vertex));
}
SDL_GL_SwapBuffers();
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0, -m_dist, 0, 0, 0, 0, 0, 0, 1);
glMultMatrixf(m_rotationMatrix);
if (m_list)
glCallList(m_list);
SDL_GL_SwapBuffers();
}
void Viewer::run()
{
initgl();
display();
SDL_Event event;
while (SDL_WaitEvent(&event))
{
if (event.type == SDL_QUIT)
break;
else if (event.type == SDL_KEYDOWN)
{
if (event.key.keysym.sym == SDLK_ESCAPE)
break;
if (event.key.keysym.sym == SDLK_q)
break;
}
else if (event.type == SDL_MOUSEBUTTONDOWN)
{
if (event.button.button == SDL_BUTTON_LEFT)
{
if (event.button.state == SDL_PRESSED)
{
m_dragging = true;
m_startx = event.button.x;
m_starty = event.button.y;
}
}
else if (event.button.button == 4)
{
m_dist *= 0.85;
if (m_dist < 1.0f)
m_dist = 1.0f;
setProjection();
display();
}
else if (event.button.button == 5)
{
m_dist *= 1.2;
setProjection();
display();
}
}
else if (event.type == SDL_MOUSEBUTTONUP)
{
if (event.button.button == SDL_BUTTON_LEFT)
{
m_dragging = false;
}
}
else if (event.type == SDL_MOUSEMOTION)
{
if (m_dragging)
{
glLoadIdentity();
glRotatef(event.motion.y - m_starty, 1, 0, 0);
glRotatef(event.motion.x - m_startx, 0, 0, 1);
glMultMatrixf(m_rotationMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX, m_rotationMatrix);
m_startx = event.motion.x;
m_starty = event.motion.y;
display();
}
}
}
initgl();
display();
SDL_Event event;
while (SDL_WaitEvent(&event))
{
if (event.type == SDL_QUIT)
break;
else if (event.type == SDL_KEYDOWN)
{
if (event.key.keysym.sym == SDLK_ESCAPE)
break;
if (event.key.keysym.sym == SDLK_q)
break;
}
else if (event.type == SDL_MOUSEBUTTONDOWN)
{
if (event.button.button == SDL_BUTTON_LEFT)
{
if (event.button.state == SDL_PRESSED)
{
m_dragging = true;
m_startx = event.button.x;
m_starty = event.button.y;
}
}
else if (event.button.button == 4)
{
m_dist *= 0.85;
if (m_dist < 1.0f)
m_dist = 1.0f;
setProjection();
display();
}
else if (event.button.button == 5)
{
m_dist *= 1.2;
setProjection();
display();
}
}
else if (event.type == SDL_MOUSEBUTTONUP)
{
if (event.button.button == SDL_BUTTON_LEFT)
{
m_dragging = false;
}
}
else if (event.type == SDL_MOUSEMOTION)
{
if (m_dragging)
{
glLoadIdentity();
glRotatef(event.motion.y - m_starty, 1, 0, 0);
glRotatef(event.motion.x - m_startx, 0, 0, 1);
glMultMatrixf(m_rotationMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX, m_rotationMatrix);
m_startx = event.motion.x;
m_starty = event.motion.y;
display();
}
}
}
}