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

#9 fading & panning of sound sources

This commit is contained in:
XProger
2016-10-21 00:58:15 +03:00
parent 8bbd26a9ef
commit df942b2893
11 changed files with 190 additions and 95 deletions

Binary file not shown.

View File

@@ -160,6 +160,7 @@ struct Camera : Controller {
float fov, znear, zfar; float fov, znear, zfar;
vec3 target, destPos, lastDest, angleAdv; vec3 target, destPos, lastDest, angleAdv;
mat4 mViewInv;
int room; int room;
float timer; float timer;
@@ -266,29 +267,32 @@ struct Camera : Controller {
pos = pos.lerp(destPos, Core::deltaTime * lerpFactor); pos = pos.lerp(destPos, Core::deltaTime * lerpFactor);
if (actCamera > -1) return; if (actCamera <= -1) {
TR::Level::FloorInfo info;
level->getFloorInfo(room, (int)pos.x, (int)pos.z, info);
if (info.roomNext != 255)
room = info.roomNext;
if (pos.y < info.ceiling) {
if (info.roomAbove != 255)
room = info.roomAbove;
else
if (info.ceiling != 0xffff8100)
pos.y = info.ceiling;
}
TR::Level::FloorInfo info; if (pos.y > info.floor) {
level->getFloorInfo(room, (int)pos.x, (int)pos.z, info); if (info.roomBelow != 255)
room = info.roomBelow;
if (info.roomNext != 255) else
room = info.roomNext; if (info.floor != 0xffff8100)
pos.y = info.floor;
if (pos.y < info.ceiling) { }
if (info.roomAbove != 255)
room = info.roomAbove;
else
if (info.ceiling != 0xffff8100)
pos.y = info.ceiling;
} }
if (pos.y > info.floor) { mViewInv = mat4(pos, target, vec3(0, -1, 0));
if (info.roomBelow != 255) Sound::listener.matrix = mViewInv;
room = info.roomBelow;
else
if (info.floor != 0xffff8100)
pos.y = info.floor;
}
} }
vec3 trace(int fromRoom, const vec3 &from, const vec3 &to) { // TODO: use Bresenham vec3 trace(int fromRoom, const vec3 &from, const vec3 &to) { // TODO: use Bresenham
@@ -352,7 +356,7 @@ struct Camera : Controller {
} }
virtual void setup() { virtual void setup() {
Core::mViewInv = mat4(pos, target, vec3(0, -1, 0)); Core::mViewInv = mViewInv;
Core::mView = Core::mViewInv.inverse(); Core::mView = Core::mViewInv.inverse();
Core::mProj = mat4(fov, (float)Core::width / (float)Core::height, znear, zfar); Core::mProj = mat4(fov, (float)Core::width / (float)Core::height, znear, zfar);
@@ -360,7 +364,7 @@ struct Camera : Controller {
Core::viewPos = Core::mViewInv.offset.xyz; Core::viewPos = Core::mViewInv.offset.xyz;
frustum->pos = Core::viewPos; frustum->pos = Core::viewPos;
frustum->calcPlanes(Core::mViewProj); frustum->calcPlanes(Core::mViewProj);
} }
}; };

View File

