summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--Makefile21
-rw-r--r--SConstruct22
-rw-r--r--bullet.cpp26
-rw-r--r--bullet.h20
-rw-r--r--bullet_fragment.glsl11
-rw-r--r--bullet_vertex.glsl14
-rw-r--r--foo.pngbin0 -> 1435 bytes
-rw-r--r--foo2.pngbin0 -> 1024 bytes
-rw-r--r--main.cpp287
-rw-r--r--shader.cpp91
-rw-r--r--shader.h51
-rw-r--r--texture.cpp29
-rw-r--r--texture.h14
-rw-r--r--texturesdl.cpp17
-rw-r--r--texturesdl.h8
-rw-r--r--vector.cpp47
-rw-r--r--vector.h36
18 files changed, 699 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8015c2e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.swp
+*.o
+.sconf_temp
+.sconsign.dblite
+config.log
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2e0fd63
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+CC = g++
+CFLAGS = -Wall -g $(shell sdl-config --cflags)
+LDFLAGS = $(shell sdl-config --libs) -lGL -lGLU# -lGLcore
+TARGET = foo
+OBJECTS = shader.o main.o
+
+all: $(TARGET)
+
+$(TARGET): $(SHADERHEADERS) $(OBJECTS)
+ $(CC) $(LDFLAGS) -o $@ $^
+
+main.o: $(SHADERHEADERS)
+
+%.o: %.cpp
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.o: %.cpp %.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+clean:
+ rm -f $(TARGET) $(OBJECTS) $(SHADERHEADERS)
diff --git a/SConstruct b/SConstruct
new file mode 100644
index 0000000..ce1b818
--- /dev/null
+++ b/SConstruct
@@ -0,0 +1,22 @@
+AddOption('--release', action = 'store_true')
+
+env = Environment()
+
+conf = Configure(env)
+for lib in ('GL', 'GLU', 'SDL', 'SDL_image'):
+ if not conf.CheckLib(lib):
+ print 'Could not find %s' % lib
+ Exit(1)
+env = conf.Finish()
+
+if GetOption('release'):
+ env.Append(CCFLAGS = ['-O2'])
+else:
+ env.Append(CCFLAGS = ['-Wall', '-g'])
+
+env.ParseConfig('sdl-config --cflags --libs')
+env.ParseConfig('pkg-config --cflags --libs ftgl')
+
+env.Program('foo', Glob('*.cpp'))
+
+# vim: syn=python
diff --git a/bullet.cpp b/bullet.cpp
new file mode 100644
index 0000000..b7df9fb
--- /dev/null
+++ b/bullet.cpp
@@ -0,0 +1,26 @@
+#include "bullet.h"
+
+Bullet::Bullet() {
+}
+
+Bullet::Bullet(const Vector3& pos, const Vector3& direction, float radius) {
+ this->pos = pos;
+ this->direction = direction;
+ this->radius = radius;
+}
+
+Bullet::Bullet(const Bullet& b) {
+ pos = b.pos;
+ direction = b.direction;
+ radius = b.radius;
+}
+
+Bullet& Bullet::operator=(const Bullet& b) {
+ pos = b.pos;
+ direction = b.direction;
+ radius = b.radius;
+ return *this;
+}
+
+Bullet::~Bullet() {
+}
diff --git a/bullet.h b/bullet.h
new file mode 100644
index 0000000..23a4a3f
--- /dev/null
+++ b/bullet.h
@@ -0,0 +1,20 @@
+#ifndef _BULLET_H_
+#define _BULLET_H_
+
+#include "vector.h"
+
+class Bullet {
+ public:
+ Vector3 pos;
+ Vector3 direction;
+ float radius;
+
+ Bullet();
+ Bullet(const Vector3& pos, const Vector3& direction, float radius);
+ Bullet(const Bullet& b);
+ ~Bullet();
+
+ Bullet& operator=(const Bullet& b);
+};
+
+#endif
diff --git a/bullet_fragment.glsl b/bullet_fragment.glsl
new file mode 100644
index 0000000..3bd7717
--- /dev/null
+++ b/bullet_fragment.glsl
@@ -0,0 +1,11 @@
+varying mat4 v_tex_rot;
+uniform sampler2D tex;
+
+void main() {
+ vec2 l_uv = gl_PointCoord;
+ const vec2 l_offset = vec2(0.5, 0.5);
+ l_uv -= l_offset;
+ l_uv = vec2(v_tex_rot * vec4(l_uv, 0.0, 1.0));
+ l_uv += l_offset;
+ gl_FragColor = vec4(texture2D(tex, l_uv)) * gl_Color;
+}
diff --git a/bullet_vertex.glsl b/bullet_vertex.glsl
new file mode 100644
index 0000000..0843be2
--- /dev/null
+++ b/bullet_vertex.glsl
@@ -0,0 +1,14 @@
+varying mat4 v_tex_rot;
+
+void main() {
+ vec4 l_position = gl_Vertex;
+ vec2 l_direction = normalize(vec2(l_position.z, l_position.w));
+ v_tex_rot = mat4(l_direction.x, l_direction.y, 0.0, 0.0,
+ -l_direction.y, l_direction.x, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+ l_position.z = 0.0;
+ l_position.w = 1.0;
+ gl_FrontColor = gl_Color;
+ gl_Position = gl_ModelViewProjectionMatrix * l_position;
+}
diff --git a/foo.png b/foo.png
new file mode 100644
index 0000000..c87d1f1
--- /dev/null
+++ b/foo.png
Binary files differ
diff --git a/foo2.png b/foo2.png
new file mode 100644
index 0000000..7673659
--- /dev/null
+++ b/foo2.png
Binary files differ
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..51ef1c2
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,287 @@
+#include <iostream>
+#include <fstream>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <math.h>
+#include <vector>
+#include <list>
+#include <queue>
+#include "SDL.h"
+#include <FTGL/ftgl.h>
+#include "texturesdl.h"
+#include "shader.h"
+#include "vector.h"
+#include "bullet.h"
+
+class BulletAdder {
+ public:
+ unsigned int time;
+ Bullet bullet;
+
+ BulletAdder(unsigned int time, Bullet bullet) { this->time = time; this->bullet = bullet; }
+
+ bool operator<(const BulletAdder& ba) {
+ return time < ba.time;
+ };
+};
+
+class BulletAdderComparison {
+ bool reverse;
+
+ public:
+ BulletAdderComparison(const bool& revparam = false) { reverse = revparam; };
+ bool operator()(const BulletAdder& left, const BulletAdder& right) {
+ return (reverse ? left.time < right.time : left.time > right.time);
+ };
+};
+
+std::list<Bullet> bullets;
+std::priority_queue<BulletAdder, std::vector<BulletAdder>, BulletAdderComparison> bullets_queue;
+
+void create_pattern1(unsigned int base) {
+ for(int j = 0; j < 8; j++) {
+ for(float i = 0; i < M_PI; i += 0.1) {
+ bullets_queue.push(BulletAdder(base + j * 400 + (unsigned int)(i*100),
+ Bullet(
+ Vector3(50.0 + sinf(j % 2 ? M_PI_2 + i : M_PI - i + M_PI_2) * 9, 80 + cosf(M_PI_2 + i) * 10, 0),
+ Vector3(sinf(j % 2 ? M_PI_2 + i : M_PI - i + M_PI_2) / 150.0, -0.01, 0),
+ 5)));
+ }
+ }
+}
+
+void create_pattern2(unsigned int base) {
+ for(float i = 0; i < M_PI * 16; i += 0.1) {
+ bullets_queue.push(BulletAdder(base + (unsigned int)(i*40),
+ Bullet(
+ Vector3(50.0 + cosf(i) * 5,
+ 50.0 + sinf(i) * 5, 0),
+ Vector3(cosf(i) / 100.0, sinf(i) / 100.0, 0),
+ 5)));
+ }
+}
+
+void create_pattern2_2(unsigned int base) {
+ for(float i = 0; i < M_PI * 64; i += 0.1) {
+ bullets_queue.push(BulletAdder(base + (unsigned int)(i*40),
+ Bullet(
+ Vector3(50.0 + cosf(i) * 5,
+ 50.0 + sinf(i) * 5, 0),
+ Vector3(cosf(i + i / 50.0) / 100.0, sinf(i + i / 50.0) / 100.0, 0),
+ 5)));
+ }
+}
+
+void create_pattern3(unsigned int base) {
+ for(float i = 0; i < 101; i++) {
+ bullets_queue.push(BulletAdder(base + i,
+ Bullet(
+ Vector3(i, 90.0 - sinf(i), 0),
+ Vector3(cosf(i) / 100.0, (-5.0 + sinf(i)) / 200.0, 0),
+ 5)));
+ }
+}
+
+void create_bullets() {
+ create_pattern1(50);
+ create_pattern2(9000);
+ create_pattern3(12000);
+ //create_pattern2_2(100);
+}
+
+int main() {
+ if(SDL_Init(SDL_INIT_VIDEO) < 0) {
+ fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_Surface *surface = SDL_SetVideoMode(640, 480, 0, SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_HWSURFACE);
+ if(surface == NULL) {
+ fprintf(stderr, "Failed to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_Event event;
+ bool running = true;
+ bool paused = false;
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+
+ glEnable(GL_TEXTURE_2D);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ glEnable(GL_POINT_SPRITE);
+ glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
+
+ glClearColor(0, 0, 0, 0);
+ glClearDepth(1);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+
+ glShadeModel(GL_SMOOTH);
+
+ create_bullets();
+
+ TextureSDL texture1("foo.png");
+ TextureSDL texture2("foo2.png");
+
+ GLFragmentShader shader1("bullet_fragment.glsl");
+ GLVertexShader shader2("bullet_vertex.glsl");
+ GLShaderProgram program;
+ program.attach(shader1);
+ program.attach(shader2);
+ program.link();
+
+ FTPixmapFont font("/usr/share/fonts/TTF/DejaVuSansMono.ttf");
+ font.FaceSize(12);
+
+ float f = 0.0;
+ float fps = 0.0;
+ unsigned int lasttick = SDL_GetTicks();
+ unsigned int elapsed = 0;
+ unsigned int lastframes = 0,
+ frames = 0;
+ while(running) {
+ while(SDL_PollEvent(&event)) {
+ switch(event.type) {
+ case SDL_QUIT:
+ running = false;
+ break;
+ case SDL_KEYDOWN:
+ switch(event.key.keysym.sym) {
+ case SDLK_ESCAPE:
+ running = false;
+ break;
+ case SDLK_SPACE:
+ paused = !paused;
+ lasttick = SDL_GetTicks();
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(45, 640. / 480., 1, 100);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ unsigned int tick = SDL_GetTicks();
+ unsigned int step = tick - lasttick;
+ lasttick = tick;
+
+ if(!paused) {
+ f += 0.0005 * step;
+ elapsed += step;
+ while(bullets_queue.size() && bullets_queue.top().time <= elapsed) {
+ BulletAdder ba = bullets_queue.top();
+ Bullet& bullet = ba.bullet;
+ bullets_queue.pop();
+ bullets.push_back(bullet);
+ }
+ }
+ gluLookAt(
+ 5 * sinf(f), 1, 5 * cosf(f),
+ 0, 0, 0,
+ 5 * sinf(f), 2, 5 * cosf(f));
+
+ glBegin(GL_LINES);
+ for(int i = -10; i < 11; i++) {
+ if(i % 5 == 0)
+ glColor3f(1, 1, 1);
+ else
+ glColor3f(.5, .5, .5);
+ glVertex3f(i, 0, -10);
+ glVertex3f(i, 0, 10);
+ glVertex3f(-10, 0, i);
+ glVertex3f(10, 0, i);
+ }
+ glEnd();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, 100, 0, 100, 0, 10);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+ program.use();
+ std::list<Bullet>::iterator it;
+ glPointSize(16.0);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, texture2.tex());
+ glBegin(GL_POINTS);
+ for(it = bullets.begin(); it != bullets.end();) {
+ Bullet& b = (*it);
+
+ if(!paused) {
+ b.pos.x += b.direction.x * step;
+ b.pos.y += b.direction.y * step;
+ b.pos.z += b.direction.z * step;
+ }
+
+ glVertex4f(b.pos.x, b.pos.y, b.direction.x, b.direction.y);
+ //glColor3f(b.color.r, b.color.g, b.color.b);
+ /*glTexCoord2f(0, 0);
+ glVertex3f(b.pos.x-1, b.pos.y-1, b.pos.z);
+ glTexCoord2f(1, 0);
+ glVertex3f(b.pos.x+1, b.pos.y-1, b.pos.z);
+ glTexCoord2f(1, 1);
+ glVertex3f(b.pos.x+1, b.pos.y+1, b.pos.z);
+ glTexCoord2f(0, 1);
+ glVertex3f(b.pos.x-1, b.pos.y+1, b.pos.z);*/
+
+ if(b.pos.x < -b.radius || b.pos.x > 100+b.radius || b.pos.y < -b.radius || b.pos.y > 100+b.radius) {
+ it = bullets.erase(it);
+ } else {
+ it++;
+ }
+ }
+ glEnd();
+ //glDisable(GL_POINT_SPRITE);
+ glDisable(GL_TEXTURE_2D);
+
+ glUseProgram(0);
+
+ char s[0xff];
+
+ snprintf(s, 0xff, "Bullets: %d", (int)bullets.size());
+ glRasterPos2f(1, 1);
+ font.Render(s);
+
+ snprintf(s, 0xff, "Queue: %d", (int)bullets_queue.size());
+ glRasterPos2f(1, 1 + font.LineHeight() * (100.0 / 480.0));
+ font.Render(s);
+
+ if(tick - lastframes >= 1000) {
+ fps = (float)frames * ((float)(tick - lastframes) / 1000.0f);
+ frames = 1;
+ lastframes = tick;
+ } else {
+ frames++;
+ }
+ snprintf(s, 0xff, "FPS: %.2f", fps);
+ glRasterPos2f(1, 1 + 2 * font.LineHeight() * (100.0 / 480.0));
+ font.Render(s);
+
+
+ SDL_GL_SwapBuffers();
+
+ SDL_Delay(1);
+ }
+
+ SDL_Quit();
+}
diff --git a/shader.cpp b/shader.cpp
new file mode 100644
index 0000000..04aa031
--- /dev/null
+++ b/shader.cpp
@@ -0,0 +1,91 @@
+#include <fstream>
+#include "shader.h"
+
+bool GLBaseShader::shader_source(const char *filename) {
+ std::ifstream inf(filename, std::ios_base::in);
+ if(!inf.is_open()) {
+ std::cerr << "Failed to load shader " << filename << std::endl;
+ return false;
+ }
+ inf.seekg(0, std::ios_base::end);
+ int length = inf.tellg();
+ inf.seekg(0, std::ios_base::beg);
+ char *buffer = new char[length];
+ inf.read(buffer, length);
+ inf.close();
+
+ glShaderSource(shader, 1, (const GLchar**)&buffer, &length);
+ print_check_ogl_error();
+ delete[] buffer;
+ glCompileShader(shader);
+ print_check_ogl_error();
+ int p;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &p);
+ if(p == 0) {
+ std::cerr << "Failed to compile shader:" << std::endl;
+ char log[0xffff];
+ int size;
+ glGetShaderInfoLog(shader, 0xffff, &size, (GLchar*)&log);
+ std::cerr << log << std::endl;
+ }
+ return shader;
+}
+
+bool GLBaseShader::shader_source(std::string& filename) {
+ return shader_source(filename.c_str());
+}
+
+GLBaseShader::GLBaseShader(GLenum type) {
+ shader = glCreateShader(type);
+}
+
+GLShaderProgram::GLShaderProgram() {
+ program = glCreateProgram();
+}
+
+bool GLShaderProgram::attach(GLBaseShader& shader) {
+ glAttachShader(program, shader.shader);
+ return !print_check_ogl_error();
+}
+
+bool GLShaderProgram::detach(GLBaseShader& shader) {
+ glDetachShader(program, shader.shader);
+ return !print_check_ogl_error();
+}
+
+bool GLShaderProgram::link() {
+ glLinkProgram(program);
+ bool error = print_check_ogl_error();
+ int p;
+ glGetProgramiv(program, GL_LINK_STATUS, &p);
+ if(p == 0) {
+ std::cerr << "Failed to link program:" << std::endl;
+ char log[0xffff];
+ int size;
+ glGetProgramInfoLog(program, 0xffff, &size, (GLchar*)&log);
+ printf(log);
+ }
+ return !error && p;
+}
+
+bool GLShaderProgram::use() {
+ if(!glIsProgram(program)) program = glCreateProgram();
+ glUseProgram(program);
+ return !print_check_ogl_error();
+}
+
+void GLShaderProgram::remove() {
+ glDeleteProgram(program);
+}
+
+void print_ogl_error(GLenum error) {
+ unsigned char *buf = (unsigned char*)gluErrorString(error);
+ std::cerr << "OpenGL: " << buf << std::endl;
+}
+
+bool print_check_ogl_error() {
+ GLenum error = glGetError();
+ if(error != GL_NO_ERROR)
+ print_ogl_error(error);
+ return error != GL_NO_ERROR;
+}
diff --git a/shader.h b/shader.h
new file mode 100644
index 0000000..d2ec9d4
--- /dev/null
+++ b/shader.h
@@ -0,0 +1,51 @@
+#ifndef _SHADER_H_
+#define _SHADER_H_
+
+#include <iostream>
+#include <string>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+class GLBaseShader {
+ friend class GLShaderProgram;
+
+ protected:
+ bool shader_source(const char *filename);
+ bool shader_source(std::string& filename);
+ unsigned int shader;
+ public:
+ GLBaseShader(GLenum);
+};
+
+class GLVertexShader : public GLBaseShader {
+ public:
+ GLVertexShader() : GLBaseShader(GL_VERTEX_SHADER) {};
+ GLVertexShader(const char *s) : GLBaseShader(GL_VERTEX_SHADER) { shader_source(s); };
+ GLVertexShader(std::string& s) : GLBaseShader(GL_VERTEX_SHADER) { shader_source(s); };
+};
+
+class GLFragmentShader : public GLBaseShader {
+ public:
+ GLFragmentShader() : GLBaseShader(GL_FRAGMENT_SHADER) {};
+ GLFragmentShader(const char *s) : GLBaseShader(GL_FRAGMENT_SHADER) { shader_source(s); };
+ GLFragmentShader(std::string& s) : GLBaseShader(GL_FRAGMENT_SHADER) { shader_source(s); };
+};
+
+class GLShaderProgram {
+ protected:
+ unsigned int program;
+ public:
+ GLShaderProgram();
+
+ bool attach(GLBaseShader&);
+ bool detach(GLBaseShader&);
+ bool link();
+ bool use();
+ void remove();
+};
+
+void print_ogl_error(GLenum);
+bool print_check_ogl_error();
+
+#endif
diff --git a/texture.cpp b/texture.cpp
new file mode 100644
index 0000000..ca9d8e7
--- /dev/null
+++ b/texture.cpp
@@ -0,0 +1,29 @@
+#ifndef __APPLE__
+#include <GL/gl.h>
+#include <GL/glut.h>
+#else
+#include <OpenGL/gl.h>
+#include <GLUT/glut.h>
+#endif
+#include <stdexcept>
+#include "texture.h"
+#include <stdio.h>
+
+unsigned int Texture::tex() {
+ return texture;
+}
+
+void Texture::build() {
+ if(!data) {
+ throw(std::runtime_error("No texture data"));
+ }
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ if(byte_per_pixel == 4) {
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ } else if(byte_per_pixel == 3) {
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
+ }
+}
diff --git a/texture.h b/texture.h
new file mode 100644
index 0000000..14e500f
--- /dev/null
+++ b/texture.h
@@ -0,0 +1,14 @@
+#ifndef _TEXTURE_H_
+#define _TEXTURE_H_
+class Texture {
+ public:
+ unsigned int tex();
+ protected:
+ void build();
+ unsigned char* data;
+ unsigned int width;
+ unsigned int height;
+ unsigned int byte_per_pixel;
+ unsigned int texture;
+};
+#endif // _TEXTURE_H_
diff --git a/texturesdl.cpp b/texturesdl.cpp
new file mode 100644
index 0000000..8e112ef
--- /dev/null
+++ b/texturesdl.cpp
@@ -0,0 +1,17 @@
+#include <iostream>
+#include <stdexcept>
+#include <SDL/SDL_image.h>
+#include "texturesdl.h"
+
+TextureSDL::TextureSDL(const char* filename) {
+ SDL_Surface* image = IMG_Load(filename);
+
+ width = image->w;
+ height = image->h;
+ byte_per_pixel = image->format->BytesPerPixel;
+ data = (unsigned char*)image->pixels;
+
+ build();
+
+ SDL_FreeSurface(image);
+}
diff --git a/texturesdl.h b/texturesdl.h
new file mode 100644
index 0000000..6b2eff2
--- /dev/null
+++ b/texturesdl.h
@@ -0,0 +1,8 @@
+#ifndef _TEXTURESDL_H_
+#define _TEXTURESDL_H_
+#include "texture.h"
+class TextureSDL : public Texture {
+ public:
+ TextureSDL(const char* filename);
+};
+#endif // _TEXTURESDL_H_
diff --git a/vector.cpp b/vector.cpp
new file mode 100644
index 0000000..f2ce8d7
--- /dev/null
+++ b/vector.cpp
@@ -0,0 +1,47 @@
+#include "vector.h"
+
+Vector3::Vector3() {
+ x = y = z = 0;
+}
+
+Vector3::Vector3(float p1, float p2, float p3) {
+ x = p1;
+ y = p2;
+ z = p3;
+}
+
+Vector3::Vector3(const Vector3& v) {
+ x = v.r;
+ y = v.y;
+ z = v.z;
+}
+
+Vector3& Vector3::operator=(const Vector3& v) {
+ x = v.r;
+ y = v.y;
+ z = v.z;
+ return *this;
+}
+
+Vector4::Vector4() : Vector3() {
+ w = 0;
+}
+
+Vector4::Vector4(float p1, float p2, float p3, float p4) : Vector3(p1, p2, p3) {
+ w = p4;
+}
+
+Vector4::Vector4(const Vector4& v) {
+ x = v.r;
+ y = v.y;
+ z = v.z;
+ w = v.w;
+}
+
+Vector4& Vector4::operator=(const Vector4& v) {
+ x = v.r;
+ y = v.y;
+ z = v.z;
+ w = v.w;
+ return *this;
+}
diff --git a/vector.h b/vector.h
new file mode 100644
index 0000000..3c590c3
--- /dev/null
+++ b/vector.h
@@ -0,0 +1,36 @@
+#ifndef _VECTOR_H_
+#define _VECTOR_H_
+
+class Vector3 {
+ public:
+ union {
+ float x, r;
+ };
+ union {
+ float y, g;
+ };
+ union {
+ float z, b;
+ };
+
+ Vector3();
+ Vector3(float p1, float p2, float p3);
+ Vector3(const Vector3& v);
+
+ Vector3& operator=(const Vector3& v);
+};
+
+class Vector4 : public Vector3 {
+ public:
+ union {
+ float w, a;
+ };
+
+ Vector4();
+ Vector4(float p1, float p2, float p3, float p4);
+ Vector4(const Vector4& v);
+
+ Vector4& operator=(const Vector4& v);
+};
+
+#endif