1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-06 21:26:56 +02:00

- FFP renderer

This commit is contained in:
XProger
2016-08-16 01:13:15 +03:00
parent 0fb508e801
commit 3382830f9a
11 changed files with 3016 additions and 0 deletions

149
src/core.h Normal file
View File

@@ -0,0 +1,149 @@
#ifndef H_CORE
#define H_CORE
#include <stdio.h>
#include <windows.h>
#include <gl/GL.h>
#include <gl/glext.h>
#include "utils.h"
#include "input.h"
#ifdef WIN32
#if defined(_MSC_VER) // Visual Studio
#define GetProcOGL(x) *(void**)&x=(void*)wglGetProcAddress(#x);
#else // GCC
#define GetProcOGL(x) x=(typeof(x))wglGetProcAddress(#x);
#endif
// Texture
PFNGLACTIVETEXTUREPROC glActiveTexture;
PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
// Shader
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLDELETEPROGRAMPROC glDeleteProgram;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLDELETESHADERPROC glDeleteShader;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
PFNGLUNIFORM1IVPROC glUniform1iv;
PFNGLUNIFORM3FVPROC glUniform3fv;
PFNGLUNIFORM4FVPROC glUniform4fv;
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
// Mesh
PFNGLGENBUFFERSARBPROC glGenBuffers;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers;
PFNGLBINDBUFFERARBPROC glBindBuffer;
PFNGLBUFFERDATAARBPROC glBufferData;
#endif
namespace Core {
int width, height;
float deltaTime;
mat4 mView, mProj, mViewProj, mModel;
}
#include "texture.h"
#include "shader.h"
#include "mesh.h"
enum CullMode { cfNone, cfBack, cfFront };
enum BlendMode { bmNone, bmAlpha, bmAdd, bmMultiply, bmScreen };
namespace Core {
void init() {
GetProcOGL(glActiveTexture);
GetProcOGL(glCompressedTexImage2D);
GetProcOGL(glCreateProgram);
GetProcOGL(glDeleteProgram);
GetProcOGL(glLinkProgram);
GetProcOGL(glUseProgram);
GetProcOGL(glGetProgramInfoLog);
GetProcOGL(glCreateShader);
GetProcOGL(glDeleteShader);
GetProcOGL(glShaderSource);
GetProcOGL(glAttachShader);
GetProcOGL(glCompileShader);
GetProcOGL(glGetShaderInfoLog);
GetProcOGL(glGetUniformLocation);
GetProcOGL(glUniform1iv);
GetProcOGL(glUniform3fv);
GetProcOGL(glUniform4fv);
GetProcOGL(glUniformMatrix4fv);
GetProcOGL(glBindAttribLocation);
GetProcOGL(glEnableVertexAttribArray);
GetProcOGL(glDisableVertexAttribArray);
GetProcOGL(glVertexAttribPointer);
GetProcOGL(glGenBuffers);
GetProcOGL(glDeleteBuffers);
GetProcOGL(glBindBuffer);
GetProcOGL(glBufferData);
}
void free() {
//
}
void clear(const vec4 &color) {
glClearColor(color.x, color.y, color.z, color.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void setViewport(int x, int y, int width, int height) {
glViewport(x, y, width, height);
}
void setCulling(CullMode mode) {
switch (mode) {
case cfNone :
glDisable(GL_CULL_FACE);
case cfBack :
glCullFace(GL_BACK);
break;
case cfFront :
glCullFace(GL_FRONT);
break;
}
if (mode != bmNone)
glEnable(GL_CULL_FACE);
}
void setBlending(BlendMode mode) {
switch (mode) {
case bmNone :
glDisable(GL_BLEND);
break;
case bmAlpha :
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case bmAdd :
glBlendFunc(GL_ONE, GL_ONE);
break;
case bmMultiply :
glBlendFunc(GL_DST_COLOR, GL_ZERO);
break;
case bmScreen :
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
break;
}
if (mode != bmNone)
glEnable(GL_BLEND);
}
}
#endif

1639
src/game.h Normal file

File diff suppressed because it is too large Load Diff

83
src/input.h Normal file
View File

@@ -0,0 +1,83 @@
#ifndef H_INPUT
#define H_INPUT
#include "utils.h"
enum InputKey { ikNone,
// keyboard
ikLeft, ikRight, ikUp, ikDown, ikSpace, ikEnter, ikEscape, ikShift, ikCtrl, ikAlt,
ik0, ik1, ik2, ik3, ik4, ik5, ik6, ik7, ik8, ik9,
ikA, ikB, ikC, ikD, ikE, ikF, ikG, ikH, ikI, ikJ, ikK, ikL, ikM,
ikN, ikO, ikP, ikQ, ikR, ikS, ikT, ikU, ikV, ikW, ikX, ikY, ikZ,
// mouse
ikMouseL, ikMouseR, ikMouseM,
// touch
ikTouchA, ikTouchB,
// gamepad
ikJoyA, ikJoyB, ikJoyX, ikJoyY, ikJoyLB, ikJoyRB, ikJoyL, ikJoyR, ikJoySelect, ikJoyStart, ikJoyLT, ikJoyRT, ikJoyDP,
ikMAX };
namespace Input {
bool down[ikMAX];
struct {
vec2 pos;
struct {
vec2 L, R, M;
} start;
} mouse;
struct {
vec2 L, R;
float LT, RT, DP;
} joy;
struct {
vec2 A, B;
struct {
vec2 A, B;
} start;
} touch;
void reset() {
memset(down, 0, sizeof(down));
memset(&mouse, 0, sizeof(mouse));
memset(&joy, 0, sizeof(joy));
memset(&touch, 0, sizeof(touch));
}
void setDown(InputKey key, bool value) {
if (down[key] == value)
return;
if (value)
switch (key) {
case ikMouseL : mouse.start.L = mouse.pos; break;
case ikMouseR : mouse.start.R = mouse.pos; break;
case ikMouseM : mouse.start.M = mouse.pos; break;
case ikTouchA : touch.start.A = touch.A; break;
case ikTouchB : touch.start.B = touch.B; break;
}
down[key] = value;
}
void setPos(InputKey key, const vec2 &pos) {
switch (key) {
case ikMouseL :
case ikMouseR :
case ikMouseM : mouse.pos = pos; break;
case ikJoyL : joy.L = pos; break;
case ikJoyR : joy.R = pos; break;
case ikJoyLT : joy.LT = pos.x; break;
case ikJoyRT : joy.RT = pos.x; break;
case ikJoyDP : joy.DP = pos.x; break;
case ikTouchA : touch.A = pos; break;
case ikTouchB : touch.B = pos; break;
}
}
}
#endif

62
src/mesh.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef H_MESH
#define H_MESH
#include "core.h"
typedef unsigned short Index;
struct Vertex {
vec3 coord;
vec3 normal;
vec2 texCoord;
};
struct Mesh {
GLuint ID[2];
int iCount;
int vCount;
Mesh(const char *name) {
Stream stream(name);
Index *indices = stream.readArray<Index> (stream.read(iCount));
Vertex *vertices = stream.readArray<Vertex>(stream.read(vCount));
glGenBuffers(2, ID);
bind();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iCount * sizeof(Index), indices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, vCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
delete[] indices;
delete[] vertices;
}
virtual ~Mesh() {
glDeleteBuffers(2, ID);
}
void bind() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ID[0]);
glBindBuffer(GL_ARRAY_BUFFER, ID[1]);
}
void render() {
bind();
glEnableVertexAttribArray(aCoord);
glEnableVertexAttribArray(aNormal);
glEnableVertexAttribArray(aTexCoord);
Vertex *v = NULL;
glVertexAttribPointer(aCoord, 3, GL_FLOAT, false, sizeof(Vertex), &v->coord);
glVertexAttribPointer(aNormal, 3, GL_FLOAT, false, sizeof(Vertex), &v->normal);
glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, false, sizeof(Vertex), &v->texCoord);
glDrawElements(GL_TRIANGLES, iCount, GL_UNSIGNED_SHORT, NULL);
glDisableVertexAttribArray(aCoord);
glDisableVertexAttribArray(aNormal);
glDisableVertexAttribArray(aTexCoord);
}
};
#endif