@@ -166,7 +166,7 @@ struct Controller {
return b.floor - floor; return b.floor - floor;
} }
void playSound(int id) const { void playSound(int id, const vec3 &pos, int flags) const {
// LOG("play sound %d\n", id); // LOG("play sound %d\n", id);
int16 a = level->soundsMap[id]; int16 a = level->soundsMap[id];
@@ -175,7 +175,7 @@ struct Controller {
if (b.chance == 0 || (rand() & 0x7fff) <= b.chance) { if (b.chance == 0 || (rand() & 0x7fff) <= b.chance) {
uint32 c = level->soundOffsets[b.offset + rand() % ((b.flags & 0xFF) >> 2)]; uint32 c = level->soundOffsets[b.offset + rand() % ((b.flags & 0xFF) >> 2)];
void *p = &level->soundData[c]; void *p = &level->soundData[c];
Sound::play(new Stream(p, 1024 * 1024), (float)b.volume / 0xFFFF, 0.0f, Sound::Flags::PAN); Sound::play(new Stream(p, 1024 * 1024), pos, (float)b.volume / 0xFFFF, 0.0f, flags);
} }
} }
@@ -198,6 +198,27 @@ struct Controller {
angle.y = k * PI * 0.5f; // clamp angle to n*PI/2 angle.y = k * PI * 0.5f; // clamp angle to n*PI/2
} }
virtual Box getBoundingBox() {
TR::Animation *anim = &level->anims[animIndex];
TR::Model &model = getModel();
float k = animTime * 30.0f / anim->frameRate;
int fIndex = (int)k;
int fCount = (anim->frameEnd - anim->frameStart) / anim->frameRate + 1;
int fSize = sizeof(TR::AnimFrame) + model.mCount * sizeof(uint16) * 2;
k = k - fIndex;
int fIndexA = fIndex % fCount, fIndexB = (fIndex + 1) % fCount;
TR::AnimFrame *fA = (TR::AnimFrame*)&level->frameData[(anim->frameOffset + fIndexA * fSize) >> 1];
TR::AnimFrame *fB = (TR::AnimFrame*)&level->frameData[(anim->frameOffset + fIndexB * fSize) >> 1];
Box box(fA->box.min().lerp(fB->box.min(), k), fA->box.max().lerp(fB->box.max(), k));
box.rotate90(getEntity().rotation.value / 0x4000);
box.min += pos;
box.max += pos;
return box;
}
void collide() { void collide() {
TR::Entity &entity = getEntity(); TR::Entity &entity = getEntity();
@@ -255,7 +276,7 @@ struct Controller {
case TR::Action::SECRET : case TR::Action::SECRET :
if (!level->secrets[next->value]) { if (!level->secrets[next->value]) {
level->secrets[next->value] = true; level->secrets[next->value] = true;
playSound(TR::SND_SECRET); playSound(TR::SND_SECRET, pos, 0);
} }
actionCommand = next; actionCommand = next;
activateNext(); activateNext();
@@ -411,12 +432,12 @@ struct Controller {
if (cmd == TR::ANIM_CMD_EFFECT) { if (cmd == TR::ANIM_CMD_EFFECT) {
switch (id) { switch (id) {
case TR::EFFECT_ROTATE_180 : angle.y = angle.y + PI; break; case TR::EFFECT_ROTATE_180 : angle.y = angle.y + PI; break;
case TR::EFFECT_LARA_BUBBLES : if (rand() % 10 > 6) playSound(TR::SND_BUBBLE); break; case TR::EFFECT_LARA_BUBBLES : if (rand() % 10 > 6) playSound(TR::SND_BUBBLE, pos, Sound::Flags::PAN); break;
case TR::EFFECT_LARA_HANDSFREE : break; case TR::EFFECT_LARA_HANDSFREE : break;
default : LOG("unknown special cmd %d (anim %d)\n", id, animIndex); default : LOG("unknown special cmd %d (anim %d)\n", id, animIndex);
} }
} else } else
playSound(id); playSound(id, pos, Sound::Flags::PAN);
} }
break; break;
} }

View File

