#define _SECURE_SCL 0
#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
#include <windows.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_main.h>
#include <SDL_opengl.h>
#include <glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include "tree.h"
#include "obj.h"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
#include <luabind/luabind.hpp>
#include <luabind/function.hpp>
#include <luabind/class.hpp>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
// Mouse UI Element Stuff
const int UITYPE_BUTTON = 1;
const int UITYPE_IMAGE = 2;
const int MAX_BUTTONS = 1000;
const int MIN_TICKSPERFRAME = 20;
typedef std::map <std::string, Uint16> tTexLinkNameToNum;
typedef std::map <Uint16, std::string> tTexLinkNumToName;
tTexLinkNameToNum texLinkNameToNum;
tTexLinkNumToName texLinkNumToName;
//typedef std::map <std::string, std::map> mapMap;
typedef std::map <std::string, std::string> mapString;
typedef std::map <std::string, int> mapInt;
typedef std::map <std::string, float> mapFloat;
typedef std::map <std::string, bool> mapBool;
//mapMap gameOpts;
mapString stringOpts;
mapInt intOpts;
mapFloat floatOpts;
mapBool boolOpts;
/*
gameOpts["string"] = stringOpts;
gameOpts["int"] = intOpts;
gameOpts["float"] = floatOpts;
gameOpts["bool"] = boolOpts;
*/
struct nsIntPoint
{
int x;
int y;
};
struct nsDblPoint
{
double x;
double y;
};
struct XYZ
{
double x;
double y;
double z;
};
struct nsTexture
{
std::string filename;
nsDblPoint scale;
nsDblPoint offset;
nsDblPoint ratio;
nsIntPoint tilesize;
SDL_Surface *pixels;
Uint16 textureID;
bool ready;
GLuint GLID;
};
std::vector<nsTexture> vecTex;
nsDblPoint ORIGIN;
nsIntPoint iORIGIN;
nsDblPoint ONEONE;
struct nsQuad
{
nsIntPoint screen;
nsIntPoint size;
int z;
nsDblPoint UV1;
nsDblPoint UV2;
Uint16 textureID;
Uint16 ID;
std::string name;
double alpha;
};
typedef std::vector<nsQuad> nsQuadList;
nsQuadList vecQuad;
nsQuadList UIQuad;
nsQuadList WorldQuad;
typedef std::map<std::string, std::string> FilesList;
typedef std::map<std::string, SDL_Surface*> _FilesList;
struct UIElem
{
std::string id;
std::map <std::string, std::string> events;
FilesList files;
_FilesList _files;
int texnum;
double x;
double y;
double tx;
double ty;
double szx;
double szy;
double osx;
double osy;
Uint16 sx;
Uint16 sy;
Uint16 visible;
double alpha;
unsigned long color;
std::string caption;
Uint16 type; // 0 = inert image | 1 = button
} ThisUI, UI[MAX_BUTTONS];
std::map <std::string, int> UImap;
typedef UIElem* UIElem_ptr;
// Sprite Struct Definition
typedef struct {
SDL_Surface *image;
SDL_Surface *bgsave;
Uint16 x;
Uint16 y;
Uint16 ox;
Uint16 oy;
} sprite, *sprite_ptr;
SDL_Surface *screen;
typedef SDL_Surface* SDL_SurfPtr;
int btnCount = 0;
int AbortApp = 0;
luabind::object *LG = new luabind::object;
SDL_Event event;
std::string luaStateFunc = "";
// Function declarations:
void RS_Blit(SDL_Surface *bitmap, Sint16 x, Sint16 y);
void play_game();
void draw_sprite(sprite *s);
void erase_sprite(sprite *s);
void report_errors(lua_State *L, int status);
SDL_Surface *prep_image(std::string *file);
static int AddUI( lua_State *L );
int InitTex(std::string filename, nsIntPoint tilesize);
void SetCurTex(std::string filename);
void reInitTex(std::string filename, Uint16 texIndex);
int AddQuad(nsQuadList &qvec, int textureID, int scrX, int scrY, double z, int sizeX, int sizeY, nsDblPoint UV1, nsDblPoint UV2, double alpha);
void drawQuads (nsQuadList const &quads, nsIntPoint offset);
int UI_setPos(lua_State *L);
int UI_setVisible(lua_State *L);
int UI_setAlpha(lua_State *L);
void camera (double xpos, double ypos, double zpos, double xrot, double yrot);
void drawsphere(int ndiv, float radius=1.0);
void drawtri(GLfloat *a, GLfloat *b, GLfloat *c, int div, float r);
void normalize(GLfloat *a);
void CreateSphere(XYZ c,double r,int n);
void glColorHex(unsigned long color, float alpha)
{
glColor4f ( (color >> 16) / 256.0,
(color >> 8 & 0xFF) / 256.0,
(color & 0xFF) / 256.0,
alpha);
}
void RS_Blit(SDL_Surface *bitmap, Sint16 x, Sint16 y) {
// Blits a surface onto the screen
SDL_Rect dest;
dest.x = x;
dest.y = y;
dest.w = bitmap->w;
dest.h = bitmap->h;
SDL_BlitSurface(bitmap, NULL, screen, &dest);
}
void get_bg(SDL_Surface *surface, Sint16 x, Sint16 y) {
/* Blits a surface sized chunk of background to the surface provided*/
SDL_Rect src;
SDL_Rect dst;
src.x = x;
src.y = y;
src.w = surface->w;
src.h = surface->h;
dst.x = 0;
dst.y = 0;
dst.w = surface->w;
dst.h = surface->h;
SDL_BlitSurface(screen, &src, surface, &dst);
}
SDL_Surface *prep_image(std::string *file) {
// Loads a bitmap image from disk and prepares it for use
SDL_Surface *image;
// image=SDL_LoadBMP(file->c_str());
image=IMG_Load(file->c_str());
if ( image == NULL ) {
fprintf(stderr, "Couldn't load %s: %s\n", file->c_str(), SDL_GetError());
return(NULL);
}
return(image);
}
void camera (double xpos, double ypos, double zpos, double xrot, double yrot) {
glRotatef(xrot,1.0,0.0,0.0); //rotate our camera on teh x-axis (left and right)
glRotatef(yrot,0.0,1.0,0.0); //rotate our camera on the y-axis (up and down)
glTranslated(-xpos,-ypos,-zpos); //translate the screen to the position of our camera
}
void DrawWorld() {
WorldQuad.clear();
/*
int t;
for (t = 0; t < btnCount; t++) {
FilesList::iterator p = UI[t].files.begin();
while (p != UI[t].files.end()) {
if (UI[t].visible > 0) {
int tex_sx = vecTex[UI[t].texnum].scale.x;
int tex_sy = vecTex[UI[t].texnum].scale.y;
nsDblPoint UV_ul;
nsDblPoint UV_br;
UV_ul.x = UI[t].tx / tex_sx;
UV_ul.y = UI[t].ty / tex_sy;
UV_br.x = (UI[t].tx + UI[t].szx) / tex_sx;
UV_br.y = (UI[t].ty + UI[t].szy) / tex_sy;
UI[t].sx = UI[t].szx * UI[t].osx;
UI[t].sy = UI[t].szy * UI[t].osy;
AddQuad(
WorldQuad,
UI[t].texnum,
UI[t].x,
UI[t].y,
-t * 0.1 ,
UI[t].sx,
UI[t].sy,
UV_ul,
UV_br,
UI[t].alpha);
}
p++;
}
}
*/
nsDblPoint UV_ul;
nsDblPoint UV_br;
UV_ul.x = 0;
UV_ul.y = 0;
UV_br.x = 1;
UV_br.y = 1;
AddQuad(
WorldQuad,
0,
-2000,
-2000,
0,
1,
1,
UV_ul,
UV_br,
1);
glCullFace( GL_BACK );
glFrontFace( GL_CCW );
glEnable( GL_CULL_FACE );
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// glOrtho(0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, -1.0, 10.0);
/*
double left, right;
double bottom, top;
double zfar, znear;
double FOV = 100;
double NEARPLANE = 1;
double FARPLANE = 1;
double ASPECT = SCREEN_WIDTH/SCREEN_HEIGHT;
top = tan (FOV*3.14159/360.0)*NEARPLANE;
bottom = -top;
left = ASPECT*bottom;
right = ASPECT*top;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum (left, right, bottom, top, NEARPLANE, FARPLANE);
*/
glEnable(GL_DEPTH_TEST);
gluPerspective (80, (GLfloat)SCREEN_WIDTH / (GLfloat)SCREEN_HEIGHT, 1.0, 1000.0); //set the perspective (angle of sight, width, height, , depth)
double rotx = luabind::object_cast<double>((*LG)["vy"]);
double roty = luabind::object_cast<double>((*LG)["vx"]);
camera (0,0,-10,rotx,roty);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawQuads(WorldQuad, iORIGIN);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
// drawsphere(3, 10);
XYZ t;
t.x = 0; t.y =0; t.z = -10;
glBindTexture(GL_TEXTURE_2D, vecTex[texLinkNameToNum["sky1.png"]].GLID);
glCullFace( GL_BACK );
glFrontFace( GL_CW );
glDisable( GL_CULL_FACE );
CreateSphere(t,850,20);
}
// UI Functions below
void LoadUI() {
// Loads all the images used by the UI Components
int t;
for (t = 0; t < btnCount; t++) {
FilesList::iterator p = UI[t].files.begin();
while (p != UI[t].files.end()) {
UI[t]._files[p->second] = prep_image(&p->second);
UI[t].sx = UI[t]._files[p->second]->w;
UI[t].sy = UI[t]._files[p->second]->h;
SDL_SetColorKey(UI[t]._files[p->second], SDL_SRCCOLORKEY|SDL_RLEACCEL,
SDL_MapRGB(UI[t]._files[p->second]->format, 0, 0, 255));
p++;
}
}
}
void DrawUI_2D() {
// Draws all the surfaces in a UI component list to screen.
int t;
for (t = 0; t < btnCount; t++) {
FilesList::iterator p = UI[t].files.begin();
while (p != UI[t].files.end()) {
if (UI[t].visible > 0) {
printf("drawing ui elem id: %s\n", UI[t].id.c_str());
RS_Blit(UI[t]._files[p->second], UI[t].x, UI[t].y);
}
p++;
}
}
}
void DrawUI() {
// Draws all the surfaces in a UI component list to screen.
UIQuad.clear();
int t;
glClear(GL_DEPTH_BUFFER_BIT);
glCullFace( GL_BACK );
glFrontFace( GL_CCW );
glEnable( GL_CULL_FACE );
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, -1000.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (t = 0; t < btnCount; t++) {
if (UI[t].visible > 0) {
if (UI[t].type == 3) {
// Text Element
// Text Element
glDisable(GL_TEXTURE_2D);
glColorHex(UI[t].color, UI[t].alpha);
glPushMatrix();glLoadIdentity();
glRasterPos3f(UI[t].x, UI[t].y, UI[t].tx);
for (int count=0; count <= UI[t].caption.length(); count++) {
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, UI[t].caption.c_str()[count]);
}
glPopMatrix();
} else {
int tex_sx = vecTex[UI[t].texnum].scale.x;
int tex_sy = vecTex[UI[t].texnum].scale.y;
nsDblPoint UV_ul;
nsDblPoint UV_br;
UV_ul.x = UI[t].tx / tex_sx;
UV_ul.y = UI[t].ty / tex_sy;
UV_br.x = (UI[t].tx + UI[t].szx) / tex_sx;
UV_br.y = (UI[t].ty + UI[t].szy) / tex_sy;
UI[t].sx = UI[t].szx * UI[t].osx;
UI[t].sy = UI[t].szy * UI[t].osy;
AddQuad(
UIQuad,
UI[t].texnum,
UI[t].x,
UI[t].y,
t ,
UI[t].sx,
UI[t].sy,
UV_ul,
UV_br,
UI[t].alpha);
}
}
}
drawQuads(UIQuad, iORIGIN);
}
void FreeUI() {
// Frees resources allocated by the supplied UI.
int t;
for (t = 0; t < btnCount; t++) {
FilesList::iterator p = UI[t].files.begin();
while (p != UI[t].files.end()) {
SDL_FreeSurface(UI[t]._files[p->second]);
p++;
}
}
}
void CheckUI(SDL_Event event, int x, int y, luabind::object *LG) {
int t;
std::vector<std::string> tfunclist;
for (t = 0; t < btnCount; t++) {
// FilesList::iterator p = UI[t].files.begin();
// while (p != UI[t].files.end()) {
if (UI[t].type == UITYPE_BUTTON) {
if (UI[t].visible > 0) {
if( (x>UI[t].x)&&(x < UI[t].x + UI[t].sx) ) {
if ((y>UI[t].y)&&(y < UI[t].y + UI[t].sy)) {
if (UI[t].events.find("click") != UI[t].events.end()) {
if (UI[t].events["click"] != "") {
tfunclist.push_back(UI[t].events["click"]);
// (*LG)["UIFunc"][UI[t].events["click"]]();
}
}
// (*LG)["StateAcON"]["Execute"]();
// AbortApp=1;
}
}
}
}
// p++;
// }
}
for (t = 0; t < tfunclist.size(); t++) {
(*LG)["UIFunc"][tfunclist[t]]();
}
}
// Lua Functions Below
void report_errors(lua_State *L, int status) {
if ( status!=0 ) {
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1); // remove error message
}
}
void play_game() {
// Main Control Loop
}
//static int AddUI( lua_State *L ) {
// printf("add ui");
// return 0;
//}
int UI_setVisible(lua_State *L)
{
// args:
// id (str): ID String
// visible (int): Visibility
// number of passed arguments
int argc = lua_gettop(L);
if (argc != 2) return luaL_error(L, "wrong number of arguments");
/* get first argument as int */
std::string _id = luaL_checkstring(L, 1);
int _visible = luaL_checknumber(L, 2);
// printf ("setting UI element id %s visibility to %d\n", _id.c_str(), _visible);
UIElem tbut1;
tbut1 = UI[UImap[_id]];
UI[UImap[_id]].visible = _visible;
// push return value (multiple return values are possible)
lua_pushnumber(L, (int)1);
// number of returned arguments
return 1;
}
int UI_setPos(lua_State *L)
{
// args:
// id (str): ID String
// newx (dbl): New X Position
// newy (dbl): New Y Position
// number of passed arguments
int argc = lua_gettop(L);
if (argc != 3) return luaL_error(L, "wrong number of arguments");
/* get first argument as int */
std::string _id = luaL_checkstring(L, 1);
double _newx = luaL_checknumber(L, 2);
double _newy = luaL_checknumber(L, 3);
// printf ("setting UI element id %s position to %f,%f\n", _id.c_str(), _newx, _newy);
UIElem tbut1;
tbut1 = UI[UImap[_id]];
UI[UImap[_id]].x = _newx;
UI[UImap[_id]].y = _newy;
// push return value (multiple return values are possible)
lua_pushnumber(L, (int)1);
// number of returned arguments
return 1;
}
int UI_setAlpha(lua_State *L)
{
// args:
// id (str): ID String
// alpha (int): New Alpha Value
// number of passed arguments
int argc = lua_gettop(L);
if (argc != 2) return luaL_error(L, "wrong number of arguments");
/* get first argument as int */
std::string _id = luaL_checkstring(L, 1);
double _alpha = luaL_checknumber(L, 2);
// printf ("setting UI element id %s visibility to %d\n", _id.c_str(), _visible);
UI[UImap[_id]].alpha = _alpha;
// push return value (multiple return values are possible)
lua_pushnumber(L, (int)1);
// number of returned arguments
return 1;
}
int AddUI(lua_State *L)
{
// args:
// id (str): ID String
// type (int): 1 = Button / 2 = Image / 3 = Text
// x, y (dbl): Location of upperleft corner of ui elem on screen
// tx, ty (dbl): Location on texture of upperleft corner of element
// szx, szy (dbl): Size (in pixels) of the element on its source texture
// osx, osy (dbl): Output scale (1 = 100%);
// src (str): Source image for bitmap elements
// group (str): Grouping ID
// visible (int): Visibility
// alpha (dbl): Alpha 0-1 : 1 = full opaque
// caption (str): For Text elements
// color (long): For Text elements
// click (str): Click handler function
// number of passed arguments
int argc = lua_gettop(L);
if (argc != 17) return luaL_error(L, "wrong number of arguments");
/* get first argument as int */
std::string _id = luaL_checkstring(L, 1);
int _type = luaL_checknumber(L, 2);
double _x = luaL_checknumber(L, 3);
double _y = luaL_checknumber(L, 4);
double _tx = luaL_checknumber(L, 5);
double _ty = luaL_checknumber(L, 6);
double _szx = luaL_checknumber(L, 7);
double _szy = luaL_checknumber(L, 8);
double _osx = luaL_checknumber(L, 9);
double _osy = luaL_checknumber(L, 10);
std::string _src = luaL_checkstring(L, 11);
std::string _group = luaL_checkstring(L, 12);
int _visible = luaL_checkint(L, 13);
double _alpha = luaL_checknumber(L, 14);
std::string _caption = luaL_checkstring(L, 15);
unsigned long _color = luaL_checknumber(L, 16);
std::string _click = luaL_checkstring(L, 17);
int texnum = -1;
if (texLinkNameToNum.find(_src) != texLinkNameToNum.end()) {
texnum = texLinkNameToNum[_src];
} else {
printf ("Attempting to load texture file: %s\n", _src.c_str());
nsIntPoint tp1;
tp1.x = 0;
tp1.y = 0;
texnum = InitTex(_src, tp1);
}
printf ("creating UI element id %s at (%f,%f)\n", _id.c_str(), _x, _y);
UIElem tbut1;
tbut1.id = _id;
tbut1.type = _type;
tbut1.caption = _caption;
tbut1.color = _color;
tbut1.events["click"] = _click;
tbut1.files["bg"] = _src;
tbut1.texnum = texnum;
tbut1.alpha = _alpha;
tbut1.visible = _visible;
tbut1.x = _x;
tbut1.y = _y;
tbut1.tx = _tx;
tbut1.ty = _ty;
tbut1.szx = _szx;
tbut1.szy = _szy;
tbut1.osx = _osx;
tbut1.osy = _osy;
UI[btnCount] = tbut1;
if (_id != "") {
UImap[_id] = btnCount;
}
btnCount++;
// push return value (multiple return values are possible)
lua_pushnumber(L, (int)1);
// number of returned arguments
return 1;
}
// 3D Drawing Functions
void drawQuads (nsQuadList const &quads, nsIntPoint offset)
{
int lasttex = -1;
glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// printf("Drawing quadlist with (%d) elements...\n", quads.size());
for( Uint16 i = 0; i < quads.size(); i++ ) {
int curtex = quads[i].textureID;
if (curtex != lasttex) {
// printf("Binding Texture ID(%d) : %s\n", quads[i].textureID, texLinkNumToName[quads[i].textureID].c_str());
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, vecTex[quads[i].textureID].GLID);
}
lasttex = quads[i].textureID;
glDisable(GL_LIGHTING);
glDisable(GL_NORMALIZE);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
//
glTranslatef(quads[i].screen.x+offset.x, quads[i].screen.y+offset.y, 0.0f);
// printf("Translating to (%d, %d)\n", quads[i].screen.x+offset.x, quads[i].screen.y+offset.y);
// glRotatef(tile_rot, 0.0, 0.0, 1.0);
// glTranslatef(-1.0 * (TILE_WIDTH / 2), -1.0 * (TILE_HEIGHT / 2), 0.0);
// std::cout << "test";
// printf("Creating quad size (%d, %d)\n", quads[i].size.x, quads[i].size.y);
int z= quads[i].z;
glBegin(GL_QUADS);
glColor4f(1.0f, 1.0f, 1.0f, quads[i].alpha);
glTexCoord2f(quads[i].UV1.x, quads[i].UV2.y);
glVertex3f(0.0f, quads[i].size.y, z);
glTexCoord2f(quads[i].UV2.x, quads[i].UV2.y);
glVertex3f(quads[i].size.x, quads[i].size.y, z);
glTexCoord2f(quads[i].UV2.x, quads[i].UV1.y);
glVertex3f(quads[i].size.x, 0.0f, z);
glTexCoord2f(quads[i].UV1.x, quads[i].UV1.y);
glVertex3f(0.0f, 0.0f, z);
glEnd();
glLoadIdentity();
}
}
void reloadAllTex() {
for (int t = 0; t< vecTex.size(); t++) {
printf("Reloading Texture: %s\n", vecTex[t].filename.c_str());
reInitTex(vecTex[t].filename, t);
}
}
void reInitTex(std::string filename, Uint16 texIndex) {
nsTexture tTx;
tTx.filename = filename;
tTx.offset = ORIGIN;
tTx.ready = false;
tTx.textureID = texIndex;
texLinkNameToNum[tTx.filename] = tTx.textureID;
texLinkNumToName[tTx.textureID] = tTx.filename;
tTx.pixels = IMG_Load(tTx.filename.c_str());
glGenTextures(1, &tTx.GLID);
glBindTexture(GL_TEXTURE_2D, tTx.GLID);
glTexImage2D(GL_TEXTURE_2D, 0, 4, tTx.pixels->w, tTx.pixels->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tTx.pixels->pixels);
gluBuild2DMipmaps( GL_TEXTURE_2D, 4, tTx.pixels->w, tTx.pixels->h, GL_RGBA, GL_UNSIGNED_BYTE, tTx.pixels->pixels );
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tTx.pixels->w, tTx.pixels->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tTx.pixels->pixels);
if (glGetError() != GL_NO_ERROR)
{
if (glGetError() == GL_OUT_OF_MEMORY) {
printf("Out Of Video Memory\n");
} else {
printf("Invalid Image data - Error Code: %d\n", glGetError());
}
} else {
tTx.ready = true;
}
tTx.ratio.x = (double)1 / tTx.pixels->w;
tTx.ratio.y = (double)1 / tTx.pixels->h;
tTx.scale.x = tTx.pixels->w;
tTx.scale.y = tTx.pixels->h;
vecTex[texIndex] = tTx;
std::cout<< "Reloaded texture "<< tTx.filename << " with textureID: " << tTx.textureID << " and GLID: "<< tTx.GLID << std::endl;
}
int InitTex(std::string filename, nsIntPoint tilesize) {
nsTexture tTx;
tTx.filename = filename;
tTx.offset = ORIGIN;
tTx.ready = false;
tTx.textureID = vecTex.size();
texLinkNameToNum[tTx.filename] = tTx.textureID;
texLinkNumToName[tTx.textureID] = tTx.filename;
tTx.pixels = IMG_Load(tTx.filename.c_str());
glGenTextures(1, &tTx.GLID);
glBindTexture(GL_TEXTURE_2D, tTx.GLID);
glTexImage2D(GL_TEXTURE_2D, 0, 4, tTx.pixels->w, tTx.pixels->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tTx.pixels->pixels);
gluBuild2DMipmaps( GL_TEXTURE_2D, 4, tTx.pixels->w, tTx.pixels->h, GL_RGBA, GL_UNSIGNED_BYTE, tTx.pixels->pixels );
// glTexImage2D(GL_TEXTURE_2D, 3, 4, tTx.pixels->w, tTx.pixels->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tTx.pixels->pixels);
// glTexImage2D(GL_TEXTURE_2D, 3, 3, mobo->w, mobo->h, 0 , GL_RGB, GL_UNSIGNED_BYTE, mobo->pixels);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tTx.pixels->w, tTx.pixels->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tTx.pixels->pixels);
if (glGetError() != GL_NO_ERROR)
{
if (glGetError() == GL_OUT_OF_MEMORY) {
printf("Out Of Video Memory\n");
} else {
printf("Invalid Image data - Error Code: %d\n", glGetError());
}
return -1;
} else {
tTx.ready = true;
}
tTx.ratio.x = (double)1 / tTx.pixels->w;
tTx.ratio.y = (double)1 / tTx.pixels->h;
tTx.scale.x = tTx.pixels->w;
tTx.scale.y = tTx.pixels->h;
tTx.tilesize = tilesize;
vecTex.push_back(tTx);
std::cout<< "Added texture "<< tTx.filename << " with textureID: " << tTx.textureID << " and GLID: "<< tTx.GLID << std::endl;
return (tTx.textureID);
}
void SetCurTex(std::string filename){
int tnum = 0;
if (texLinkNameToNum.find(filename) == texLinkNameToNum.end()) {
// Init Tex
printf("loading uninitialized texture %s\n", filename.c_str());
tnum = InitTex(filename, iORIGIN);
} else {
tnum = texLinkNameToNum[filename];
}
glEnable(GL_TEXTURE_2D);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, vecTex[tnum].GLID);
}
int AddQuad(nsQuadList &qvec, int textureID, int scrX, int scrY, double z, int sizeX, int sizeY, nsDblPoint UV1, nsDblPoint UV2, double alpha){
nsQuad tQd;
tQd.ID = vecQuad.size()+1;
tQd.screen.x = scrX;
tQd.screen.y = scrY;
tQd.z = z;
tQd.size.x = sizeX;
tQd.size.y = sizeY;
tQd.UV1 = UV1;
tQd.UV2 = UV2;
tQd.textureID = textureID;
tQd.alpha = alpha;
qvec.push_back(tQd);
return tQd.ID;
}
int main(int argc, char *argv[])
// App Entry Point
//int _tmain(int argc, _TCHAR* argv[])
{
SDL_Event event;
Uint8 *keys;
int x, y;
int ox, oy;
int done=0, translucent=0;
int curTicks = SDL_GetTicks()-1;
int lastTicks = curTicks;
int thisTicks = curTicks - lastTicks;
double MOVEPERTICK = 0.2;
double lastFPS = 0;
Uint8 * key_states = NULL;
bool mouse_down = false;
bool quit = false;
bool MouseVis = true;
GLfloat tile_rot = 0.0f;
GLfloat tile_x = 0.0f;
GLfloat tile_y = 0.0f;
ORIGIN.x = 0;
ORIGIN.y = 0;
iORIGIN.x = 0;
iORIGIN.y = 0;
ONEONE.x = 1;
ONEONE.y = 1;
boolOpts["FULLSCREEN"] = false;
char* memory = NULL;
size_t bytes = ObjLoadFile("island.obj", &memory);
ObjModel* model = new ObjModel;
model = ObjLoadModel(memory, bytes);
printf("Object Model has: %d faces!\n", model->nTriangle);
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr,
"Couldn't initialize SDL: %s\n", SDL_GetError());
exit(1);
}
/*
if( argc > 2) {
printf("options: --fullscreen");
return(0);
}
if( argc==2) {
if(!strcmp(argv[1], "--fullscreen")) {
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE|SDL_FULLSCREEN);
}
else {
printf("options: --fullscreen");
return(0);
}
}
else {
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
}
*/
// ** SDL GL INIT FUNC
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 8 );
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// initialize opengl
// create window
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL);
// screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_FULLSCREEN);
SDL_WM_SetCaption("beaBird 0.1", NULL);
/*
glClearColor(0.0f, 0.5f, 0.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f);
*/
printf("Creating device context sized (%d, %d)\n", SCREEN_WIDTH, SCREEN_HEIGHT);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SDL_GL_SwapBuffers();
glEnable(GL_TEXTURE_2D);
glShadeModel( GL_SMOOTH );
glCullFace( GL_BACK );
glFrontFace( GL_CCW );
glEnable( GL_CULL_FACE );
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// glOrtho(SCREEN_WIDTH * -1, SCREEN_WIDTH, SCREEN_HEIGHT * -1, SCREEN_HEIGHT, -10.0, 10.0);
glOrtho(0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, -1000.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat global_ambient[] = { 0.35f, 0.35f, 0.35f, 1.0f };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
GLfloat specular[] = {1.0f, 1.0f, 1.0f , 1.0f};
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
GLfloat diffuse[] = {0.8f, 0.8f, 0.8f , 1.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
GLfloat position[] = {2.0f, 10.0f, -15.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, position);
GLfloat ambient2[] = {0.5,0.25,0.25,1};
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 25.0);
//can set params for front and back separately (GL_BACK, GL_FRONT_AND_BACK)
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient2);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
/* Initialize the display in a 640x480 8-bit palettized mode */
if ( screen == NULL ) {
fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
SDL_GetError());
exit(1);
}
// *** EXECUTE LUA START UP SCRIPT
const char* file = "lua/test.lua";
lua_State *L = lua_open();
luaL_openlibs(L);
std::cerr << "-- Loading file: " << file << std::endl;
int s = luaL_loadfile(L, file);
*LG = luabind::globals(L);
lua_register(L, "AddUI", AddUI);
lua_register(L, "UI_setVisible", UI_setVisible);
lua_register(L, "UI_setPos", UI_setPos);
lua_register(L, "UI_setAlpha", UI_setAlpha);
if ( s==0 ) {
// execute Lua program
s = lua_pcall(L, 0, LUA_MULTRET, 0);
}
/* Hide the existing cursor *///
SDL_ShowCursor(0);
x=0;y=0;
SDL_GetMouseState(&x, &y);
MouseVis = true;
if ((x == 0) && (y == 0)) {
MouseVis = false;
}
do {
lastTicks = curTicks;
curTicks = SDL_GetTicks();
thisTicks = curTicks - lastTicks;
SDL_GetMouseState(&x, &y);
(*LG)["MOVEPERTICK"] = MOVEPERTICK;
(*LG)["thisTicks"] = thisTicks;
(*LG)["mouseVis"] = MouseVis;
(*LG)["mouseX"] = x;
(*LG)["mouseY"] = y;
luaStateFunc = luabind::object_cast<std::string>((*LG)["curStateFunc"]);
if (luaStateFunc != "") { (*LG)["StateFunc"][luaStateFunc](); }
while ( SDL_PollEvent(&event) ) {
ox = x; oy = y; /* Save old values for erasing the cursor */
switch (event.type)
{
case SDL_APPMOUSEFOCUS:
if (event.active.gain == 1) {
std::cout << "got mouse" << std::endl;
MouseVis = true;
} else {
std::cout << "lost mouse" << std::endl;
MouseVis = false;
}
break;
case SDL_MOUSEMOTION:
if (mouse_down)
{
tile_rot += event.motion.xrel;
}
break;
case SDL_MOUSEBUTTONDOWN:
mouse_down = true;
CheckUI(event, x, y, LG);
break;
case SDL_MOUSEBUTTONUP:
mouse_down = false;
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
{
quit = true;
}
break;
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_TAB)
{
(*LG)["PlayerFunc"]["ToggleDebug"]();
if (boolOpts["FULLSCREEN"] == true) {
boolOpts["FULLSCREEN"] = false;
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL);
reloadAllTex();
} else {
boolOpts["FULLSCREEN"] = true;
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_FULLSCREEN);
reloadAllTex();
}
}
break;
case SDL_QUIT:
quit = true;
}
}
// check key states
key_states = SDL_GetKeyState(NULL);
if (key_states[SDLK_LEFT])
{
(*LG)["PlayerFunc"]["MoveLeft"]();
}
if (key_states[SDLK_RIGHT])
{
(*LG)["PlayerFunc"]["MoveRight"]();
}
if (key_states[SDLK_UP])
{
(*LG)["PlayerFunc"]["MoveUp"]();
}
if (key_states[SDLK_DOWN])
{
(*LG)["PlayerFunc"]["MoveDown"]();
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw 3d Text Here
DrawWorld();
glLoadIdentity();
glColorHex(0xFFFFFF, 1.0f);
glDisable( GL_CULL_FACE );
// glEnable( GL_DEPTH_TEST );
// glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_POLYGON_SMOOTH);
glEnable(GL_LIGHT0);
glFrontFace( GL_CCW );
glTranslatef(0.0f, -5.0f, 0.0f);
glScalef(20.0f, 20.0f, 20.0f);
/*
printf("First Tri vert1=(%f, %f, %f)\n",
model->VertexArray[model->TriangleArray[2].Vertex[0]].x,
model->VertexArray[model->TriangleArray[2].Vertex[0]].y,
model->VertexArray[model->TriangleArray[2].Vertex[0]].z
);
printf(" vert2=(%f, %f, %f)\n",
model->VertexArray[model->TriangleArray[2].Vertex[1]].x,
model->VertexArray[model->TriangleArray[2].Vertex[1]].y,
model->VertexArray[model->TriangleArray[2].Vertex[1]].z
);
printf(" vert3=(%f, %f, %f)\n",
model->VertexArray[model->TriangleArray[2].Vertex[2]].x,
model->VertexArray[model->TriangleArray[2].Vertex[2]].y,
model->VertexArray[model->TriangleArray[2].Vertex[2]].z
);
*/
int curface =0;
for (int tb=1; tb< model->nBreak+1; tb++) {
int breakAt = model->BreakArray[tb].breakAt;
std::string newTexName = model->Materials->MaterialArray[model->BreakArray[tb].newTexNum].diffuseMap;
SetCurTex(newTexName);
// printf("%s\n", newTexName.c_str());
//glDisable(GL_TEXTURE_2D);
glBegin(GL_TRIANGLES);
for (int t=curface; t< breakAt; t++){
// for (int t=0; t< model->nTriangle ; t++){
// printf(".%d.", t);
// glNormal3f(e.x,e.y,e.z);
ObjTriangle objTri = model->TriangleArray[t];
// glNormal3f(
// model->NormalArray[objTri.Normal[0]-1].x,
// model->NormalArray[objTri.Normal[0]-1].y,
// model->NormalArray[objTri.Normal[0]-1].z
// );
glNormal3f(
model->VertexArray[objTri.Vertex[0]-1].normal.x,
model->VertexArray[objTri.Vertex[0]-1].normal.y,
model->VertexArray[objTri.Vertex[0]-1].normal.z
);
glTexCoord2f(
model->TexCoordArray[objTri.TexCoord[0]-1].u,
model->TexCoordArray[objTri.TexCoord[0]-1].v
);
glVertex3f(
model->VertexArray[objTri.Vertex[0]-1].x,
model->VertexArray[objTri.Vertex[0]-1].y,
model->VertexArray[objTri.Vertex[0]-1].z
);
// glNormal3f(
// model->NormalArray[objTri.Normal[1]-1].x,
// model->NormalArray[objTri.Normal[1]-1].y,
// model->NormalArray[objTri.Normal[1]-1].z
// );
glNormal3f(
model->VertexArray[objTri.Vertex[1]-1].normal.x,
model->VertexArray[objTri.Vertex[1]-1].normal.y,
model->VertexArray[objTri.Vertex[1]-1].normal.z
);
glTexCoord2f(
model->TexCoordArray[objTri.TexCoord[1]-1].u,
model->TexCoordArray[objTri.TexCoord[1]-1].v
);
glVertex3f(
model->VertexArray[objTri.Vertex[1]-1].x,
model->VertexArray[objTri.Vertex[1]-1].y,
model->VertexArray[objTri.Vertex[1]-1].z
);
// glNormal3f(
// model->NormalArray[objTri.Normal[2]-1].x,
// model->NormalArray[objTri.Normal[2]-1].y,
// model->NormalArray[objTri.Normal[2]-1].z
// );
glNormal3f(
model->VertexArray[objTri.Vertex[2]-1].normal.x,
model->VertexArray[objTri.Vertex[2]-1].normal.y,
model->VertexArray[objTri.Vertex[2]-1].normal.z
);
glTexCoord2f(
model->TexCoordArray[objTri.TexCoord[2]-1].u,
model->TexCoordArray[objTri.TexCoord[2]-1].v
);
glVertex3f(
model->VertexArray[objTri.Vertex[2]-1].x,
model->VertexArray[objTri.Vertex[2]-1].y,
model->VertexArray[objTri.Vertex[2]-1].z
);
}
glEnd();
}
DrawUI();
// Draw 2d Text Here
SDL_GL_SwapBuffers();
int pauseTicks = MIN_TICKSPERFRAME - (SDL_GetTicks()-curTicks);
if (pauseTicks > 0) {
Sleep(pauseTicks);
// printf("%d.", pauseTicks);
}
if (AbortApp == 0) { AbortApp = luabind::object_cast<int>((*LG)["AbortApp"]); }
} while(!AbortApp);
/* Free the surfaces */
// delete UI;
FreeUI();
// SDL_FreeSurface(button1);
// SDL_FreeSurface(button2);
// SDL_FreeSurface(cursor);
// SDL_FreeSurface(cursor_save);
SDL_Quit();
// free(model->NormalArray);
// free(model->TexCoordArray);
// free(model->TriangleArray);
// free(model->VertexArray);
// free(model);
report_errors(L, s);
lua_close(L);
exit(0);
}
// Quick N Dirty Sphere
#define X .525731112119133606
#define Z .850650808352039932
static GLfloat vdata[12][3] = {
{-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
{0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
{Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
};
static GLuint tindices[20][3] = {
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
void normalize(GLfloat *a) {
GLfloat d=sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
a[0]/=d; a[1]/=d; a[2]/=d;
}
void drawtri(GLfloat *a, GLfloat *b, GLfloat *c, int div, float r) {
if (div<=0) {
glNormal3fv(a); glVertex3f(a[0]*r, a[1]*r, a[2]*r);
glNormal3fv(b); glVertex3f(b[0]*r, b[1]*r, b[2]*r);
glNormal3fv(c); glVertex3f(c[0]*r, c[1]*r, c[2]*r);
} else {
GLfloat ab[3], ac[3], bc[3];
for (int i=0;i<3;i++) {
ab[i]=(a[i]+b[i])/2;
ac[i]=(a[i]+c[i])/2;
bc[i]=(b[i]+c[i])/2;
}
normalize(ab); normalize(ac); normalize(bc);
drawtri(a, ab, ac, div-1, r);
drawtri(b, bc, ab, div-1, r);
drawtri(c, ac, bc, div-1, r);
drawtri(ab, bc, ac, div-1, r); //<--Comment this line and sphere looks really cool!
}
}
void drawsphere(int ndiv, float radius) {
glBegin(GL_TRIANGLES);
for (int i=0;i<20;i++)
drawtri(vdata[tindices[i][0]], vdata[tindices[i][1]], vdata[tindices[i][2]], ndiv, radius);
glEnd();
}
/// Dirty dirty sphere #2
#define PI 3.141592654
#define PID2 3.141592654/2
#define TWOPI 6.283185308
void CreateSphere(XYZ c,double r,int n)
{
int i,j;
double theta1,theta2,theta3;
XYZ e,p;
if (r < 0)
r = -r;
if (n < 0)
n = -n;
if (n < 4 || r <= 0) {
glBegin(GL_POINTS);
glVertex3f(c.x,c.y,c.z);
glEnd();
return;
}
for (j=0;j<n/2;j++) {
theta1 = j * TWOPI / n - PID2;
theta2 = (j + 1) * TWOPI / n - PID2;
glBegin(GL_QUAD_STRIP);
for (i=0;i<=n;i++) {
theta3 = i * TWOPI / n;
e.x = cos(theta2) * cos(theta3);
e.y = sin(theta2);
e.z = cos(theta2) * sin(theta3);
p.x = c.x + r * e.x;
p.y = c.y + r * e.y;
p.z = c.z + r * e.z;
glNormal3f(e.x,e.y,e.z);
glTexCoord2f(i/(double)n,2*(j+1)/(double)n);
glVertex3f(p.x,p.y,p.z);
e.x = cos(theta1) * cos(theta3);
e.y = sin(theta1);
e.z = cos(theta1) * sin(theta3);
p.x = c.x + r * e.x;
p.y = c.y + r * e.y;
p.z = c.z + r * e.z;
glNormal3f(e.x,e.y,e.z);
glTexCoord2f(i/(double)n,2*j/(double)n);
glVertex3f(p.x,p.y,p.z);
}
glEnd();
}
}
//--------------------------------------------------
#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include "obj.h"
MatLib* MatLoadLib(char *memory, size_t size)
{
char* p = NULL, * e = NULL;
// MatLib* ret = (MatLib*) calloc(1, sizeof(MatLib)); memset(ret, 0, sizeof(MatLib));
MatLib *ret = new MatLib;
ret->nMaterial = 0;
p = memory;
e = memory + size;
while (p != e)
{
if (memcmp(p, "newmtl", 6) == 0) ret->nMaterial++;
while (*p++ != (char) 0x0A);
}
// ret->MaterialArray = (ObjMaterial*) malloc(sizeof(ObjMaterial) * (ret->nMaterial+1));
ret->MaterialArray.resize(ret->nMaterial+1);
p = memory;
printf("%d materials found...\n", ret->nMaterial);
int nMl = 0;
while (p != e)
{
if (memcmp(p, "newmtl", 6) == 0)
{
// Next Material
nMl++;
char matNameC[100];
sscanf(p, "newmtl %s%*s", &matNameC);
std::string matName = matNameC;
printf("new material (%d): __%s__\n", nMl, matName.c_str());
ret->MaterialArray[nMl].name = matName;
printf ("xxx\n");
// ret->nameLookup[matName] = nMl;
// (*ret).nameLookup.insert(std::make_pair( matName, nMl));
}
if (memcmp(p, "Ns", 2) == 0)
{
sscanf(p, "Ns %f", &ret->MaterialArray[nMl].Ns);
}
if (memcmp(p, "Ka", 2) == 0)
{
sscanf(p, "Ka %f %f %f", &ret->MaterialArray[nMl].ambient.r, &ret->MaterialArray[nMl].ambient.r, &ret->MaterialArray[nMl].ambient.g, &ret->MaterialArray[nMl].ambient.b);
}
if (memcmp(p, "Kd", 2) == 0)
{
sscanf(p, "Kd %f %f %f", &ret->MaterialArray[nMl].diffuse.r, &ret->MaterialArray[nMl].ambient.r, &ret->MaterialArray[nMl].diffuse.g, &ret->MaterialArray[nMl].diffuse.b);
}
if (memcmp(p, "Ks", 2) == 0)
{
sscanf(p, "Ks %f %f %f", &ret->MaterialArray[nMl].specular.r, &ret->MaterialArray[nMl].ambient.r, &ret->MaterialArray[nMl].specular.g, &ret->MaterialArray[nMl].specular.b);
}
if (memcmp(p, "Ni", 2) == 0)
{
sscanf(p, "Ni %f", &ret->MaterialArray[nMl].Ni);
}
if (memcmp(p, "d ", 2) == 0)
{
sscanf(p, "d %f", &ret->MaterialArray[nMl].d);
}
if (memcmp(p, "illum", 5) == 0)
{
sscanf(p, "illum %f", &ret->MaterialArray[nMl].illum);
}
if (memcmp(p, "map_Kd", 6) == 0)
{
char texNameC[100];
sscanf(p, "map_Kd %s%*s", &texNameC);
std::string texName = texNameC;
printf("texture name: __%s__\n", texName.c_str());
ret->MaterialArray[nMl].diffuseMap = texName;
}
while (*p++ != (char) 0x0A);
}
return ret;
}
ObjModel* ObjLoadModel(char* memory, size_t size)
{
char* p = NULL, * e = NULL;
ObjModel *ret = new ObjModel;
ret->nNormal = 0;
ret->nTexCoord = 0;
ret->nVertex = 0;
ret->nTriangle = 0;
ret->nBreak = 0;
// ObjModel* ret = (ObjModel*) calloc(1, sizeof(ObjModel));
// memset(ret, 0, sizeof(ObjModel));
p = memory;
e = memory + size;
while (p != e)
{
if (memcmp(p, "vn", 2) == 0) ret->nNormal++;
else if (memcmp(p, "vt", 2) == 0) ret->nTexCoord++;
else if (memcmp(p, "v", 1) == 0) ret->nVertex++;
else if (memcmp(p, "f", 1) == 0) ret->nTriangle++;
else if (memcmp(p, "usemtl", 1) == 0) ret->nBreak++;
while (*p++ != (char) 0x0A);
}
// ret->VertexArray = (ObjVertex*) malloc(sizeof(ObjVertex) * ret->nVertex);
// ret->NormalArray = (ObjNormal*) malloc(sizeof(ObjNormal) * ret->nNormal);
// ret->TexCoordArray = (ObjTexCoord*) malloc(sizeof(ObjTexCoord) * ret->nTexCoord);
// ret->TriangleArray = (ObjTriangle*) malloc(sizeof(ObjTriangle) * ret->nTriangle);
// ret->BreakArray = (ObjBreak*) malloc(sizeof(ObjBreak) * (ret->nBreak+1));
ret->VertexArray.resize(ret->nVertex+1);
ret->NormalArray.resize(ret->nNormal+1);
ret->TexCoordArray.resize(ret->nTexCoord+1);
ret->TriangleArray.resize(ret->nTriangle+1);
ret->BreakArray.resize(ret->nBreak+1);
p = memory;
// char* matLibFilename = "";
int nV = 0, nN = 0, nT = 0, nF = 0, nMl = 0, nB = 0;
while (p != e)
{
if (memcmp(p, "mtllib", 6) == 0)
{
char matLibName[100];
sscanf(p, "mtllib %s%*s", &matLibName);
nMl++;
std::string matLibFilename = matLibName;
printf("using material library: __%s__\n", matLibFilename.c_str());
char* memory = NULL;
size_t bytes = ObjLoadFile(matLibName, &memory);
ret->Materials = MatLoadLib(memory, bytes);
// &ret->Materials = materials;
}
if (memcmp(p, "usemtl", 6) == 0)
{
char newMatNameC[100];
sscanf(p, "usemtl %s%*s", &newMatNameC);
std::string newMatName = newMatNameC;
printf("Switching to material: %s ...\n", newMatName.c_str());
ret->BreakArray[nB].breakAt = nF;
nB++;
int switchto = 0;
for (int t = 1; t < ret->Materials->nMaterial+1; t++){
printf ("%d (%s): ", t, newMatName.c_str());
printf ("%s\n", ret->Materials->MaterialArray[t].name.c_str());
if (ret->Materials->MaterialArray[t].name == newMatName) {
printf("found break %d tex lookup for mat = %d\n", nB, t);
switchto = t;
}
}
ret->BreakArray[nB].newTexNum = switchto;
}
if (memcmp(p, "vn", 2) == 0)
{
sscanf(p, "vn %f %f %f", &ret->NormalArray[nN].x,
&ret->NormalArray[nN].y,
&ret->NormalArray[nN].z);
nN++;
}
else if (memcmp(p, "vt", 2) == 0)
{
sscanf(p, "vt %f %f", &ret->TexCoordArray[nT].u,
&ret->TexCoordArray[nT].v);
nT++;
}
else if (memcmp(p, "v", 1) == 0) /* or *p == 'v' */
{
sscanf(p, "v %f %f %f", &ret->VertexArray[nV].x,
&ret->VertexArray[nV].y,
&ret->VertexArray[nV].z);
nV++;
}
else if (memcmp(p, "f", 1) == 0) /* or *p == 'f' */
{
sscanf(p, "f %d/%d/%d %d/%d/%d %d/%d/%d", &ret->TriangleArray[nF].Vertex[0],
&ret->TriangleArray[nF].TexCoord[0],
&ret->TriangleArray[nF].Normal[0],
&ret->TriangleArray[nF].Vertex[1],
&ret->TriangleArray[nF].TexCoord[1],
&ret->TriangleArray[nF].Normal[1],
&ret->TriangleArray[nF].Vertex[2],
&ret->TriangleArray[nF].TexCoord[2],
&ret->TriangleArray[nF].Normal[2]);
ret->VertexArray[ret->TriangleArray[nF].Vertex[0]].faces.push_back(nF);
ret->VertexArray[ret->TriangleArray[nF].Vertex[1]].faces.push_back(nF);
ret->VertexArray[ret->TriangleArray[nF].Vertex[2]].faces.push_back(nF);
nF++;
}
while (*p++ != (char) 0x0A);
}
for (int t= 0; t< ret->VertexArray.size(); t++) {
ObjNormal nS, nSA;
nS.x = 0;
nS.y = 0;
nS.z = 0;
int numF = 0;
for (int f= 0; f< ret->VertexArray[t].faces.size(); f++) {
ObjNormal n1,n2,n3, nA;
n1 = ret->NormalArray[ret->TriangleArray[ret->VertexArray[t].faces[f]].Normal[0]];
n2 = ret->NormalArray[ret->TriangleArray[ret->VertexArray[t].faces[f]].Normal[1]];
n3 = ret->NormalArray[ret->TriangleArray[ret->VertexArray[t].faces[f]].Normal[2]];
nA.x = (n1.x + n2.x + n3.x)/ 3;
nA.y = (n1.y + n2.y + n3.y)/ 3;
nA.z = (n1.z + n2.z + n3.z)/ 3;
nS.x += nA.x;
nS.y += nA.y;
nS.z += nS.z;
numF=numF+1;
}
nSA.x = nS.x / numF;
nSA.y = nS.y / numF;
nSA.z = nS.z / numF;
ret->VertexArray[t].normal = nSA;
}
ret->BreakArray[nB].breakAt = nF;
return ret;
}
size_t ObjLoadFile(char* szFileName, char** memory)
{
size_t bytes = 0;
FILE* file = fopen(szFileName, "rt");
if (file != NULL)
{
fseek(file, 0, SEEK_END);
size_t end = ftell(file);
fseek(file, 0, SEEK_SET);
*memory = (char*) malloc(end);
bytes = fread(*memory, sizeof(char), end, file);
fclose(file);
}
return bytes;
}
//------------------------------------------------------------------
#include <stdlib.h>
#include <string>
#include <vector>
#include <map>
#ifndef OBJ_H
#define OBJ_H
typedef std::map <std::string, int> tNameToNum;
typedef std::vector <int> intList;
typedef struct
{
float x, y, z;
} ObjVec;
typedef struct
{
float x, y, z;
intList faces;
ObjVec normal;
} ObjVertex;
typedef struct
{
float r, g, b;
} MatColor;
typedef struct
{
MatColor ambient;
MatColor diffuse;
MatColor specular;
float alpha;
std::string diffuseMap;
std::string ambientMap;
std::string specularMap;
std::string alphaMap;
std::string name;
float d;
float Ni;
float Ns;
float illum;
} ObjMaterial;
typedef ObjVec ObjNormal;
typedef struct
{
int breakAt;
int newTexNum;
} ObjBreak;
typedef struct
{
float u, v;
} ObjTexCoord;
typedef struct
{
int Vertex[3];
int Normal[3];
int TexCoord[3];
int Material;
} ObjTriangle;
typedef struct
{
std::vector<ObjMaterial> MaterialArray;
int nMaterial;
tNameToNum nameLookup;
} MatLib;
typedef struct
{
int nVertex, nNormal, nTexCoord, nTriangle, nBreak;
std::vector<ObjBreak> BreakArray;
std::vector<ObjVertex> VertexArray;
std::vector<ObjNormal> NormalArray;
std::vector<ObjTexCoord> TexCoordArray;
std::vector<ObjTriangle> TriangleArray;
MatLib* Materials;
} ObjModel;
MatLib* MatLoadLib(char*, size_t);
ObjModel* ObjLoadModel(char*, size_t);
size_t ObjLoadFile(char*, char**);
#endif