91
src/shader.h Normal file
View File

@@ -0,0 +1,91 @@
#ifndef H_SHADER
#define H_SHADER
#include "core.h"
enum AttribType { aCoord, aTexCoord, aNormal, aMAX };
enum SamplerType { sTex0, sMAX };
enum UniformType { uViewProj, uModel, uLightVec, uMAX };
const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal" };
const char *SamplerName[sMAX] = { "sTex0" };
const char *UniformName[uMAX] = { "uViewProj", "uModel", "uLightVec" };
struct Shader {
GLuint ID;
GLint uID[uMAX];
Shader(const char *name, int param) {
Stream stream(name);
char *text = new char[stream.size + 1];
stream.read(text, stream.size);
text[stream.size] = '\0';
#define GLSL_DEFINE "#version 110\n"
const int type[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER };
const char *code[2][2] = {
{ GLSL_DEFINE "#define VERTEX\n", text },
{ GLSL_DEFINE "#define FRAGMENT\n", text }
};
GLchar info[256];
ID = glCreateProgram();
for (int i = 0; i < 2; i++) {
GLuint obj = glCreateShader(type[i]);
glShaderSource(obj, 2, code[i], NULL);
glCompileShader(obj);
glGetShaderInfoLog(obj, sizeof(info), NULL, info);
if (info[0]) LOG("! shader: %s\n", info);
glAttachShader(ID, obj);
glDeleteShader(obj);
}
delete[] text;
for (int at = 0; at < aMAX; at++)
glBindAttribLocation(ID, at, AttribName[at]);
glLinkProgram(ID);
glGetProgramInfoLog(ID, sizeof(info), NULL, info);
if (info[0]) LOG("! program: %s\n", info);
bind();
for (int st = 0; st < sMAX; st++)
glUniform1iv(glGetUniformLocation(ID, (GLchar*)SamplerName[st]), 1, &st);
for (int ut = 0; ut < uMAX; ut++)
uID[ut] = glGetUniformLocation(ID, (GLchar*)UniformName[ut]);
}
virtual ~Shader() {
glDeleteProgram(ID);
}
void bind() {
glUseProgram(ID);
setParam(uViewProj, Core::mViewProj);
setParam(uModel, Core::mModel);
}
void setParam(UniformType uType, const vec3 &value, int count = 1) {
if (uID[uType] != -1)
glUniform3fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const vec4 &value, int count = 1) {
if (uID[uType] != -1)
glUniform4fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const mat4 &value, int count = 1) {
if (uID[uType] != -1)
glUniformMatrix4fv(uID[uType], count, false, (GLfloat*)&value);
}
};
#endif