@@ -295,7 +295,7 @@ namespace Debug {
void debugSectors(const TR::Level &level, const vec3 &pos, int roomIndex) { void debugSectors(const TR::Level &level, const vec3 &pos, int roomIndex) {
TR::Room &room = level.rooms[roomIndex]; TR::Room &room = level.rooms[roomIndex];
vec3 p = (pos - vec3(room.info.x, 0, room.info.z)) / vec3(1024, 1, 1024); vec3 p = (pos - vec3(room.info.x, 0, room.info.z)) * vec3(1.0f / 1024.0f, 1, 1.0f / 1024.0f);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
for (int z = 0; z < room.zSectors; z++) for (int z = 0; z < room.zSectors; z++)
@@ -409,14 +409,15 @@ namespace Debug {
TR::StaticMesh *sm = level.getMeshByID(m.meshID); TR::StaticMesh *sm = level.getMeshByID(m.meshID);
ASSERT(sm != NULL); ASSERT(sm != NULL);
vec3 min, max, offset = vec3(m.x, m.y, m.z); Box box;
sm->getBox(false, m.rotation, min, max); // visible box vec3 offset = vec3(m.x, m.y, m.z);
sm->getBox(false, m.rotation, box); // visible box
Debug::Draw::box(offset + min, offset + max, vec4(1, 1, 0, 0.25)); Debug::Draw::box(offset + box.min, offset + box.max, vec4(1, 1, 0, 0.25));
if (sm->flags == 2) { // collision box if (sm->flags == 2) { // collision box
sm->getBox(true, m.rotation, min, max); sm->getBox(true, m.rotation, box);
Debug::Draw::box(offset + min - vec3(10.0f), offset + max + vec3(10.0f), vec4(1, 0, 0, 0.50)); Debug::Draw::box(offset + box.min - vec3(10.0f), offset + box.max + vec3(10.0f), vec4(1, 0, 0, 0.50));
} }
/* /*
TR::Mesh *mesh = (TR::Mesh*)&level.meshData[level.meshOffsets[sm->mesh] / 2]; TR::Mesh *mesh = (TR::Mesh*)&level.meshData[level.meshOffsets[sm->mesh] / 2];

View File

@@ -75,6 +75,7 @@ namespace TR {
SND_NO = 2, SND_NO = 2,
SND_LANDING = 4, SND_LANDING = 4,
SND_BUBBLE = 37, SND_BUBBLE = 37,
SND_DART = 151,
SND_SECRET = 173, SND_SECRET = 173,
}; };
@@ -472,34 +473,17 @@ namespace TR {
MinMax cbox; MinMax cbox;
uint16 flags; uint16 flags;
void getBox(bool collision, angle rotation, vec3 &min, vec3 &max) { void getBox(bool collision, angle rotation, ::Box &box) {
int k = rotation.value / 0x4000; int k = rotation.value / 0x4000;
MinMax &m = collision ? cbox : vbox; MinMax &m = collision ? cbox : vbox;
ASSERT(m.minX <= m.maxX && m.minY <= m.maxY && m.minZ <= m.maxZ); ASSERT(m.minX <= m.maxX && m.minY <= m.maxY && m.minZ <= m.maxZ);
switch (k) { box = ::Box(m.min(), m.max());
case 0 : box.rotate90(k);
min = vec3(m.minX, m.minY, m.minZ);
max = vec3(m.maxX, m.maxY, m.maxZ); ASSERT(box.min.x <= box.max.x && box.min.y <= box.max.y && box.min.z <= box.max.z);
break;
case 1 :
min = vec3(m.minZ, m.minY, -m.maxX);
max = vec3(m.maxZ, m.maxY, -m.minX);
break;
case 2 :
min = vec3(-m.maxX, m.minY, -m.maxZ);
max = vec3(-m.minX, m.maxY, -m.minZ);
break;
case 3 :
min = vec3(-m.maxZ, m.minY, m.minX);
max = vec3(-m.minZ, m.maxY, m.maxX);
break;
default :
ASSERT(false);
}
ASSERT(min.x <= max.x && min.y <= max.y && min.z <= max.z);
} }
}; };

View File

@@ -17,7 +17,7 @@ namespace Game {
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
//Sound::play(Sound::openWAD("05_Lara's_Themes.wav"), 1, 1, 0); //Sound::play(Sound::openWAD("05_Lara's_Themes.wav"), 1, 1, 0);
Sound::play(new Stream("05.ogg"), 1, 1, 0); Sound::play(new Stream("05.ogg"), vec3(0.0f), 1, 1, Sound::Flags::LOOP);
//Sound::play(new Stream("03.mp3"), 1, 1, 0); //Sound::play(new Stream("03.mp3"), 1, 1, 0);
#endif #endif
} }

View File

@@ -144,11 +144,16 @@ struct Lara : Controller {
angle = vec3(0.0f, PI * 0.5f, 0.0f); angle = vec3(0.0f, PI * 0.5f, 0.0f);
getEntity().room = 12; getEntity().room = 12;
*/ */
/*
// level 2 (pool) // level 2 (pool)
pos = vec3(70067, -256, 29104); pos = vec3(70067, -256, 29104);
angle = vec3(0.0f, -0.68f, 0.0f); angle = vec3(0.0f, -0.68f, 0.0f);
getEntity().room = 15; getEntity().room = 15;
*/
// level 2 (blade)
pos = vec3(27221, -1024, 29205);
angle = vec3(0.0f, PI * 0.5f, 0.0f);
getEntity().room = 61;
/* /*
// level 2 (wolf) // level 2 (wolf)
@@ -323,7 +328,7 @@ struct Lara : Controller {
for (int i = 0; i < info.trigCmdCount; i++) { for (int i = 0; i < info.trigCmdCount; i++) {
if (!controller) { if (!controller) {
LOG("! next activation entity %d has no controller\n", level->entities[info.trigCmd[i].args].type); LOG("! next activation entity %d has no controller\n", level->entities[info.trigCmd[i].args].type);
playSound(TR::SND_NO); playSound(TR::SND_NO, pos, 0);
return; return;
} }
@@ -420,7 +425,7 @@ struct Lara : Controller {
if (stand == STAND_SLIDE || (stand == STAND_AIR && velocity.y > 0) || stand == STAND_GROUND) { if (stand == STAND_SLIDE || (stand == STAND_AIR && velocity.y > 0) || stand == STAND_GROUND) {
if (e.y + 8 >= info.floor && (abs(info.slantX) > 2 || abs(info.slantZ) > 2)) { if (e.y + 8 >= info.floor && (abs(info.slantX) > 2 || abs(info.slantZ) > 2)) {
if (stand == STAND_AIR) if (stand == STAND_AIR)
playSound(TR::SND_LANDING); playSound(TR::SND_LANDING, pos, Sound::Flags::PAN);
pos.y = info.floor; pos.y = info.floor;
updateEntity(); updateEntity();
@@ -928,8 +933,9 @@ struct Lara : Controller {
vec3 p = pos; vec3 p = pos;
pos = pos + offset; pos = pos + offset;
TR::Entity &e = getEntity();
TR::Level::FloorInfo info; TR::Level::FloorInfo info;
level->getFloorInfo(getEntity().room, (int)pos.x, (int)pos.z, info, true); level->getFloorInfo(e.room, (int)pos.x, (int)pos.z, info, true);
// get frame to get height // get frame to get height
TR::Animation *anim = &level->anims[animIndex]; TR::Animation *anim = &level->anims[animIndex];
@@ -937,7 +943,40 @@ struct Lara : Controller {
bool canPassGap = (info.floor - info.ceiling) >= (stand == STAND_GROUND ? 768 : 512); bool canPassGap = (info.floor - info.ceiling) >= (stand == STAND_GROUND ? 768 : 512);
float f = info.floor - pos.y; float f = info.floor - pos.y;
float c = pos.y - info.ceiling; float c = pos.y - info.ceiling;
/*
Box eBox = Box(pos - vec3(128.0f, 0.0f, 128.0f), pos + vec3(128.0, getHeight(), 128.0f)); // getBoundingBox();
// check static meshes in the room
if (canPassGap) {
TR::Room &r = level->rooms[e.room];
for (int i = 0; i < r.meshesCount; i++) {
TR::Room::Mesh &m = r.meshes[i];
TR::StaticMesh *sm = level->getMeshByID(m.meshID);
if (sm->flags != 2) continue; // no have collision box
Box mBox;
vec3 offset(m.x, m.y, m.z);
sm->getBox(true, m.rotation, mBox);
mBox.min += offset;
mBox.max += offset;
if (eBox.intersect(mBox)) {
canPassGap = false;
break;
}
}
}
// check entities in the room
if (canPassGap)
for (int i = 0; i < level->entitiesCount; i++)
if (i != entity && level->entities[i].room == e.room && level->entities[i].controller) {
Box mBox = ((Controller*)level->entities[i].controller)->getBoundingBox();
if (eBox.intersect(mBox)) {
canPassGap = false;
break;
}
}
*/
if (canPassGap) if (canPassGap)
switch (stand) { switch (stand) {
case STAND_AIR : { case STAND_AIR : {

View File

@@ -238,10 +238,11 @@ struct Level {
ASSERT(sMesh != NULL); ASSERT(sMesh != NULL);
// check visibility // check visibility
vec3 min, max, offset = vec3(rMesh.x, rMesh.y, rMesh.z); Box box;
sMesh->getBox(false, rMesh.rotation, min, max); vec3 offset = vec3(rMesh.x, rMesh.y, rMesh.z);
if (!camera->frustum->isVisible(offset + min, offset + max)) sMesh->getBox(false, rMesh.rotation, box);
continue; if (!camera->frustum->isVisible(offset + box.min, offset + box.max))
continue;
rMesh.flags.rendered = true; rMesh.flags.rendered = true;
// set light parameters // set light parameters
@@ -362,7 +363,7 @@ struct Level {
m.translate(pos); m.translate(pos);
m.rotateY(angle); m.rotateY(angle);
m.translate(vec3(offset.x, 0.0f, offset.z)); m.translate(vec3(offset.x, 0.0f, offset.z));
m.scale(vec3(size.x, 0.0f, size.z) / 1024.0f); m.scale(vec3(size.x, 0.0f, size.z) * (1.0f / 1024.0f));
Core::active.shader->setParam(uModel, m); Core::active.shader->setParam(uModel, m);
Core::active.shader->setParam(uColor, vec4(0.0f, 0.0f, 0.0f, 0.5f)); Core::active.shader->setParam(uColor, vec4(0.0f, 0.0f, 0.0f, 0.5f));

View File

@@ -20,6 +20,7 @@
#endif #endif
#define SND_CHANNELS_MAX 32 #define SND_CHANNELS_MAX 32
#define SND_FADEOFF_DIST (1024.0f * 5.0f)
namespace Sound { namespace Sound {
@@ -216,7 +217,7 @@ namespace Sound {
struct Listener { struct Listener {
mat4 matrix; mat4 matrix;
vec3 velocity; // vec3 velocity;
} listener; } listener;
enum Flags { enum Flags {
@@ -229,12 +230,14 @@ namespace Sound {
struct Sample { struct Sample {
Decoder *decoder; Decoder *decoder;
vec3 pos;
vec3 velocity;
float volume; float volume;
float pitch; float pitch;
int flags; int flags;
bool isPlaying; bool isPlaying;
Sample(Stream *stream, float volume, float pitch, int flags) : decoder(NULL), volume(volume), pitch(pitch), flags(flags) { Sample(Stream *stream, const vec3 &pos, float volume, float pitch, int flags) : decoder(NULL), pos(pos), volume(volume), pitch(pitch), flags(flags) {
uint32 fourcc; uint32 fourcc;
stream->read(fourcc); stream->read(fourcc);
if (fourcc == FOURCC("RIFF")) { // wav if (fourcc == FOURCC("RIFF")) { // wav
@@ -286,6 +289,21 @@ namespace Sound {
delete decoder; delete decoder;
} }
vec3 getPan() {
if (!(flags & PAN))
return vec3(1.0f);
mat4 m = Sound::listener.matrix;
vec3 v = pos - m.offset.xyz;
float dist = max(0.0f, 1.0f - (v.length2() / (SND_FADEOFF_DIST * SND_FADEOFF_DIST)));
float pan = m.right.xyz.dot(v.normal());
float l = min(1.0f, 1.0f - pan);
float r = min(1.0f, 1.0f + pan);
return vec3(l, r, 1.0f) * dist;
}
bool render(Frame *frames, int count) { bool render(Frame *frames, int count) {
if (!isPlaying) return 0; if (!isPlaying) return 0;
int i = 0; int i = 0;
@@ -298,14 +316,15 @@ namespace Sound {
i += res; i += res;
} }
if (volume != 1.0f) vec3 pan = getPan() * volume;
if (pan.x < 1.0f || pan.y < 1.0f)
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
frames[j].L = int(frames[j].L * volume); frames[j].L = int(frames[j].L * pan.x);
frames[j].R = int(frames[j].R * volume); frames[j].R = int(frames[j].R * pan.y);
} }
return true; return true;
} }
} *channels[SND_CHANNELS_MAX]; } *channels[SND_CHANNELS_MAX];
int channelsCount; int channelsCount;
@@ -338,7 +357,7 @@ namespace Sound {
memset(buffer, 0, sizeof(Frame) * count); memset(buffer, 0, sizeof(Frame) * count);
channels[i]->render(buffer, count); channels[i]->render(buffer, count);
for (int j = 0; j < count; j++) { for (int j = 0; j < count; j++) {
result[j].L += buffer[j].L; result[j].L += buffer[j].L;
result[j].R += buffer[j].R; result[j].R += buffer[j].R;
@@ -382,14 +401,15 @@ namespace Sound {
return NULL; return NULL;
} }
void play(Stream *stream, float volume, float pitch, int flags) { Sample* play(Stream *stream, const vec3 &pos, float volume, float pitch, int flags) {
if (!stream) return; if (!stream) return NULL;
if (channelsCount < SND_CHANNELS_MAX) if (channelsCount < SND_CHANNELS_MAX)
channels[channelsCount++] = new Sample(stream, volume, pitch, flags); return channels[channelsCount++] = new Sample(stream, pos, volume, pitch, flags);
else {
LOG("! no free channels\n"); LOG("! no free channels\n");
delete stream; delete stream;
} return NULL;
} }
} }

View File

@@ -107,8 +107,8 @@ struct Dartgun : Trigger {
level->entities[dartIndex].controller = new Dart(level, dartIndex); level->entities[dartIndex].controller = new Dart(level, dartIndex);
addSprite(level, TR::Entity::SMOKE, entity.room, (int)pos.x, (int)pos.y, (int)pos.z); addSprite(level, TR::Entity::SMOKE, entity.room, (int)pos.x, (int)pos.y, (int)pos.z);
playSound(151); playSound(TR::SND_DART, pos, Sound::Flags::PAN);
return true; return true;
} }

View File

@@ -76,12 +76,12 @@ inline const int sign(const T &x) {
} }
float clampAngle(float a) { float clampAngle(float a) {
return a < -PI ? a + PI2 : (a >= PI ? a - PI2 : a); return a < -PI ? a + PI2 : (a >= PI ? a - PI2 : a);
} }
float shortAngle(float a, float b) { float shortAngle(float a, float b) {
float n = clampAngle(b) - clampAngle(a); float n = clampAngle(b) - clampAngle(a);
return clampAngle(n - int(n / PI2) * PI2); return clampAngle(n - int(n / PI2) * PI2);
} }
@@ -111,10 +111,14 @@ struct vec3 {
float& operator [] (int index) const { return ((float*)this)[index]; } float& operator [] (int index) const { return ((float*)this)[index]; }
vec3& operator += (const vec3 &v) { x += v.x; y += v.y; z += v.z; return *this; }
vec3& operator -= (const vec3 &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
vec3& operator *= (const vec3 &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
vec3& operator *= (float s) { x *= s; y *= s; z *= s; return *this; }
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 - (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 / (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); } 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; } float dot(const vec3 &v) const { return x*v.x + y*v.y + z*v.z; }
@@ -484,12 +488,33 @@ struct mat4 {
} }
}; };
struct Box {
vec3 min, max;
Box() {}
Box(const vec3 &min, const vec3 &max) : min(min), max(max) {}
void rotate90(int n) {
switch (n) {
case 0 : break;
case 1 : *this = Box(vec3( min.z, min.y, -max.x), vec3( max.z, max.y, -min.x)); break;
case 2 : *this = Box(vec3(-max.x, min.y, -max.z), vec3(-min.x, max.y, -min.z)); break;
case 3 : *this = Box(vec3(-max.z, min.y, min.x), vec3(-min.z, max.y, max.x)); break;
default : ASSERT(false);
}
}
bool intersect(const Box &box) const {
return !((max.x < box.min.x || min.x > box.max.x) || (max.y < box.min.y || min.y > box.max.y) || (max.z < box.min.z || min.z > box.max.z));
}
};
struct Stream { struct Stream {
FILE *f; FILE *f;
const char *data; const char *data;
int size, pos; int size, pos;
Stream(const void *data, int size) : f(NULL), data((char*)data), size(size), pos(0) {} Stream(const void *data, int size) : f(NULL), data((char*)data), size(size), pos(0) {}
Stream(const char *name) : data(NULL), size(-1), pos(0) { Stream(const char *name) : data(NULL), size(-1), pos(0) {
f = fopen(name, "rb"); f = fopen(name, "rb");
@@ -500,12 +525,12 @@ struct Stream {
} }
~Stream() { ~Stream() {
if (f) fclose(f); if (f) fclose(f);
} }
void setPos(int pos) { void setPos(int pos) {
this->pos = pos; this->pos = pos;
if (f) fseek(f, pos, SEEK_SET); if (f) fseek(f, pos, SEEK_SET);
} }
void seek(int offset) { void seek(int offset) {
@@ -515,11 +540,11 @@ struct Stream {
} }
void raw(void *data, int count) { void raw(void *data, int count) {
if (f) if (f)
fread(data, 1, count, f); fread(data, 1, count, f);
else else
memcpy(data, this->data + pos, count); memcpy(data, this->data + pos, count);
pos += count; pos += count;
} }
template <typename T> template <typename T>