mirror of
https://github.com/Gigaslav/HL2Overcharged.git
synced 2026-09-04 11:44:45 +03:00
1547 lines
38 KiB
C++
1547 lines
38 KiB
C++
/*===============================================================================================
|
|
3D Demo Example
|
|
Copyright (c), Firelight Technologies Pty, Ltd 2005-2016.
|
|
|
|
Example to show occlusion
|
|
===============================================================================================*/
|
|
|
|
#include "../../../api/inc/fmod.hpp"
|
|
#include "../../../api/inc/fmod_errors.h"
|
|
#include "../../api/inc/fmod_event.hpp"
|
|
#include "../../api/inc/fmod_event_net.hpp"
|
|
|
|
#include <windows.h>
|
|
|
|
#include "gl/glut.h"
|
|
#include "soil/include/SOIL.h"
|
|
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stack>
|
|
#include <string>
|
|
|
|
#include <crtdbg.h>
|
|
|
|
namespace FMOD
|
|
{
|
|
|
|
//#define SHOW_GUI_DEBUG_TEXT
|
|
#define GL_CLAMP_TO_EDGE 0x812F
|
|
|
|
void ERRCHECK(FMOD_RESULT result)
|
|
{
|
|
if (result != FMOD_OK)
|
|
{
|
|
printf("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
int INTERFACE_UPDATETIME = 17; // milliseconds
|
|
|
|
bool fullscreen = false;
|
|
|
|
// window size
|
|
int width = 500;
|
|
int height = 500;
|
|
|
|
// mouse control
|
|
bool doRotate = false;
|
|
int xMouse = 0;
|
|
int yMouse = 0;
|
|
|
|
// listener orientation
|
|
float xRotation = 0.0f;
|
|
float yRotation = 90.0f;
|
|
|
|
// listerer position
|
|
float xListenerPos = -4.0f;
|
|
float yListenerPos = 1.3f;
|
|
float zListenerPos = 0.0f;
|
|
|
|
// keyboard control
|
|
bool moveForward = false;
|
|
bool moveBackward = false;
|
|
bool moveLeft = false;
|
|
bool moveRight = false;
|
|
bool moveUp = false;
|
|
bool moveDown = false;
|
|
bool moveFast = false;
|
|
bool ambientVolUp = false;
|
|
bool ambientVolDown = false;
|
|
bool masterVolUp = false;
|
|
bool masterVolDown = false;
|
|
|
|
const float PI = 3.14159265f;
|
|
|
|
float accumulatedTime = 0.0f;
|
|
|
|
// textures
|
|
GLuint texture;
|
|
GLuint skyboxTexture[6];
|
|
|
|
// sounds placement
|
|
struct Object
|
|
{
|
|
float xPos;
|
|
float yPos;
|
|
float zPos;
|
|
float intensity;
|
|
int sound;
|
|
FMOD::Event *event;
|
|
};
|
|
|
|
const int NUM_OBJECTS = 7;
|
|
Object objects[NUM_OBJECTS] =
|
|
{
|
|
{ -11.0f, 1.0f, 0.0f, 1.0f, 0, 0 },
|
|
{ 12.0f, 2.0f, 0.0f, 1.0f, 1, 0 },
|
|
{ 45.0f, 1.0f, 0.0f, 1.0f, 3, 0 },
|
|
{ -30.0f, 1.0f, 21.0f, 1.0f, 2, 0 },
|
|
{ -30.0f, 1.0f, -21.0f, 1.0f, 3, 0 },
|
|
{ 12.0f, 1.0f, -27.0f, 1.0f, 0, 0 },
|
|
{ 4.0f, 1.0f, 16.0f, 1.0f, 0, 0 },
|
|
};
|
|
|
|
// geometry structers for loading and drawing
|
|
struct Polygon
|
|
{
|
|
int numVertices;
|
|
int indicesOffset;
|
|
float directOcclusion;
|
|
float reverbOcclusion;
|
|
FMOD_VECTOR normal;
|
|
};
|
|
|
|
struct Mesh
|
|
{
|
|
int numVertices;
|
|
FMOD_VECTOR *vertices;
|
|
float (*texcoords)[2];
|
|
int numPolygons;
|
|
Polygon* polygons;
|
|
int numIndices;
|
|
int *indices;
|
|
FMOD::Geometry *geometry;
|
|
};
|
|
|
|
class GlutCloseClass
|
|
{
|
|
public:
|
|
GlutCloseClass() {};
|
|
~GlutCloseClass();
|
|
};
|
|
|
|
|
|
GlutCloseClass gCloseObject;
|
|
|
|
Mesh walls;
|
|
Mesh rotatingMesh;
|
|
Mesh doorList[4];
|
|
|
|
// fmod sounds structures
|
|
FMOD::EventSystem *fmodEventSystem = 0;
|
|
FMOD::EventProject *fmodEventProject = 0;
|
|
FMOD::EventGroup *fmodEventGroup = 0;
|
|
FMOD::EventParameter *fmodEventParameter = 0;
|
|
FMOD::System *fmodSystem = 0;
|
|
FMOD::Geometry *geometry = 0;
|
|
FMOD::DSP *global_lowpass = 0;
|
|
|
|
float ambientVolume = 0.2f;
|
|
float masterVolume;
|
|
|
|
/*
|
|
Global stack of strings to render
|
|
*/
|
|
#ifdef SHOW_GUI_DEBUG_TEXT
|
|
std::stack<std::string> debugText;
|
|
std::stack<std::string> statusText;
|
|
#endif
|
|
|
|
GLenum rendermode = GL_FILL;
|
|
|
|
bool showdebug = false;
|
|
bool showhelp = false;
|
|
|
|
void outputText(int x, int y, std::string text)
|
|
{
|
|
int i;
|
|
const char *txt = text.c_str();
|
|
|
|
glRasterPos2f(x, y);
|
|
for (i = 0; i < (int)text.length(); i++)
|
|
{
|
|
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, txt[i]);
|
|
}
|
|
}
|
|
|
|
#ifdef SHOW_GUI_DEBUG_TEXT
|
|
void renderText(int x, int y, std::stack<std::string> *text)
|
|
{
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
|
for (int count = 0; count < text->size(); count++)
|
|
{
|
|
outputText(x, y, text->top());
|
|
text->pop();
|
|
|
|
y -= 17;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void renderUiText()
|
|
{
|
|
/*
|
|
Render help text
|
|
*/
|
|
if (showhelp)
|
|
{
|
|
int x = 10;
|
|
int y = height - 20;
|
|
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
|
outputText(x, y, "F1 - Toggle help");
|
|
outputText(x, y-=18, "F2 - Toggle fullscreen");
|
|
outputText(x, y-=18, "F3 - Toggle wireframe rendering");
|
|
outputText(x, y-=18, "F11 - Toggle debug info");
|
|
outputText(x, y-=18, "--");
|
|
outputText(x, y-=18, "w - Move forward");
|
|
outputText(x, y-=18, "s - Move backward");
|
|
outputText(x, y-=18, "a - Move left");
|
|
outputText(x, y-=18, "d - Move right");
|
|
outputText(x, y-=18, "space - Move up");
|
|
outputText(x, y-=18, "c - Move down");
|
|
outputText(x, y-=18, "Mouse (hold left button) - look direction");
|
|
outputText(x, y-=18, "--");
|
|
// outputText(x, y-=18, "V/v - Master volume up/down");
|
|
outputText(x, y-=18, "Z/z - Ambient sound volume up/down");
|
|
}
|
|
else
|
|
{
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
|
outputText(10, height - 20, "F1 - Help");
|
|
}
|
|
|
|
/*
|
|
Render debug text
|
|
*/
|
|
#ifdef SHOW_GUI_DEBUG_TEXT
|
|
if (showdebug)
|
|
{
|
|
renderText(width - (width/2), height - 20, &debugText);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Otherwise just pop everything off the stack
|
|
*/
|
|
for (int count = 0; count < debugText.size(); count++)
|
|
{
|
|
debugText.pop();
|
|
}
|
|
}
|
|
|
|
/*
|
|
Render status text
|
|
*/
|
|
renderText(10, 20, &statusText);
|
|
#endif
|
|
}
|
|
|
|
void initGeometry(const char* szFileName, Mesh& mesh, bool alter = false)
|
|
{
|
|
FMOD_RESULT result;
|
|
|
|
FILE* file = fopen(szFileName, "rb");
|
|
if (file)
|
|
{
|
|
// read vertices
|
|
fread(&mesh.numVertices, sizeof (mesh.numVertices), 1, file);
|
|
mesh.vertices = new FMOD_VECTOR[mesh.numVertices];
|
|
mesh.texcoords = new float[mesh.numVertices][2];
|
|
fread(mesh.vertices, sizeof (float) * 3, mesh.numVertices, file);
|
|
fread(mesh.texcoords, sizeof (float) * 2, mesh.numVertices, file);
|
|
|
|
|
|
fread(&mesh.numIndices, sizeof (mesh.numIndices), 1, file);
|
|
mesh.indices = new int[mesh.numIndices];
|
|
fread(mesh.indices, sizeof (int), mesh.numIndices, file);
|
|
|
|
|
|
fread(&mesh.numPolygons, sizeof (mesh.numPolygons), 1, file);
|
|
mesh.polygons = new Polygon[mesh.numPolygons];
|
|
|
|
// read polygons
|
|
for (int poly = 0; poly < mesh.numPolygons; poly++)
|
|
{
|
|
Polygon* polygon = &mesh.polygons[poly];
|
|
|
|
|
|
fread(&polygon->numVertices, sizeof (polygon->numVertices), 1, file);
|
|
fread(&polygon->indicesOffset, sizeof (polygon->indicesOffset), 1, file);
|
|
fread(&polygon->directOcclusion, sizeof (polygon->directOcclusion), 1, file);
|
|
fread(&polygon->reverbOcclusion, sizeof (polygon->reverbOcclusion), 1, file);
|
|
|
|
int* indices = &mesh.indices[polygon->indicesOffset];
|
|
|
|
// calculate polygon normal
|
|
float xN = 0.0f;
|
|
float yN = 0.0f;
|
|
float zN = 0.0f;
|
|
// todo: return an error if a polygon has less then 3 vertices.
|
|
for (int vertex = 0; vertex < polygon->numVertices - 2; vertex++)
|
|
{
|
|
float xA = mesh.vertices[indices[vertex + 1]].x -mesh.vertices[indices[0]].x;
|
|
float yA = mesh.vertices[indices[vertex + 1]].y -mesh.vertices[indices[0]].y;
|
|
float zA = mesh.vertices[indices[vertex + 1]].z -mesh.vertices[indices[0]].z;
|
|
float xB = mesh.vertices[indices[vertex + 2]].x -mesh.vertices[indices[0]].x;
|
|
float yB = mesh.vertices[indices[vertex + 2]].y -mesh.vertices[indices[0]].y;
|
|
float zB = mesh.vertices[indices[vertex + 2]].z -mesh.vertices[indices[0]].z;
|
|
// cross product
|
|
xN += yA * zB - zA * yB;
|
|
yN += zA * xB - xA * zB;
|
|
zN += xA * yB - yA * xB;
|
|
}
|
|
float fMagnidued = (float)sqrt(xN * xN + yN * yN + zN * zN);
|
|
if (fMagnidued > 0.0f) // a tollerance here might be called for
|
|
{
|
|
xN /= fMagnidued;
|
|
yN /= fMagnidued;
|
|
zN /= fMagnidued;
|
|
}
|
|
polygon->normal.x = xN;
|
|
polygon->normal.y = yN;
|
|
polygon->normal.z = zN;
|
|
}
|
|
fclose(file);
|
|
}
|
|
|
|
result = fmodSystem->createGeometry(mesh.numPolygons, mesh.numIndices, &mesh.geometry);
|
|
ERRCHECK(result);
|
|
|
|
/*
|
|
Tell FMOD about the geometry
|
|
*/
|
|
for (int poly = 0; poly < mesh.numPolygons; poly++)
|
|
{
|
|
Polygon* polygon = &mesh.polygons[poly];
|
|
FMOD_VECTOR vertices[16];
|
|
for (int i = 0; i < polygon->numVertices; i++)
|
|
vertices[i] = mesh.vertices[mesh.indices[polygon->indicesOffset + i]];
|
|
int polygonIndex = 0;
|
|
|
|
if (alter && polygon->directOcclusion == 0.85f)
|
|
{
|
|
// polygon->directOcclusion = 0.95f;
|
|
}
|
|
|
|
result = mesh.geometry->addPolygon(
|
|
polygon->directOcclusion,
|
|
polygon->reverbOcclusion,
|
|
false, // single sided
|
|
polygon->numVertices,
|
|
vertices,
|
|
&polygonIndex);
|
|
ERRCHECK(result);
|
|
}
|
|
}
|
|
|
|
|
|
void freeGeometry(Mesh& mesh)
|
|
{
|
|
mesh.geometry->release();
|
|
|
|
delete [] mesh.vertices;
|
|
delete [] mesh.texcoords;
|
|
delete [] mesh.polygons;
|
|
delete [] mesh.indices;
|
|
}
|
|
|
|
|
|
void inWater()
|
|
{
|
|
FMOD_RESULT result;
|
|
FMOD_REVERB_PROPERTIES reverbprops;
|
|
static bool inwater = false;
|
|
|
|
if (xListenerPos > -14.75f && xListenerPos < -7.6f
|
|
&& zListenerPos > -10.85f && zListenerPos < -3.75f
|
|
&& yListenerPos < 5.0f)
|
|
{
|
|
/*
|
|
Use opengl fog to make it look like we are in water
|
|
*/
|
|
if (!inwater)
|
|
{
|
|
glEnable(GL_FOG);
|
|
|
|
result = fmodEventSystem->getReverbPreset("UnderWater", &reverbprops);
|
|
ERRCHECK(result);
|
|
result = fmodEventSystem->setReverbProperties(&reverbprops);
|
|
ERRCHECK(result);
|
|
result = global_lowpass->setBypass(false);
|
|
ERRCHECK(result);
|
|
|
|
inwater = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Disable fog (water)
|
|
*/
|
|
if (inwater)
|
|
{
|
|
glDisable(GL_FOG);
|
|
|
|
result = fmodEventSystem->getReverbPreset("StdReverb", &reverbprops);
|
|
ERRCHECK(result);
|
|
result = fmodEventSystem->setReverbProperties(&reverbprops);
|
|
ERRCHECK(result);
|
|
if (global_lowpass)
|
|
{
|
|
result = global_lowpass->setBypass(true);
|
|
ERRCHECK(result);
|
|
}
|
|
|
|
inwater = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void drawSkyBox()
|
|
{
|
|
glPushMatrix();
|
|
glTranslatef(xListenerPos, 0.0f, yListenerPos);
|
|
glDisable(GL_LIGHTING);
|
|
/*
|
|
Walls
|
|
*/
|
|
glBindTexture(GL_TEXTURE_2D, skyboxTexture[0]);
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(1.0f, 1.0f); glVertex3f(-150.0f, -150.0f, -150.0f);
|
|
glTexCoord2f(1.0f, 0.0f); glVertex3f(-150.0f, 150.0f, -150.0f);
|
|
glTexCoord2f(0.0f, 0.0f); glVertex3f(150.0f, 150.0f, -150.0f);
|
|
glTexCoord2f(0.0f, 1.0f); glVertex3f(150.0f, -150.0f, -150.0f);
|
|
glEnd();
|
|
|
|
glBindTexture(GL_TEXTURE_2D, skyboxTexture[1]);
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(1.0f, 1.0f); glVertex3f(150.0f, -150.0f, -150.0f);
|
|
glTexCoord2f(1.0f, 0.0f); glVertex3f(150.0f, 150.0f,-150.0f);
|
|
glTexCoord2f(0.0f, 0.0f); glVertex3f(150.0f, 150.0f, 150.0f);
|
|
glTexCoord2f(0.0f, 1.0f); glVertex3f(150.0f, -150.0f, 150.0f);
|
|
glEnd();
|
|
|
|
glBindTexture(GL_TEXTURE_2D, skyboxTexture[2]);
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(0.0f, 1.0f); glVertex3f(-150.0f, -150.0f, 150.0f);
|
|
glTexCoord2f(0.0f, 0.0f); glVertex3f(-150.0f, 150.0f, 150.0f);
|
|
glTexCoord2f(1.0f, 0.0f); glVertex3f(150.0f, 150.0f, 150.0f);
|
|
glTexCoord2f(1.0f, 1.0f); glVertex3f(150.0f, -150.0f, 150.0f);
|
|
glEnd();
|
|
|
|
glBindTexture(GL_TEXTURE_2D, skyboxTexture[3]);
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(0.0f, 1.0f); glVertex3f(-150.0f, -150.0f, -150.0f);
|
|
glTexCoord2f(0.0f, 0.0f); glVertex3f(-150.0f, 150.0f, -150.0f);
|
|
glTexCoord2f(1.0f, 0.0f); glVertex3f(-150.0f, 150.0f, 150.0f);
|
|
glTexCoord2f(1.0f, 1.0f); glVertex3f(-150.0f, -150.0f, 150.0f);
|
|
glEnd();
|
|
|
|
/*
|
|
Top
|
|
*/
|
|
glBindTexture(GL_TEXTURE_2D, skyboxTexture[4]);
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(1.0f, 0.0f); glVertex3f(-150.0f, 150.0f, -150.0f);
|
|
glTexCoord2f(1.0f, 1.0f); glVertex3f(150.0f, 150.0f, -150.0f);
|
|
glTexCoord2f(0.0f, 1.0f); glVertex3f(150.0f, 150.0f, 150.0f);
|
|
glTexCoord2f(0.0f, 0.0f); glVertex3f(-150.0f, 150.0f, 150.0f);
|
|
glEnd();
|
|
|
|
/*
|
|
Bottom
|
|
*/
|
|
glBindTexture(GL_TEXTURE_2D, skyboxTexture[5]);
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(0.0f, 1.0f); glVertex3f(-150.0f, -150.0f, -150.0f);
|
|
glTexCoord2f(0.0f, 0.0f); glVertex3f(150.0f, -150.0f, -150.0f);
|
|
glTexCoord2f(1.0f, 0.0f); glVertex3f(150.0f, -150.0f, 150.0f);
|
|
glTexCoord2f(1.0f, 1.0f); glVertex3f(-150.0f, -150.0f, 150.0f);
|
|
glEnd();
|
|
|
|
glEnable(GL_LIGHTING);
|
|
glPopMatrix();
|
|
}
|
|
|
|
void drawWaterRoom()
|
|
{
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
|
glEnable(GL_BLEND);
|
|
|
|
glPushMatrix();
|
|
glColor4f(0.0f,0.1f,0.8f,1.0f);
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glBegin(GL_QUADS);
|
|
glVertex3f(-14.72f, 4.0f, -10.85f);
|
|
glVertex3f(-7.68f, 4.0f, -10.85f);
|
|
glVertex3f(-7.68f, 4.0f, -3.85f);
|
|
glVertex3f(-14.72f, 4.0f, -3.85f);
|
|
glEnd();
|
|
|
|
// Door
|
|
glBegin(GL_QUADS);
|
|
glVertex3f(-7.6f, 0.0f, -6.3f);
|
|
glVertex3f(-7.6f, 0.0f, -8.35f);
|
|
glVertex3f(-7.6f, 2.0f, -8.35f);
|
|
glVertex3f(-7.6f, 2.0f, -6.3f);
|
|
glEnd();
|
|
|
|
// Door
|
|
glBegin(GL_QUADS);
|
|
glVertex3f(-12.25, 0.0f, -3.75f);
|
|
glVertex3f(-10.17, 0.0f, -3.75f);
|
|
glVertex3f(-10.17, 2.0f, -3.75f);
|
|
glVertex3f(-12.25, 2.0f, -3.75f);
|
|
glEnd();
|
|
|
|
glEnable(GL_LIGHTING);
|
|
glPopMatrix();
|
|
|
|
glDisable(GL_BLEND);
|
|
}
|
|
|
|
void drawGeometry(Mesh& mesh)
|
|
{
|
|
FMOD_RESULT result;
|
|
|
|
FMOD_VECTOR pos;
|
|
result = mesh.geometry->getPosition(&pos);
|
|
ERRCHECK(result);
|
|
|
|
glPushMatrix();
|
|
// create matrix and set gl transformation for geometry
|
|
glTranslatef(pos.x, pos.y, pos.z);
|
|
FMOD_VECTOR forward;
|
|
FMOD_VECTOR up;
|
|
result = mesh.geometry->getRotation(&forward, &up);
|
|
ERRCHECK(result);
|
|
float matrix[16] =
|
|
{
|
|
up.y * forward.z - up.z * forward.y, up.x, forward.x, 0.0f,
|
|
up.z * forward.x - up.x * forward.z, up.y, forward.y, 0.0f,
|
|
up.x * forward.y - up.y * forward.x, up.z, forward.z, 0.0f,
|
|
0.0f, 0.0f, 0.0f, 1.0f,
|
|
};
|
|
glMultMatrixf(matrix);
|
|
|
|
// draw all polygons in object
|
|
glEnable(GL_LIGHTING);
|
|
glPolygonMode(GL_FRONT_AND_BACK, rendermode);
|
|
for (int poly = 0; poly < mesh.numPolygons; poly++)
|
|
{
|
|
Polygon* polygon = &mesh.polygons[poly];
|
|
if (polygon->directOcclusion == 0.0f)
|
|
{
|
|
continue; // don't draw because it is an open door way
|
|
}
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
glNormal3fv(&polygon->normal.x);
|
|
|
|
for (int i = 0; i < polygon->numVertices; i++)
|
|
{
|
|
int index = mesh.indices[polygon->indicesOffset + i];
|
|
glTexCoord2f(mesh.texcoords[index][0], mesh.texcoords[index][1]);
|
|
glVertex3fv(&mesh.vertices[index].x);
|
|
}
|
|
glEnd();
|
|
}
|
|
glPopMatrix();
|
|
}
|
|
|
|
void initObjects()
|
|
{
|
|
FMOD_RESULT result;
|
|
|
|
result = fmodEventGroup->getEvent("3DSoundEmit", FMOD_EVENT_DEFAULT, &objects[0].event);
|
|
ERRCHECK(result);
|
|
|
|
result = fmodEventGroup->getEvent("3DSoundEmit", FMOD_EVENT_DEFAULT, &objects[1].event);
|
|
ERRCHECK(result);
|
|
|
|
result = fmodEventGroup->getEvent("3DSoundEmit", FMOD_EVENT_DEFAULT, &objects[2].event);
|
|
ERRCHECK(result);
|
|
|
|
result = fmodEventGroup->getEvent("3DSoundEmit", FMOD_EVENT_DEFAULT, &objects[3].event);
|
|
ERRCHECK(result);
|
|
|
|
result = fmodEventGroup->getEvent("3DSoundEmit", FMOD_EVENT_DEFAULT, &objects[4].event);
|
|
ERRCHECK(result);
|
|
|
|
result = fmodEventGroup->getEvent("3DSoundEmit", FMOD_EVENT_DEFAULT, &objects[5].event);
|
|
ERRCHECK(result);
|
|
|
|
result = fmodEventGroup->getEvent("3DSoundEmit", FMOD_EVENT_DEFAULT, &objects[6].event);
|
|
ERRCHECK(result);
|
|
|
|
for (int i=0; i < NUM_OBJECTS; i++)
|
|
{
|
|
FMOD_VECTOR pos = { objects[i].xPos, objects[i].yPos, objects[i].zPos };
|
|
FMOD_VECTOR vel = { 0.0f, 0.0f, 0.0f };
|
|
|
|
if (objects[i].event)
|
|
{
|
|
result = objects[i].event->set3DAttributes(&pos, &vel);
|
|
ERRCHECK(result);
|
|
result = objects[i].event->start();
|
|
ERRCHECK(result);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void updateObjectSoundPos(Object* object)
|
|
{
|
|
FMOD_RESULT result;
|
|
|
|
if (object->event)
|
|
{
|
|
FMOD_VECTOR pos = { object->xPos, object->yPos, object->zPos };
|
|
FMOD_VECTOR oldPos;
|
|
object->event->get3DAttributes(&oldPos, 0);
|
|
|
|
FMOD_VECTOR vel;
|
|
vel.x = (pos.x - oldPos.x) * (1000.0f / (float)INTERFACE_UPDATETIME);
|
|
vel.y = (pos.y - oldPos.y) * (1000.0f / (float)INTERFACE_UPDATETIME);
|
|
vel.z = (pos.z - oldPos.z) * (1000.0f / (float)INTERFACE_UPDATETIME);
|
|
result = object->event->set3DAttributes(&pos, &vel);
|
|
// ERRCHECK(result);
|
|
}
|
|
}
|
|
|
|
|
|
void mouseFunc(int button, int state, int x, int y)
|
|
{
|
|
switch (button)
|
|
{
|
|
case GLUT_LEFT_BUTTON:
|
|
if (state == GLUT_DOWN)
|
|
{
|
|
doRotate = true;
|
|
xMouse = x;
|
|
yMouse = y;
|
|
}
|
|
else
|
|
if (state == GLUT_UP)
|
|
{
|
|
doRotate = false;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void motionFunc(int x, int y)
|
|
{
|
|
int test = 0;
|
|
|
|
int dx = x - xMouse;
|
|
int dy = y - yMouse;
|
|
|
|
// view rotation about y-axis
|
|
yRotation += (float)dx * 0.5f;
|
|
if (yRotation > 180.0f)
|
|
yRotation -= 360.0f;
|
|
else
|
|
if (yRotation < -180.0f)
|
|
yRotation += 360.0f;
|
|
|
|
// view rotation about x-axis
|
|
const float xExtent = 88.0f;
|
|
xRotation += (float)dy * 0.5f;
|
|
if (xRotation > xExtent)
|
|
xRotation = xExtent;
|
|
else
|
|
if (xRotation < -xExtent)
|
|
xRotation = -xExtent;
|
|
|
|
|
|
xMouse = x;
|
|
yMouse = y;
|
|
}
|
|
|
|
void doGeometryMovement()
|
|
{
|
|
FMOD_RESULT result;
|
|
bool doorMoving[4] = {true, true, true ,true};
|
|
|
|
// example of moving individual polygon vertices
|
|
int xGeometryWarpPos = -30.0f;
|
|
int zGeometryWarpPos = -21.0f;
|
|
int dx = xListenerPos - xGeometryWarpPos;
|
|
int dz = zListenerPos - zGeometryWarpPos;
|
|
if (dx * dx + dz * dz < 30.0f * 30.0f)
|
|
{
|
|
if (sin(accumulatedTime * 1.0f) > 0.0f)
|
|
{
|
|
static FMOD_VECTOR lastOffset = { 0.0f, 0.0f, 0.0f };
|
|
FMOD_VECTOR offset = { sin(accumulatedTime * 2.0f), 0.0f, cos(accumulatedTime * 2.0f) };
|
|
for (int poly = 0; poly < walls.numPolygons; poly++)
|
|
{
|
|
Polygon* polygon = &walls.polygons[poly];
|
|
for (int i = 0; i < polygon->numVertices; i++)
|
|
{
|
|
FMOD_VECTOR& vertex = walls.vertices[walls.indices[polygon->indicesOffset + i]];
|
|
|
|
dx = vertex.x - xGeometryWarpPos;
|
|
dz = vertex.z - zGeometryWarpPos;
|
|
if (dx * dx + dz * dz > 90.0f)
|
|
continue;
|
|
vertex.x -= lastOffset.x;
|
|
vertex.y -= lastOffset.y;
|
|
vertex.z -= lastOffset.z;
|
|
|
|
vertex.x += offset.x;
|
|
vertex.y += offset.y;
|
|
vertex.z += offset.z;
|
|
result = walls.geometry->setPolygonVertex(poly, i, &vertex);
|
|
ERRCHECK(result);
|
|
}
|
|
}
|
|
lastOffset = offset;
|
|
}
|
|
}
|
|
|
|
// example of rotation and a geometry object
|
|
FMOD_VECTOR up = { 0.0f, 1.0f, 0.0f };
|
|
FMOD_VECTOR forward = { (float)sin(accumulatedTime * 0.5f), 0.0f, (float)cos(accumulatedTime * 0.5f) };
|
|
result = rotatingMesh.geometry->setRotation(&forward, &up);
|
|
ERRCHECK(result);
|
|
FMOD_VECTOR pos;
|
|
pos.x = 12.0f;
|
|
pos.y = (float)sin(accumulatedTime) * 0.4f + 0.1f;
|
|
pos.z = 0.0f;
|
|
result = rotatingMesh.geometry->setPosition(&pos);
|
|
ERRCHECK(result);
|
|
drawGeometry(rotatingMesh);
|
|
|
|
|
|
// example of moving doors
|
|
// door 1
|
|
pos.x = 3.25f;
|
|
pos.y = ((float)sin(accumulatedTime)) * 2.0f + 1.0f;
|
|
if (pos.y < 0.0f)
|
|
{
|
|
pos.y = 0;
|
|
doorMoving[0] = false;
|
|
}
|
|
if (pos.y > 2.0f)
|
|
{
|
|
pos.y = 2.0f;
|
|
doorMoving[0] = false;
|
|
}
|
|
pos.z = 11.5f;
|
|
|
|
|
|
result = doorList[0].geometry->setPosition(&pos);
|
|
ERRCHECK(result);
|
|
|
|
|
|
// door 2
|
|
pos.x = 0.75f;
|
|
pos.y = ((float)sin(accumulatedTime)) * 2.0f + 1.0f;
|
|
if (pos.y < 0.0f)
|
|
{
|
|
pos.y = 0;
|
|
doorMoving[1] = false;
|
|
}
|
|
if (pos.y > 2.0f)
|
|
{
|
|
pos.y = 2.0f;
|
|
doorMoving[1] = false;
|
|
}
|
|
pos.z = 14.75f;
|
|
|
|
|
|
result = doorList[1].geometry->setPosition(&pos);
|
|
ERRCHECK(result);
|
|
|
|
|
|
// door 3
|
|
pos.x = 8.25f;
|
|
pos.y = ((float)sin(accumulatedTime)) * 2.0f + 1.0f;
|
|
if (pos.y < 0.0f)
|
|
{
|
|
pos.y = 0;
|
|
doorMoving[2] = false;
|
|
}
|
|
if (pos.y > 2.0f)
|
|
{
|
|
pos.y = 2.0f;
|
|
doorMoving[2] = false;
|
|
}
|
|
pos.z = 14.75f;
|
|
|
|
|
|
result = doorList[2].geometry->setPosition(&pos);
|
|
ERRCHECK(result);
|
|
|
|
|
|
// door 4
|
|
pos.x = 33.0f;
|
|
pos.y = ((float)sin(accumulatedTime)) * 2.0f + 1.0f;
|
|
if (pos.y < 0.0f)
|
|
{
|
|
pos.y = 0;
|
|
doorMoving[3] = false;
|
|
}
|
|
if (pos.y > 2.0f)
|
|
{
|
|
pos.y = 2.0f;
|
|
doorMoving[3] = false;
|
|
}
|
|
pos.z = -0.75f;
|
|
|
|
|
|
result = doorList[3].geometry->setPosition(&pos);
|
|
ERRCHECK(result);
|
|
}
|
|
|
|
void doSoundMovement()
|
|
{
|
|
objects[0].zPos = 10.0f * sin(accumulatedTime*0.3);
|
|
updateObjectSoundPos(&objects[0]);
|
|
objects[5].zPos = -22 + 8.0f * sin(accumulatedTime);
|
|
updateObjectSoundPos(&objects[5]);
|
|
}
|
|
|
|
void doListenerMovement()
|
|
{
|
|
// Update user movement
|
|
const float MOVEMENT_SPEED = 0.1f;
|
|
|
|
float forward = 0.0f;
|
|
if (moveForward)
|
|
{
|
|
forward += (MOVEMENT_SPEED * (moveFast ? 2.0f : 1.0f));
|
|
}
|
|
if (moveBackward)
|
|
{
|
|
forward -= (MOVEMENT_SPEED * (moveFast ? 2.0f : 1.0f));
|
|
}
|
|
|
|
float right = 0.0f;
|
|
if (moveLeft)
|
|
{
|
|
right -= (MOVEMENT_SPEED * (moveFast ? 2.0f : 1.0f));
|
|
}
|
|
if (moveRight)
|
|
{
|
|
right += (MOVEMENT_SPEED * (moveFast ? 2.0f : 1.0f));
|
|
}
|
|
|
|
float up = 0.0f;
|
|
if (moveUp)
|
|
{
|
|
up += (MOVEMENT_SPEED * (moveFast ? 2.0f : 1.0f));
|
|
}
|
|
if (moveDown)
|
|
{
|
|
up -= (MOVEMENT_SPEED * (moveFast ? 2.0f : 1.0f));
|
|
}
|
|
|
|
float xRight = (float)cos(yRotation * (PI / 180.0f));
|
|
float yRight = 0.0f;
|
|
float zRight = (float)sin(yRotation * (PI / 180.0f));
|
|
|
|
xListenerPos += xRight * right;
|
|
yListenerPos += yRight * right;
|
|
zListenerPos += zRight * right;
|
|
|
|
float xForward = (float)sin(yRotation * (PI / 180.0f)) * cos(xRotation * (PI / 180.0f));
|
|
float yForward = -(float)sin(xRotation * (PI / 180.0f));
|
|
float zForward = -(float)cos(yRotation * (PI / 180.0f)) * cos(xRotation * (PI / 180.0f));
|
|
|
|
xListenerPos += xForward * forward;
|
|
yListenerPos += yForward * forward;
|
|
zListenerPos += zForward * forward;
|
|
|
|
yListenerPos += up;
|
|
|
|
if (yListenerPos < 1.0f)
|
|
{
|
|
yListenerPos = 1.0f;
|
|
}
|
|
|
|
// cross product
|
|
float xUp = yRight * zForward - zRight * yForward;
|
|
float yUp = zRight * xForward - xRight * zForward;
|
|
float zUp = xRight * yForward - yRight * xForward;
|
|
|
|
// Update listener
|
|
{
|
|
FMOD_VECTOR listenerVector;
|
|
listenerVector.x = xListenerPos;
|
|
listenerVector.y = yListenerPos;
|
|
listenerVector.z = zListenerPos;
|
|
|
|
static FMOD_VECTOR lastpos = { 0.0f, 0.0f, 0.0f };
|
|
static bool bFirst = true;
|
|
FMOD_VECTOR forward;
|
|
FMOD_VECTOR up;
|
|
FMOD_VECTOR vel;
|
|
|
|
forward.x = xForward;
|
|
forward.y = yForward;
|
|
forward.z = zForward;
|
|
up.x = xUp;
|
|
up.y = yUp;
|
|
up.z = zUp;
|
|
|
|
// ********* NOTE ******* READ NEXT COMMENT!!!!!
|
|
// vel = how far we moved last FRAME (m/f), then time compensate it to SECONDS (m/s).
|
|
vel.x = (listenerVector.x - lastpos.x) * (1000.0f / (float)INTERFACE_UPDATETIME);
|
|
vel.y = (listenerVector.y - lastpos.y) * (1000.0f / (float)INTERFACE_UPDATETIME);
|
|
vel.z = (listenerVector.z - lastpos.z) * (1000.0f / (float)INTERFACE_UPDATETIME);
|
|
if (bFirst)
|
|
{
|
|
bFirst = false;
|
|
vel.x = 0;
|
|
vel.y = 0;
|
|
vel.z = 0;
|
|
}
|
|
|
|
static FMOD_VECTOR lastVel = { 0.0f, 0.0f, 0.0f };
|
|
// store pos for next time
|
|
lastpos = listenerVector;
|
|
|
|
if (lastVel.x != 0.0f || lastVel.y != 0.0f || lastVel.z != 0.0f)
|
|
{
|
|
if (vel.x == 0.0f && vel.y == 0.0f && vel.z == 0.0f)
|
|
{
|
|
int test = 0;
|
|
}
|
|
}
|
|
lastVel = vel;
|
|
|
|
FMOD_RESULT result = fmodSystem->set3DListenerAttributes(0, &listenerVector, &vel, &forward, &up);
|
|
ERRCHECK(result);
|
|
}
|
|
}
|
|
|
|
void doUpdateVolume()
|
|
{
|
|
if (ambientVolUp)
|
|
{
|
|
char volumestring[64];
|
|
|
|
ambientVolume += 0.025;
|
|
if (ambientVolume > 1.0f)
|
|
{
|
|
ambientVolume = 1.0f;
|
|
}
|
|
|
|
sprintf(volumestring, "Ambient Volume: %0.3f", ambientVolume);
|
|
|
|
#ifdef SHOW_GUI_DEBUG_TEXT
|
|
statusText.push(volumestring);
|
|
#endif
|
|
}
|
|
else if (ambientVolDown)
|
|
{
|
|
char volumestring[64];
|
|
|
|
ambientVolume -= 0.025;
|
|
if (ambientVolume < 0.0f)
|
|
{
|
|
ambientVolume = 0.0f;
|
|
}
|
|
|
|
sprintf(volumestring,"Ambient Volume: %0.3f", ambientVolume);
|
|
|
|
#ifdef SHOW_GUI_DEBUG_TEXT
|
|
statusText.push(volumestring);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void timerFunc(int nValue)
|
|
{
|
|
static bool firsttime = true;
|
|
FMOD_RESULT result;
|
|
|
|
doGeometryMovement();
|
|
|
|
doSoundMovement();
|
|
doListenerMovement();
|
|
doUpdateVolume();
|
|
|
|
result = FMOD::NetEventSystem_Update();
|
|
ERRCHECK(result);
|
|
result = fmodEventSystem->update();
|
|
ERRCHECK(result);
|
|
|
|
accumulatedTime += (float)INTERFACE_UPDATETIME / 1000.0f;
|
|
|
|
glutPostRedisplay();
|
|
glutTimerFunc(INTERFACE_UPDATETIME, timerFunc, 0);
|
|
|
|
#if 0
|
|
if (firsttime)
|
|
{
|
|
SetWindowPos(
|
|
GetForegroundWindow(), // handle to window
|
|
HWND_TOPMOST, // placement-order handle
|
|
0, // horizontal position
|
|
0, // vertical position
|
|
width, // width
|
|
height, // height
|
|
SWP_NOMOVE
|
|
);
|
|
firsttime = false;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void keyboardFunc(unsigned char key, int x, int y)
|
|
{
|
|
switch (key)
|
|
{
|
|
case 'w':
|
|
moveForward = true;
|
|
break;
|
|
case 's':
|
|
moveBackward = true;
|
|
break;
|
|
case 'a':
|
|
moveLeft = true;
|
|
break;
|
|
case 'd':
|
|
moveRight = true;
|
|
break;
|
|
case ' ':
|
|
moveUp = true;
|
|
break;
|
|
case 'c':
|
|
moveDown = true;
|
|
break;
|
|
case 'z' :
|
|
ambientVolDown = true;
|
|
break;
|
|
case 'Z' :
|
|
ambientVolUp = true;
|
|
break;
|
|
case 'v':
|
|
masterVolDown = true;
|
|
break;
|
|
case 'V':
|
|
masterVolUp = true;
|
|
break;
|
|
|
|
case 'p':
|
|
{
|
|
float value;
|
|
|
|
fmodEventParameter->getValue(&value);
|
|
|
|
fmodEventParameter->setValue(value - 20.0f);
|
|
}
|
|
break;
|
|
|
|
case 'P':
|
|
{
|
|
float value;
|
|
|
|
fmodEventParameter->getValue(&value);
|
|
|
|
fmodEventParameter->setValue(value + 20.0f);
|
|
}
|
|
break;
|
|
|
|
case 'f':
|
|
moveFast = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void keyboardUpFunc(unsigned char key, int x, int y)
|
|
{
|
|
switch (key)
|
|
{
|
|
case 'w':
|
|
moveForward = false;
|
|
break;
|
|
case 's':
|
|
moveBackward = false;
|
|
break;
|
|
case 'a':
|
|
moveLeft = false;
|
|
break;
|
|
case 'd':
|
|
moveRight = false;
|
|
break;
|
|
case ' ':
|
|
moveUp = false;
|
|
break;
|
|
case 'c':
|
|
moveDown = false;
|
|
break;
|
|
case 'z' :
|
|
ambientVolDown = false;
|
|
break;
|
|
case 'Z' :
|
|
ambientVolUp = false;
|
|
break;
|
|
case 'v':
|
|
masterVolDown = false;
|
|
break;
|
|
case 'V':
|
|
masterVolUp = false;
|
|
break;
|
|
case 'f':
|
|
moveFast = false;
|
|
break;
|
|
case 27:
|
|
exit(1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void specialKeyFunc(int key, int x, int y)
|
|
{
|
|
/* switch (key)
|
|
{
|
|
|
|
}*/
|
|
|
|
key = key;
|
|
}
|
|
|
|
void specialKeyUpFunc(int key, int x, int y)
|
|
{
|
|
switch (key)
|
|
{
|
|
case GLUT_KEY_F1:
|
|
showhelp = !showhelp;
|
|
break;
|
|
case GLUT_KEY_F2:
|
|
if(fullscreen)
|
|
{
|
|
glutPositionWindow(20,40);
|
|
glutReshapeWindow(500,500);
|
|
fullscreen = false;
|
|
}
|
|
else
|
|
{
|
|
glutFullScreen();
|
|
fullscreen = true;
|
|
}
|
|
break;
|
|
case GLUT_KEY_F3:
|
|
rendermode = (rendermode == GL_LINE ? GL_FILL : GL_LINE);
|
|
break;
|
|
case GLUT_KEY_F11:
|
|
showdebug = !showdebug;
|
|
break;
|
|
case GLUT_KEY_F8:
|
|
rotatingMesh.geometry->setActive(false);
|
|
walls.geometry->setActive(false);
|
|
break;
|
|
case GLUT_KEY_F9:
|
|
rotatingMesh.geometry->setActive(true);
|
|
walls.geometry->setActive(true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void display(void)
|
|
{
|
|
// Show listener position
|
|
{
|
|
char text[64];
|
|
|
|
sprintf(text, "Listener Pos: (%.2f, %.2f, %.2f)", xListenerPos, yListenerPos, zListenerPos);
|
|
#ifdef SHOW_GUI_DEBUG_TEXT
|
|
debugText.push(std::string(text));
|
|
#endif
|
|
}
|
|
// Show cpu usage position
|
|
{
|
|
char text[64];
|
|
float dsp, stream, geometry, update, total;
|
|
|
|
fmodSystem->getCPUUsage(&dsp, &stream, &geometry, &update, &total);
|
|
sprintf(text, "CPU Usage : (%.2f, %.2f, %.2f, %.2f, %.2f)", dsp, stream, geometry, update, total);
|
|
#ifdef SHOW_GUI_DEBUG_TEXT
|
|
debugText.push(std::string(text));
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
3D RENDERING
|
|
*/
|
|
|
|
// update view
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(
|
|
60.0, // fov
|
|
(float)width / (float)height, // aspect
|
|
0.1, // near
|
|
500.0 // far
|
|
);
|
|
|
|
|
|
glRotatef(xRotation, 1.0f, 0.0f, 0.0f);
|
|
glRotatef(yRotation, 0.0f, 1.0f, 0.0f);
|
|
glTranslatef(-xListenerPos, -yListenerPos, -zListenerPos);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
// clear
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
glClearColor(0.4, 0.6f, 1.0f, 0.0f);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
glBindTexture( GL_TEXTURE_2D, texture );
|
|
|
|
// draw geometry
|
|
drawGeometry(walls);
|
|
drawGeometry(rotatingMesh);
|
|
drawGeometry(doorList[0]);
|
|
drawGeometry(doorList[1]);
|
|
drawGeometry(doorList[2]);
|
|
drawGeometry(doorList[3]);
|
|
|
|
|
|
// draw skybox
|
|
drawSkyBox();
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
// draw sound objects
|
|
int object;
|
|
for (object = 0; object < NUM_OBJECTS; object++)
|
|
{
|
|
char txt[256];
|
|
|
|
|
|
float directOcclusion = 1.0f;
|
|
float reverbOcclusion = 1.0f;
|
|
|
|
// set colour baced on direct occlusion
|
|
// objects[object].channel->getOcclusion(&directOcclusion, &reverbOcclusion);
|
|
float intensity = 1.0f;// - directOcclusion;
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, rendermode);
|
|
glPushMatrix();
|
|
glTranslatef(objects[object].xPos, objects[object].yPos, objects[object].zPos);
|
|
|
|
sprintf(txt, "Sound object (%d): %.2f, %.2f, %.2f", object, objects[object].xPos, objects[object].yPos, objects[object].zPos);
|
|
#ifdef SHOW_GUI_DEBUG_TEXT
|
|
debugText.push(std::string(txt));
|
|
#endif
|
|
|
|
glPushAttrib(GL_LIGHTING_BIT);
|
|
|
|
intensity *= 0.75f;
|
|
float color[4] = { intensity, intensity, 0.0f, 0.0f };
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
|
|
intensity *= 0.5f;
|
|
float ambient[4] = { intensity, intensity, 0.0f, 0.0f };
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
|
|
|
|
|
|
glRotatef(accumulatedTime * 200.0f, 0.0f, 1.0f, 0.0f);
|
|
{
|
|
FMOD_VECTOR soundorientation;
|
|
float rad = (accumulatedTime * 200.0f);
|
|
|
|
rad *= 3.14159f;
|
|
rad /= 180.0f;
|
|
|
|
soundorientation.x = sinf(rad);
|
|
soundorientation.y = 0;
|
|
soundorientation.z = cosf(rad);
|
|
|
|
objects[object].event->set3DAttributes(0, 0, &soundorientation);
|
|
}
|
|
|
|
glutSolidTorus(0.15f, 0.6f, 8, 16);
|
|
glPopAttrib();
|
|
glPopMatrix();
|
|
}
|
|
|
|
/*
|
|
Draw blue transparent blue quads to entry to water room
|
|
*/
|
|
drawWaterRoom();
|
|
|
|
/*
|
|
Do water effects if we are in the water room
|
|
*/
|
|
inWater();
|
|
|
|
|
|
/*
|
|
2D RENDERING
|
|
*/
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluOrtho2D(0.0f, (GLsizei)width, 0.0f, (GLsizei)height);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
glDisable(GL_LIGHTING);
|
|
glDisable(GL_NORMALIZE);
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
/*
|
|
Render text
|
|
*/
|
|
renderUiText();
|
|
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
glEnable(GL_LIGHTING);
|
|
glEnable(GL_LIGHT0);
|
|
glEnable(GL_NORMALIZE);
|
|
glShadeModel(GL_SMOOTH);
|
|
glPolygonMode(GL_FRONT_AND_BACK, rendermode);
|
|
|
|
// finish
|
|
glutSwapBuffers();
|
|
}
|
|
|
|
void reshapeFunc(int w, int h)
|
|
{
|
|
width = w;
|
|
height = h;
|
|
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
|
|
}
|
|
|
|
GLuint loadTexturePNG(const char *filename)
|
|
{
|
|
GLuint texture = SOIL_load_OGL_texture(filename, 0, 0, 0);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
return texture;
|
|
}
|
|
|
|
GLuint loadTexture(const char *filename)
|
|
{
|
|
GLuint texture;
|
|
int width;
|
|
int height;
|
|
unsigned char *data;
|
|
FILE *file;
|
|
|
|
// open texture data
|
|
file = fopen( filename, "rb" );
|
|
if ( file == NULL )
|
|
return 0;
|
|
|
|
width = 128;
|
|
height = 128;
|
|
data = (unsigned char*)malloc(width * height * 3);
|
|
|
|
fread(data, width * height * 3, 1, file );
|
|
fclose(file);
|
|
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
gluBuild2DMipmaps(
|
|
GL_TEXTURE_2D,
|
|
3,
|
|
width,
|
|
height,
|
|
GL_RGB,
|
|
GL_UNSIGNED_BYTE,
|
|
data);
|
|
|
|
free(data);
|
|
|
|
return texture;
|
|
}
|
|
|
|
|
|
void init(void)
|
|
{
|
|
FMOD_RESULT result;
|
|
bool listenerflag = true;
|
|
FMOD_VECTOR listenerpos = { 0.0f, 0.0f, 0.0f };
|
|
FMOD_SPEAKERMODE speakermode;
|
|
|
|
printf("==================================================================\n");
|
|
printf("3D example. Copyright (c) Firelight Technologies 2004-2016.\n");
|
|
printf("==================================================================\n\n");
|
|
|
|
result = FMOD::EventSystem_Create(&fmodEventSystem);
|
|
ERRCHECK(result);
|
|
result = FMOD::NetEventSystem_Init(fmodEventSystem);
|
|
ERRCHECK(result);
|
|
result = fmodEventSystem->getSystemObject(&fmodSystem);
|
|
ERRCHECK(result);
|
|
result = fmodSystem->getDriverCaps(0,0,0,&speakermode);
|
|
ERRCHECK(result);
|
|
result = fmodSystem->setSpeakerMode(speakermode);
|
|
ERRCHECK(result);
|
|
result = fmodEventSystem->init(64, FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_OCCLUSION_LOWPASS | FMOD_INIT_HRTF_LOWPASS, 0, FMOD_EVENT_INIT_NORMAL);
|
|
ERRCHECK(result);
|
|
result = fmodEventSystem->setMediaPath("..\\media\\");
|
|
ERRCHECK(result);
|
|
result = fmodEventSystem->load("examples.fev", 0, &fmodEventProject);
|
|
ERRCHECK(result);
|
|
result = fmodEventProject->getGroup("FeatureDemonstration/3D Events", true, &fmodEventGroup);
|
|
ERRCHECK(result);
|
|
|
|
/*
|
|
Create a programmer created lowpass filter to apply to everything.
|
|
*/
|
|
result = fmodSystem->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &global_lowpass);
|
|
ERRCHECK(result);
|
|
|
|
result = global_lowpass->setParameter(FMOD_DSP_LOWPASS_CUTOFF, 1000);
|
|
ERRCHECK(result);
|
|
|
|
result = global_lowpass->setBypass(true); // turn it off to start with.
|
|
ERRCHECK(result);
|
|
|
|
result = fmodSystem->addDSP(global_lowpass, 0);
|
|
ERRCHECK(result);
|
|
|
|
|
|
initObjects();
|
|
|
|
result = fmodSystem->setGeometrySettings(200.0f);
|
|
ERRCHECK(result);
|
|
|
|
printf("Loading geometry...");
|
|
|
|
// load objects
|
|
initGeometry("../media/walls.bin", walls, true);
|
|
initGeometry("../media/center.bin", rotatingMesh);
|
|
initGeometry("../media/door.bin", doorList[0]);
|
|
initGeometry("../media/door.bin", doorList[1]);
|
|
initGeometry("../media/door.bin", doorList[2]);
|
|
initGeometry("../media/door.bin", doorList[3]);
|
|
|
|
printf("done.\n");
|
|
|
|
// place doors in desired orientatins
|
|
FMOD_VECTOR up = { 0.0f, 1.0f, 0.0f };
|
|
FMOD_VECTOR forward = { 1.0f, 0.0f, 0.0f };
|
|
result = doorList[1].geometry->setRotation(&forward, &up);
|
|
ERRCHECK(result);
|
|
result = doorList[2].geometry->setRotation(&forward, &up);
|
|
ERRCHECK(result);
|
|
result = doorList[3].geometry->setRotation(&forward, &up);
|
|
ERRCHECK(result);
|
|
|
|
/*
|
|
Load textures
|
|
*/
|
|
printf("Loading textures...\n");
|
|
|
|
texture = loadTexture("../media/texture.img");
|
|
skyboxTexture[0] = loadTexturePNG("../media/skybox/bluesky/front.png");
|
|
skyboxTexture[1] = loadTexturePNG("../media/skybox/bluesky/right.png");
|
|
skyboxTexture[2] = loadTexturePNG("../media/skybox/bluesky/back.png");
|
|
skyboxTexture[3] = loadTexturePNG("../media/skybox/bluesky/left.png");
|
|
skyboxTexture[4] = loadTexturePNG("../media/skybox/bluesky/top.png");
|
|
skyboxTexture[5] = loadTexturePNG("../media/skybox/bluesky/bottom.png");
|
|
|
|
printf("done.\n");
|
|
|
|
// setup lighting
|
|
GLfloat lightDiffuse[] = {1.0, 1.0, 1.0, 1.0};
|
|
GLfloat lightPosition[] = {300.0, 1000.0, 400.0, 0.0};
|
|
GLfloat lightAmbiant[] = {1.25, 1.25, 1.25, 1.0};
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
|
|
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
|
|
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbiant);
|
|
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0f);
|
|
glEnable(GL_LIGHT0);
|
|
glEnable(GL_LIGHTING);
|
|
|
|
// setup fog(water)
|
|
GLfloat fogColor[4] = {0.0f,0.1f,0.9f,1.0f};
|
|
|
|
glFogi(GL_FOG_MODE, GL_EXP); // Fog Mode
|
|
glFogfv(GL_FOG_COLOR, fogColor); // Set Fog Color
|
|
glFogf(GL_FOG_DENSITY, 0.15f); // How Dense Will The Fog Be
|
|
glHint(GL_FOG_HINT, GL_DONT_CARE); // Fog Hint Value
|
|
glFogf(GL_FOG_START, 0.0f); // Fog Start Depth
|
|
glFogf(GL_FOG_END, 1.0f); // Fog End Depth
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
}
|
|
|
|
GlutCloseClass::~GlutCloseClass()
|
|
{
|
|
glDeleteTextures( 1, &texture );
|
|
|
|
freeGeometry(walls);
|
|
freeGeometry(rotatingMesh);
|
|
freeGeometry(doorList[0]);
|
|
freeGeometry(doorList[1]);
|
|
freeGeometry(doorList[2]);
|
|
freeGeometry(doorList[3]);
|
|
|
|
fmodEventSystem->release();
|
|
FMOD::NetEventSystem_Shutdown();
|
|
|
|
_CrtDumpMemoryLeaks();
|
|
}
|
|
}
|
|
|
|
using namespace FMOD;
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
glutInit(&argc, argv);
|
|
|
|
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
|
|
glutInitWindowSize(width, height);
|
|
glutCreateWindow("FMOD Ex 3D Demo");
|
|
glutDisplayFunc(display);
|
|
glutReshapeFunc(reshapeFunc);
|
|
glutMouseFunc(mouseFunc);
|
|
glutMotionFunc(motionFunc);
|
|
glutKeyboardFunc(keyboardFunc);
|
|
glutKeyboardUpFunc(keyboardUpFunc);
|
|
glutSpecialFunc(specialKeyFunc);
|
|
glutSpecialUpFunc(specialKeyUpFunc);
|
|
|
|
glutTimerFunc(INTERFACE_UPDATETIME, timerFunc, 0);
|
|
|
|
init();
|
|
|
|
Sleep(1000);
|
|
|
|
glutMainLoop();
|
|
|
|
return 0;
|
|
}
|
|
|