103
src/texture.h Normal file
View File

@@ -0,0 +1,103 @@
#ifndef H_TEXTURE
#define H_TEXTURE
#include "core.h"
#define PVR_RGBA8 0x61626772
#define PVR_ALPHA 0x00000061
#define PVR_PVRTC4 0x00000002 // iOS
#define PVR_ETC1 0x00000006 // Android
#define PVR_BC1 0x00000007 // Desktop
#define GL_COMPRESSED_RGB_S3TC_DXT1 0x83F0
#define GL_ETC1_RGB8_OES 0x8D64
#define GL_COMPRESSED_RGB_PVRTC_4BPPV1 0x8C00
struct Texture {
GLuint ID;
int width, height;
Texture(const char *name) {
Stream stream(name);
struct {
int version;
int flags;
long format;
long ext;
int color;
int channel;
int height;
int width;
int depth;
int surfaces;
int faces;
int mipCount;
int metaSize;
} header;
stream.read(header);
stream.seek(header.metaSize);
GLenum fmt;
int minSize;
switch (header.format) {
case PVR_ALPHA : minSize = 1; fmt = GL_ALPHA; break;
case PVR_RGBA8 : minSize = 1; fmt = GL_RGBA; break;
case PVR_BC1 : minSize = 4; fmt = GL_COMPRESSED_RGB_S3TC_DXT1; break;
case PVR_ETC1 : minSize = 4; fmt = GL_ETC1_RGB8_OES; break;
case PVR_PVRTC4 : minSize = 8; fmt = GL_COMPRESSED_RGB_PVRTC_4BPPV1; break;
default :
LOG("! unsupported texture format\n");
ID = 0;
return;
}
glGenTextures(1, &ID);
bind(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, header.mipCount == 1 ? GL_LINEAR : GL_LINEAR_MIPMAP_LINEAR);
int sizeX = width = header.width;
int sizeY = height = header.height;
char *data = new char[width * height * 4];
for (int i = 0; i < header.mipCount; i++) {
if (minSize == 1) {
int size = sizeX * sizeY * (header.format == PVR_RGBA8 ? 4 : 1);
stream.read(data, size);
glTexImage2D(GL_TEXTURE_2D, i, fmt, sizeX, sizeY, 0, fmt, GL_UNSIGNED_BYTE, data);
} else {
int size = (max(sizeX, minSize) * max(sizeY, minSize) * 4 + 7) / 8;
stream.read(data, size);
glCompressedTexImage2D(GL_TEXTURE_2D, i, fmt, sizeX, sizeY, 0, size, data);
}
sizeX /= 2;
sizeY /= 2;
}
delete[] data;
}
Texture(int width, int height, int format, void *data) : width(width), height(height) {
glGenTextures(1, &ID);
bind(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
virtual ~Texture() {
glDeleteTextures(1, &ID);
}
void bind(int sampler) {
glActiveTexture(GL_TEXTURE0 + sampler);
glBindTexture(GL_TEXTURE_2D, ID);
}
};
#endif

540
src/utils.h Normal file
View File

@@ -0,0 +1,540 @@
#ifndef H_UTILS
#define H_UTILS
#include <cstring>
#include <math.h>
#include <float.h>
#ifdef _DEBUG
#define debugBreak() _asm { int 3 }
#define ASSERT(expr) if (expr) {} else { LOG("ASSERT %s in %s:%d\n", #expr, __FILE__, __LINE__); debugBreak(); }
#else
#define ASSERT(expr)
#endif
#ifndef ANDROID
#define LOG(...) printf(__VA_ARGS__)
#else
#include <android/log.h>
#define LOG(...) __android_log_print(ANDROID_LOG_INFO,"X5",__VA_ARGS__)
#endif
#define PI 3.14159265358979323846f
#define DEG2RAD (PI / 180.0f)
#define RAD2DEG (180.0f / PI)
#define EPS FLT_EPSILON
template <typename T>
inline const T& min(const T &a, const T &b) {
return a < b ? a : b;
}
template <class T>
inline const T& max(const T &a, const T &b) {
return a > b ? a : b;
}
struct vec2 {
float x, y;
vec2() {}
vec2(float s) : x(s), y(s) {}
vec2(float x, float y) : x(x), y(y) {}
vec2 operator + (const vec2 &v) const { return vec2(x+v.x, y+v.y); }
vec2 operator - (const vec2 &v) const { return vec2(x-v.x, y-v.y); }
vec2 operator * (float s) const { return vec2(x*s, y*s); }
float dot(const vec2 &v) const { return x*v.x + y*v.y; }
float cross(const vec2 &v) const { return x*v.y - y*v.x; }
float length() const { return sqrtf(dot(*this)); }
vec2 normal() const { float s = length(); return s == 0.0 ? (*this) : (*this)*(1.0f/s); }
};
struct vec3 {
float x, y, z;
vec3() {}
vec3(float s) : x(s), y(s), z(s) {}
vec3(float x, float y, float z) : x(x), y(y), z(z) {}
vec3(const vec2 &xy, float z = 0.0f) : x(xy.x), y(xy.y), z(z) {}
vec3 operator + (const vec3 &v) const { return vec3(x+v.x, y+v.y, z+v.z); }
vec3 operator - (const vec3 &v) const { return vec3(x-v.x, y-v.y, z-v.z); }
vec3 operator * (const vec3 &v) const { return vec3(x*v.x, y*v.y, z*v.z); }
vec3 operator * (float s) const { return vec3(x*s, y*s, z*s); }
float dot(const vec3 &v) const { return x*v.x + y*v.y + z*v.z; }
vec3 cross(const vec3 &v) const { return vec3(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x); }
float length() const { return sqrtf(x*x + y*y + z*z); }
vec3 normal() const { float s = length(); return s == 0.0 ? (*this) : (*this)*(1.0f/s); }
vec3 lerp(const vec3 &v, const float t) const {
return *this + (v - *this) * t;
}
};
struct vec4 {
union {
struct { vec3 xyz; };
struct { float x, y, z, w; };
};
vec4() {}
vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
};
struct quat {
float x, y, z, w;
quat() {}
quat(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
quat(const vec3 &axis, float angle) {
angle *= 0.5f;
float s = sinf(angle);
x = axis.x * s;
y = axis.y * s;
z = axis.z * s;
w = cosf(angle);
}
quat quat::operator - () const {
return quat(-x, -y, -z, -w);
}
quat quat::operator + (const quat &q) const {
return quat(x + q.x, y + q.y, z + q.z, w + q.w);
}
quat quat::operator - (const quat &q) const {
return quat(x - q.x, y - q.y, z - q.z, w - q.w);
}
quat quat::operator * (const float s) const {
return quat(x * s, y * s, z * s, w * s);
}
quat quat::operator * (const quat &q) const {
return quat(w * q.x + x * q.w + y * q.z - z * q.y,
w * q.y + y * q.w + z * q.x - x * q.z,
w * q.z + z * q.w + x * q.y - y * q.x,
w * q.w - x * q.x - y * q.y - z * q.z);
}
float dot(const quat &q) const {
return x * q.x + y * q.y + z * q.z + w * q.w;
}
float length2() const {
return dot(*this);
}
float length() const {
return sqrtf(length2());
}
void quat::normalize() {
*this = normal();
}
quat quat::normal() const {
return *this * (1.0f / length());
}
quat quat::conjugate() const {
return quat(-x, -y, -z, w);
}
quat quat::inverse() const {
return conjugate() * (1.0f / length2());
}
quat lerp(const quat &q, float t) const {
if (t <= 0.0f) return *this;
if (t >= 1.0f) return q;
return dot(q) < 0 ? (*this - (q + *this) * t) :
(*this + (q - *this) * t);
}
quat slerp(const quat &q, float t) const {
if (t <= 0.0f) return *this;
if (t >= 1.0f) return q;
quat temp;
float omega, cosom, sinom, scale0, scale1;
cosom = dot(q);
if (cosom < 0.0f) {
temp = -q;
cosom = -cosom;
} else
temp = q;
if (1.0f - cosom > EPS) {
omega = acos(cosom);
sinom = 1.0f / sin(omega);
scale0 = sin((1.0f - t) * omega) * sinom;
scale1 = sin(t * omega) * sinom;
} else {
scale0 = 1.0f - t;
scale1 = t;
}
return *this * scale0 + temp * scale1;
}
};
struct mat4 {
union {
struct {
float e00, e10, e20, e30,
e01, e11, e21, e31,
e02, e12, e22, e32,
e03, e13, e23, e33;
};
struct { vec4 right, up, dir, offset; };
};
mat4() {}
mat4(const quat &rot, const vec3 &pos) {
setRot(rot);
setPos(pos);
e30 = e31 = e32 = 0.0f;
e33 = 1.0f;
}
mat4(float l, float r, float b, float t, float znear, float zfar) {
identity();
e00 = 2.0f / (r - l);
e11 = 2.0f / (t - b);
e22 = 2.0f / (znear - zfar);
e03 = (l + r) / (l - r);
e13 = (b + t) / (b - t);
e23 = (zfar + znear) / (znear - zfar);
}
mat4(float fov, float aspect, float znear, float zfar) {
float k = 1.0f / tanf(fov * 0.5f * DEG2RAD);
identity();
e00 = k / aspect;
e11 = k;
e22 = (znear + zfar) / (znear - zfar);
e33 = 0.0f;
e32 = -1.0f;
e23 = 2.0f * zfar * znear / (znear - zfar);
}
void identity() {
e10 = e20 = e30 = e01 = e21 = e31 = e02 = e12 = e32 = e03 = e13 = e23 = 0.0f;
e00 = e11 = e22 = e33 = 1.0f;
}
mat4 operator * (const mat4 &m) const {
mat4 r;
r.e00 = e00 * m.e00 + e01 * m.e10 + e02 * m.e20 + e03 * m.e30;
r.e10 = e10 * m.e00 + e11 * m.e10 + e12 * m.e20 + e13 * m.e30;
r.e20 = e20 * m.e00 + e21 * m.e10 + e22 * m.e20 + e23 * m.e30;
r.e30 = e30 * m.e00 + e31 * m.e10 + e32 * m.e20 + e33 * m.e30;
r.e01 = e00 * m.e01 + e01 * m.e11 + e02 * m.e21 + e03 * m.e31;
r.e11 = e10 * m.e01 + e11 * m.e11 + e12 * m.e21 + e13 * m.e31;
r.e21 = e20 * m.e01 + e21 * m.e11 + e22 * m.e21 + e23 * m.e31;
r.e31 = e30 * m.e01 + e31 * m.e11 + e32 * m.e21 + e33 * m.e31;
r.e02 = e00 * m.e02 + e01 * m.e12 + e02 * m.e22 + e03 * m.e32;
r.e12 = e10 * m.e02 + e11 * m.e12 + e12 * m.e22 + e13 * m.e32;
r.e22 = e20 * m.e02 + e21 * m.e12 + e22 * m.e22 + e23 * m.e32;
r.e32 = e30 * m.e02 + e31 * m.e12 + e32 * m.e22 + e33 * m.e32;
r.e03 = e00 * m.e03 + e01 * m.e13 + e02 * m.e23 + e03 * m.e33;
r.e13 = e10 * m.e03 + e11 * m.e13 + e12 * m.e23 + e13 * m.e33;
r.e23 = e20 * m.e03 + e21 * m.e13 + e22 * m.e23 + e23 * m.e33;
r.e33 = e30 * m.e03 + e31 * m.e13 + e32 * m.e23 + e33 * m.e33;
return r;
}
vec3 operator * (const vec3 &v) const {
return vec3(
e00 * v.x + e01 * v.y + e02 * v.z + e03,
e10 * v.x + e11 * v.y + e12 * v.z + e13,
e20 * v.x + e21 * v.y + e22 * v.z + e23);
}
vec4 operator * (const vec4 &v) const {
return vec4(
e00 * v.x + e01 * v.y + e02 * v.z + e03 * v.w,
e10 * v.x + e11 * v.y + e12 * v.z + e13 * v.w,
e20 * v.x + e21 * v.y + e22 * v.z + e23 * v.w,
e30 * v.x + e31 * v.y + e32 * v.z + e33 * v.w);
}
void translate(const vec3 &offset) {
mat4 m;
m.identity();
m.setPos(offset);
*this = *this * m;
};
void scale(const vec3 &factor) {
mat4 m;
m.identity();
m.e00 = factor.x;
m.e11 = factor.y;
m.e22 = factor.z;
*this = *this * m;
}
void rotateX(float angle) {
mat4 m;
m.identity();
float s = sinf(angle), c = cosf(angle);
m.e11 = c; m.e21 = s;
m.e12 = -s; m.e22 = c;
*this = *this * m;
}
void rotateY(float angle) {
mat4 m;
m.identity();
float s = sinf(angle), c = cosf(angle);
m.e00 = c; m.e20 = -s;
m.e02 = s; m.e22 = c;
*this = *this * m;
}
void rotateZ(float angle) {
mat4 m;
m.identity();
float s = sinf(angle), c = cosf(angle);
m.e00 = c; m.e01 = -s;
m.e10 = s; m.e11 = c;
*this = *this * m;
}
float det() const {
return e00 * (e11 * (e22 * e33 - e32 * e23) - e21 * (e12 * e33 - e32 * e13) + e31 * (e12 * e23 - e22 * e13)) -
e10 * (e01 * (e22 * e33 - e32 * e23) - e21 * (e02 * e33 - e32 * e03) + e31 * (e02 * e23 - e22 * e03)) +
e20 * (e01 * (e12 * e33 - e32 * e13) - e11 * (e02 * e33 - e32 * e03) + e31 * (e02 * e13 - e12 * e03)) -
e30 * (e01 * (e12 * e23 - e22 * e13) - e11 * (e02 * e23 - e22 * e03) + e21 * (e02 * e13 - e12 * e03));
}
mat4 inverse() const {
float idet = 1.0f / det();
mat4 r;
r.e00 = (e11 * (e22 * e33 - e32 * e23) - e21 * (e12 * e33 - e32 * e13) + e31 * (e12 * e23 - e22 * e13)) * idet;
r.e01 = -(e01 * (e22 * e33 - e32 * e23) - e21 * (e02 * e33 - e32 * e03) + e31 * (e02 * e23 - e22 * e03)) * idet;
r.e02 = (e01 * (e12 * e33 - e32 * e13) - e11 * (e02 * e33 - e32 * e03) + e31 * (e02 * e13 - e12 * e03)) * idet;
r.e03 = -(e01 * (e12 * e23 - e22 * e13) - e11 * (e02 * e23 - e22 * e03) + e21 * (e02 * e13 - e12 * e03)) * idet;
r.e10 = -(e10 * (e22 * e33 - e32 * e23) - e20 * (e12 * e33 - e32 * e13) + e30 * (e12 * e23 - e22 * e13)) * idet;
r.e11 = (e00 * (e22 * e33 - e32 * e23) - e20 * (e02 * e33 - e32 * e03) + e30 * (e02 * e23 - e22 * e03)) * idet;
r.e12 = -(e00 * (e12 * e33 - e32 * e13) - e10 * (e02 * e33 - e32 * e03) + e30 * (e02 * e13 - e12 * e03)) * idet;
r.e13 = (e00 * (e12 * e23 - e22 * e13) - e10 * (e02 * e23 - e22 * e03) + e20 * (e02 * e13 - e12 * e03)) * idet;
r.e20 = (e10 * (e21 * e33 - e31 * e23) - e20 * (e11 * e33 - e31 * e13) + e30 * (e11 * e23 - e21 * e13)) * idet;
r.e21 = -(e00 * (e21 * e33 - e31 * e23) - e20 * (e01 * e33 - e31 * e03) + e30 * (e01 * e23 - e21 * e03)) * idet;
r.e22 = (e00 * (e11 * e33 - e31 * e13) - e10 * (e01 * e33 - e31 * e03) + e30 * (e01 * e13 - e11 * e03)) * idet;
r.e23 = -(e00 * (e11 * e23 - e21 * e13) - e10 * (e01 * e23 - e21 * e03) + e20 * (e01 * e13 - e11 * e03)) * idet;
r.e30 = -(e10 * (e21 * e32 - e31 * e22) - e20 * (e11 * e32 - e31 * e12) + e30 * (e11 * e22 - e21 * e12)) * idet;
r.e31 = (e00 * (e21 * e32 - e31 * e22) - e20 * (e01 * e32 - e31 * e02) + e30 * (e01 * e22 - e21 * e02)) * idet;
r.e32 = -(e00 * (e11 * e32 - e31 * e12) - e10 * (e01 * e32 - e31 * e02) + e30 * (e01 * e12 - e11 * e02)) * idet;
r.e33 = (e00 * (e11 * e22 - e21 * e12) - e10 * (e01 * e22 - e21 * e02) + e20 * (e01 * e12 - e11 * e02)) * idet;
return r;
}
mat4 transpose() const {
mat4 r;
r.e00 = e00; r.e10 = e01; r.e20 = e02; r.e30 = e03;
r.e01 = e10; r.e11 = e11; r.e21 = e12; r.e31 = e13;
r.e02 = e20; r.e12 = e21; r.e22 = e22; r.e32 = e23;
r.e03 = e30; r.e13 = e31; r.e23 = e32; r.e33 = e33;
return r;
}
quat mat4::getRot() const {
float t, s;
t = 1.0f + e00 + e11 + e22;
if (t > EPS) {
s = 0.5f / sqrtf(t);
return quat((e21 - e12) * s, (e02 - e20) * s, (e10 - e01) * s, 0.25f / s);
} else
if (e00 > e11 && e00 > e22) {
s = 0.5f / sqrtf(1.0f + e00 - e11 - e22);
return quat(0.25f / s, (e01 + e10) * s, (e02 + e20) * s, (e21 - e12) * s);
} else
if (e11 > e22) {
s = 0.5f / sqrtf(1.0f - e00 + e11 - e22);
return quat((e01 + e10) * s, 0.25f / s, (e12 + e21) * s, (e02 - e20) * s);
} else {
s = 0.5f / sqrtf(1.0f - e00 - e11 + e22);
return quat((e02 + e20) * s, (e12 + e21) * s, 0.25f / s, (e10 - e01) * s);
}
}
void mat4::setRot(const quat &rot) {
float sx = rot.x * rot.x,
sy = rot.y * rot.y,
sz = rot.z * rot.z,
sw = rot.w * rot.w,
inv = 1.0f / (sx + sy + sz + sw);
e00 = ( sx - sy - sz + sw) * inv;
e11 = (-sx + sy - sz + sw) * inv;
e22 = (-sx - sy + sz + sw) * inv;
inv *= 2.0f;
float t1 = rot.x * rot.y;
float t2 = rot.z * rot.w;
e10 = (t1 + t2) * inv;
e01 = (t1 - t2) * inv;
t1 = rot.x * rot.z;
t2 = rot.y * rot.w;
e20 = (t1 - t2) * inv;
e02 = (t1 + t2) * inv;
t1 = rot.y * rot.z;
t2 = rot.x * rot.w;
e21 = (t1 + t2) * inv;
e12 = (t1 - t2) * inv;
}
vec3 mat4::getPos() const {
return offset.xyz;
}
void mat4::setPos(const vec3 &pos) {
offset.xyz = pos;
}
};
struct Stream {
FILE *f;
int size, pos;
Stream(const char *name) : pos(0) {
f = fopen(name, "rb");
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
}
~Stream() {
fclose(f);
}
void setPos(int pos) {
this->pos = pos;
fseek(f, pos, SEEK_SET);
}
void seek(int offset) {
fseek(f, offset, SEEK_CUR);
pos += offset;
}
int read(void *data, int size) {
pos += size;
return fread(data, 1, size, f);
}
template <typename T>
T& read(T &x) {
read(&x, sizeof(x));
return x;
}
template <typename T>
T* readArray(int count) {
if (!count)
return NULL;
T *a = new T[count];
read(a, count * sizeof(T));
return a;
}
char *readStr(char *buffer) {
unsigned char len;
read(&len, sizeof(len));
if (!len)
return NULL;
read(buffer, len);
buffer[len] = 0;
return buffer;
}
};
template <typename T, typename C = int>
struct Array {
T **items;
C count;
Array() : items(NULL), count(0) {}
Array(int count) : count(count) {
if (count == 0) {
items = NULL;
return;
}
items = new T*[count];
for (int i = 0; i < count; i++)
items[i] = new T();
}
Array(Stream *stream) {
stream->read(count);
if (count == 0) {
items = NULL;
return;
}
items = new T*[count];
for (int i = 0; i < count; i++)
items[i] = new T(stream);
}
~Array() {
for (int i = 0; i < count; i++)
delete items[i];
delete[] items;
}
T* operator[] (int index) const {
return items[index];
}
};
template <typename T, typename C = int>
struct Vector {
T *items;
C count;
Vector(Stream *stream) {
stream->read(count);
if (count <= 0) {
items = NULL;
return;
}
items = (T*)malloc((int)count * sizeof(T));
stream->read(items, (int)count * sizeof(T));
}
Vector(Stream *stream, int count) : count(count) {
if (count <= 0) {
items = NULL;
return;
}
items = (T*)malloc((int)count * sizeof(T));
stream->read(items, (int)count * sizeof(T));
}
~Vector() {
if (items) free(items);
}
T& operator[] (int index) const {
ASSERT(index >= 0);
ASSERT(index < count);
return items[index];
}
};
#endif

22
src/win/OpenLara.sln Normal file
View File

@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2013 for Windows Desktop
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenLara", "OpenLara.vcxproj", "{6935E070-59B8-418A-9241-70BACB4217B5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6935E070-59B8-418A-9241-70BACB4217B5}.Debug|Win32.ActiveCfg = Debug|Win32
{6935E070-59B8-418A-9241-70BACB4217B5}.Debug|Win32.Build.0 = Debug|Win32
{6935E070-59B8-418A-9241-70BACB4217B5}.Release|Win32.ActiveCfg = Release|Win32
{6935E070-59B8-418A-9241-70BACB4217B5}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

108
src/win/OpenLara.vcxproj Normal file
View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{6935E070-59B8-418A-9241-70BACB4217B5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>OpenLara</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\bin\</OutDir>
<IncludePath>..\;$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\bin\</OutDir>
<GenerateManifest>false</GenerateManifest>
<IncludePath>..\;$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>NOMINMAX;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FloatingPointModel>Strict</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NOMINMAX;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FloatingPointModel>Strict</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>opengl32.lib;winmm.lib;wcrt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\core.h" />
<ClInclude Include="..\game.h" />
<ClInclude Include="..\input.h" />
<ClInclude Include="..\mesh.h" />
<ClInclude Include="..\shader.h" />
<ClInclude Include="..\texture.h" />
<ClInclude Include="..\utils.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

219
src/win/main.cpp Normal file
View File

@@ -0,0 +1,219 @@
#include "game.h"
DWORD getTime() {
#ifdef DEBUG
LARGE_INTEGER Freq, Count;
QueryPerformanceFrequency(&Freq);
QueryPerformanceCounter(&Count);
return (DWORD)(Count.QuadPart * 1000L / Freq.QuadPart);
#else
timeBeginPeriod(0);
return timeGetTime();
#endif
}
InputKey keyToInputKey(int code) {
int codes[] = {
VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_SPACE, VK_RETURN, VK_ESCAPE, VK_SHIFT, VK_CONTROL, VK_MENU,
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
};
for (int i = 0; i < sizeof(codes) / sizeof(codes[0]); i++)
if (codes[i] == code)
return (InputKey)(ikLeft + i);
return ikNone;
}
InputKey mouseToInputKey(int msg) {
return (msg >= WM_LBUTTONDOWN || msg <= WM_LBUTTONDBLCLK) ? ikMouseL :
(msg >= WM_RBUTTONDOWN || msg <= WM_RBUTTONDBLCLK) ? ikMouseR : ikMouseM;
}
#define JOY_DEAD_ZONE_STICK 0.3f
#define JOY_DEAD_ZONE_TRIGGER 0.01f
bool joyReady;
void joyInit() {
JOYINFOEX info;
info.dwSize = sizeof(info);
info.dwFlags = JOY_RETURNALL;
joyReady = joyGetPosEx(0, &info) == JOYERR_NOERROR;
}
void joyFree() {
joyReady = false;
memset(&Input::joy, 0, sizeof(Input::joy));
for (int ik = ikJoyA; ik <= ikJoyDP; ik++)
Input::down[ik] = false;
}
float joyAxis(int x, int xMin, int xMax) {
return ((x - xMin) / (float)(xMax - xMin)) * 2.0f - 1.0f;
}
vec2 joyDir(float ax, float ay) {
vec2 dir = vec2(ax, ay);
float dist = min(1.0f, dir.length());
if (dist < JOY_DEAD_ZONE_STICK) dist = 0;
return dir.normal() * dist;
}
void joyUpdate() {
if (!joyReady) return;
JOYINFOEX info;
info.dwSize = sizeof(info);
info.dwFlags = JOY_RETURNALL;
if (joyGetPosEx(0, &info) == JOYERR_NOERROR) {
JOYCAPS caps;
joyGetDevCaps(0, &caps, sizeof(caps));
Input::setPos(ikJoyL, joyDir(joyAxis(info.dwXpos, caps.wXmin, caps.wXmax),
joyAxis(info.dwYpos, caps.wYmin, caps.wYmax)));
if ((caps.wCaps & JOYCAPS_HASR) && (caps.wCaps & JOYCAPS_HASU))
Input::setPos(ikJoyR, joyDir(joyAxis(info.dwUpos, caps.wUmin, caps.wUmax),
joyAxis(info.dwRpos, caps.wRmin, caps.wRmax)));
if (caps.wCaps & JOYCAPS_HASZ) {
float z = joyAxis(info.dwZpos, caps.wZmin, caps.wZmax);
if (fabsf(z) > JOY_DEAD_ZONE_TRIGGER)
Input::setPos(z > 0.0f ? ikJoyLT : ikJoyRT, vec2(fabsf(z), 0.0f));
}
if (caps.wCaps & JOYCAPS_HASPOV && info.dwPOV != JOY_POVCENTERED)
Input::setPos(ikJoyDP, vec2((float)(1 + info.dwPOV / 4500), 0));
for (int i = 0; i < 10; i++)
Input::setDown((InputKey)(ikJoyA + i), (info.dwButtons & (1 << i)) > 0);
} else
joyFree();
}
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_ACTIVATE :
Input::reset();
break;
// keyboard
case WM_KEYDOWN :
case WM_KEYUP :
case WM_SYSKEYDOWN :
case WM_SYSKEYUP :
Input::setDown(keyToInputKey(wParam), msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN);
break;
// mouse
case WM_LBUTTONDOWN :
case WM_LBUTTONUP :
case WM_LBUTTONDBLCLK :
case WM_RBUTTONDOWN :
case WM_RBUTTONUP :
case WM_RBUTTONDBLCLK :
case WM_MBUTTONDOWN :
case WM_MBUTTONUP :
case WM_MBUTTONDBLCLK : {
InputKey key = mouseToInputKey(msg);
Input::setPos(key, vec2((float)(short)LOWORD(lParam), (float)(short)HIWORD(lParam)));
bool down = msg != WM_LBUTTONUP && msg != WM_RBUTTONUP && msg != WM_MBUTTONUP;
Input::setDown(key, down);
if (down)
SetCapture(hWnd);
else
ReleaseCapture();
break;
}
case WM_MOUSEMOVE :
Input::setPos(ikMouseL, vec2((float)(short)LOWORD(lParam), (float)(short)HIWORD(lParam)));
break;
// gamepad
case WM_DEVICECHANGE :
joyInit();
return 1;
// touch
// ...
case WM_SIZE :
Core::width = LOWORD(lParam);
Core::height = HIWORD(lParam);
break;
case WM_DESTROY :
PostQuitMessage(0);
break;
default :
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
HGLRC initGL(HDC hDC) {
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
int format = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, format, &pfd);
HGLRC hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
return hRC;
}
void freeGL(HGLRC hRC) {
wglMakeCurrent(0, 0);
wglDeleteContext(hRC);
}
int main() {
RECT r = { 0, 0, 1280, 720 };
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, false);
HWND hWnd = CreateWindow("static", "OpenLara", WS_OVERLAPPEDWINDOW, 0, 0, r.right - r.left, r.bottom - r.top, 0, 0, 0, 0);
joyInit();
HDC hDC = GetDC(hWnd);
HGLRC hRC = initGL(hDC);
Game::init();
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)&WndProc);
ShowWindow(hWnd, SW_SHOWDEFAULT);
DWORD time, lastTime = getTime();
MSG msg;
msg.message = WM_PAINT;
while (msg.message != WM_QUIT)
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
time = getTime();
if (time <= lastTime)
continue;
Core::deltaTime = (time - lastTime) * 0.001f;
lastTime = time;
joyUpdate();
Game::update();
Game::render();
SwapBuffers(hDC);
}
Game::free();
freeGL(hRC);
ReleaseDC(hWnd, hDC);
DestroyWindow(hWnd);
return 0;
}

BIN
src/win/wcrt.lib Normal file

Binary file not shown.