mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-13 15:40:57 +00:00
EMI: Implement projection shadows.
This commit is contained in:
parent
b80dea5a90
commit
1081471119
@ -1756,7 +1756,12 @@ bool Actor::shouldDrawShadow(int shadowId) {
|
||||
|
||||
Math::Vector3d bboxPos, bboxSize;
|
||||
getBBoxInfo(bboxPos, bboxSize);
|
||||
Math::Vector3d centerOffset = bboxPos + bboxSize * 0.5f;
|
||||
Math::Vector3d centerOffset;
|
||||
if (g_grim->getGameType() == GType_GRIM) {
|
||||
centerOffset = bboxPos + bboxSize * 0.5f;
|
||||
} else {
|
||||
centerOffset.set(0.0f, 0.01f, 0.0f);
|
||||
}
|
||||
p = getPos() + centerOffset;
|
||||
|
||||
bool actorSide = n.x() * p.x() + n.y() * p.y() + n.z() * p.z() + d < 0.f;
|
||||
@ -1798,24 +1803,34 @@ void Actor::setShadowPoint(const Math::Vector3d &p) {
|
||||
_shadowArray[_activeShadowSlot].pos = p;
|
||||
}
|
||||
|
||||
void Actor::setShadowColor(const Color &color) {
|
||||
assert(_activeShadowSlot != -1);
|
||||
|
||||
_shadowArray[_activeShadowSlot].color = color;
|
||||
}
|
||||
|
||||
void Actor::clearShadowPlanes() {
|
||||
for (int i = 0; i < MAX_SHADOWS; i++) {
|
||||
Shadow *shadow = &_shadowArray[i];
|
||||
while (!shadow->planeList.empty()) {
|
||||
delete shadow->planeList.back().sector;
|
||||
shadow->planeList.pop_back();
|
||||
}
|
||||
delete[] shadow->shadowMask;
|
||||
shadow->shadowMaskSize = 0;
|
||||
shadow->shadowMask = nullptr;
|
||||
shadow->active = false;
|
||||
shadow->dontNegate = false;
|
||||
|
||||
// TODO: Clean up the userData properly
|
||||
shadow->userData = nullptr;
|
||||
clearShadowPlane(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Actor::clearShadowPlane(int i) {
|
||||
Shadow *shadow = &_shadowArray[i];
|
||||
while (!shadow->planeList.empty()) {
|
||||
delete shadow->planeList.back().sector;
|
||||
shadow->planeList.pop_back();
|
||||
}
|
||||
delete[] shadow->shadowMask;
|
||||
shadow->shadowMaskSize = 0;
|
||||
shadow->shadowMask = nullptr;
|
||||
shadow->active = false;
|
||||
shadow->dontNegate = false;
|
||||
|
||||
// TODO: Clean up the userData properly
|
||||
shadow->userData = nullptr;
|
||||
}
|
||||
|
||||
void Actor::putInSet(const Common::String &set) {
|
||||
// The set should change immediately, otherwise a very rapid set change
|
||||
// for an actor will be recognized incorrectly and the actor will be lost.
|
||||
@ -2259,6 +2274,62 @@ int Actor::getEffectiveSortOrder() const {
|
||||
return _haveSectorSortOrder ? _sectorSortOrder : getSortOrder();
|
||||
}
|
||||
|
||||
void Actor::activateShadow(bool active, const char *shadowName) {
|
||||
Set *set = g_grim->getCurrSet();
|
||||
if (!shadowName) {
|
||||
for (int i = 0; i < set->getShadowCount(); ++i) {
|
||||
activateShadow(active, set->getShadow(i));
|
||||
}
|
||||
} else {
|
||||
SetShadow *shadow = set->getShadowByName(shadowName);
|
||||
if (shadow)
|
||||
activateShadow(active, shadow);
|
||||
}
|
||||
}
|
||||
|
||||
void Actor::activateShadow(bool active, SetShadow *setShadow) {
|
||||
if (active)
|
||||
_shadowActive = true;
|
||||
|
||||
int shadowId = -1;
|
||||
for (int i = 0; i < MAX_SHADOWS; i++) {
|
||||
if (setShadow->_name.equals(_shadowArray[i].name)) {
|
||||
shadowId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shadowId == -1) {
|
||||
for (int i = 0; i < MAX_SHADOWS; i++) {
|
||||
if (!_shadowArray[i].active) {
|
||||
shadowId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shadowId == -1) {
|
||||
warning("Actor %s trying to activate shadow %s, but all shadow slots are in use", getName().c_str(), setShadow->_name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
clearShadowPlane(shadowId);
|
||||
setActivateShadow(shadowId, active);
|
||||
|
||||
if (active) {
|
||||
setActiveShadow(shadowId);
|
||||
setShadowPoint(setShadow->_shadowPoint);
|
||||
setShadowPlane(setShadow->_name.c_str());
|
||||
setShadowColor(setShadow->_color);
|
||||
setShadowValid(-1); // Don't negate the normal.
|
||||
|
||||
Common::List<Common::String>::iterator it;
|
||||
for (it = setShadow->_sectorNames.begin(); it != setShadow->_sectorNames.end(); ++it) {
|
||||
addShadowPlane((*it).c_str(), g_grim->getCurrSet(), shadowId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Actor::attachToActor(Actor *other, const char *joint) {
|
||||
assert(other != nullptr);
|
||||
if (other->getId() == _attachedActor)
|
||||
|
@ -39,6 +39,7 @@ class LipSync;
|
||||
class Font;
|
||||
class Set;
|
||||
class Material;
|
||||
class SetShadow;
|
||||
struct Joint;
|
||||
|
||||
struct Plane {
|
||||
@ -60,6 +61,7 @@ struct Shadow {
|
||||
int shadowMaskSize;
|
||||
bool active;
|
||||
bool dontNegate;
|
||||
Color color;
|
||||
void *userData;
|
||||
};
|
||||
|
||||
@ -474,9 +476,11 @@ public:
|
||||
|
||||
void setActiveShadow(int shadowId);
|
||||
void setShadowPoint(const Math::Vector3d &pos);
|
||||
void setShadowColor(const Color &color);
|
||||
void setShadowPlane(const char *name);
|
||||
void addShadowPlane(const char *name);
|
||||
void clearShadowPlanes();
|
||||
void clearShadowPlane(int i);
|
||||
void setShadowValid(int);
|
||||
void setActivateShadow(int, bool);
|
||||
|
||||
@ -539,7 +543,8 @@ public:
|
||||
void setSortOrder(const int order) { _sortOrder = order; }
|
||||
int getEffectiveSortOrder() const;
|
||||
|
||||
void activateShadow(bool active) { _shadowActive = active; }
|
||||
void activateShadow(bool active, const char *shadowName);
|
||||
void activateShadow(bool active, SetShadow *shadow);
|
||||
|
||||
void restoreCleanBuffer();
|
||||
void drawToCleanBuffer();
|
||||
|
@ -416,7 +416,7 @@ void Lua_V2::GetActorSortOrder() {
|
||||
|
||||
void Lua_V2::ActorActivateShadow() {
|
||||
lua_Object actorObj = lua_getparam(1);
|
||||
lua_Object qualityObj = lua_getparam(2);
|
||||
lua_Object activeObj = lua_getparam(2);
|
||||
lua_Object planeObj = lua_getparam(3);
|
||||
|
||||
if (!lua_isuserdata(actorObj) || lua_tag(actorObj) != MKTAG('A','C','T','R'))
|
||||
@ -425,12 +425,11 @@ void Lua_V2::ActorActivateShadow() {
|
||||
Actor *actor = getactor(actorObj);
|
||||
if (!actor)
|
||||
return;
|
||||
int quality = (int)lua_getnumber(qualityObj);
|
||||
const char *plane = "NULL";
|
||||
bool active = (int)lua_getnumber(activeObj) == 1;
|
||||
const char *plane = nullptr;
|
||||
if (lua_isstring(planeObj))
|
||||
plane = lua_getstring(planeObj);
|
||||
warning("Lua_V2::ActorActivateShadow, actor: %s, aquality: %d, plane: %s", actor->getName().c_str(), quality, plane);
|
||||
actor->activateShadow(quality);
|
||||
actor->activateShadow(active, plane);
|
||||
}
|
||||
|
||||
void Lua_V2::ActorStopMoving() {
|
||||
|
@ -158,7 +158,9 @@ byte *GfxOpenGL::setupScreen(int screenW, int screenH, bool fullscreen) {
|
||||
GLfloat specularReflectance[] = { 0.3f, 0.3f, 0.3f, 1.0f };
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularReflectance);
|
||||
|
||||
glPolygonOffset(-6.0, -6.0);
|
||||
if (g_grim->getGameType() == GType_GRIM) {
|
||||
glPolygonOffset(-6.0, -6.0);
|
||||
}
|
||||
|
||||
initExtensions();
|
||||
glGetIntegerv(GL_MAX_LIGHTS, &_maxLights);
|
||||
@ -497,10 +499,19 @@ void GfxOpenGL::getBoundingBoxPos(const EMIModel *model, int *x1, int *y1, int *
|
||||
void GfxOpenGL::startActorDraw(const Actor *actor) {
|
||||
_currentActor = actor;
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_LIGHTING);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
if (g_grim->getGameType() == GType_MONKEY4 && !actor->isInOverworld()) {
|
||||
// Apply the view transform.
|
||||
Math::Matrix4 worldRot = _currentQuat.toMatrix();
|
||||
glMultMatrixf(worldRot.getData());
|
||||
glTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
|
||||
}
|
||||
|
||||
if (_currentShadowArray) {
|
||||
// TODO find out why shadowMask at device in woods is null
|
||||
if (!_currentShadowArray->shadowMask) {
|
||||
@ -508,11 +519,16 @@ void GfxOpenGL::startActorDraw(const Actor *actor) {
|
||||
_currentShadowArray->shadowMaskSize = _screenWidth * _screenHeight;
|
||||
}
|
||||
Sector *shadowSector = _currentShadowArray->planeList.front().sector;
|
||||
glDepthMask(GL_FALSE);
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
// glColor3f(0.0f, 1.0f, 0.0f); // debug draw color
|
||||
glColor3ub(_shadowColorR, _shadowColorG, _shadowColorB);
|
||||
if (g_grim->getGameType() == GType_GRIM) {
|
||||
glColor3ub(_shadowColorR, _shadowColorG, _shadowColorB);
|
||||
} else {
|
||||
glColor3ub(_currentShadowArray->color.getRed(), _currentShadowArray->color.getGreen(), _currentShadowArray->color.getBlue());
|
||||
}
|
||||
glShadowProjection(_currentShadowArray->pos, shadowSector->getVertices()[0], shadowSector->getNormal(), _currentShadowArray->dontNegate);
|
||||
}
|
||||
|
||||
@ -543,10 +559,6 @@ void GfxOpenGL::startActorDraw(const Actor *actor) {
|
||||
glTranslatef(pos.x(), pos.y(), pos.z());
|
||||
glMultMatrixf(quat.toMatrix().getData());
|
||||
} else {
|
||||
Math::Matrix4 worldRot = _currentQuat.toMatrix();
|
||||
glMultMatrixf(worldRot.getData());
|
||||
glTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
|
||||
|
||||
Math::Matrix4 m = actor->getFinalMatrix();
|
||||
m.transpose();
|
||||
glMultMatrixf(m.getData());
|
||||
@ -562,7 +574,7 @@ void GfxOpenGL::startActorDraw(const Actor *actor) {
|
||||
glMultMatrixf(quat.toMatrix().getData());
|
||||
}
|
||||
|
||||
if (actor->getSortOrder() >= 100) {
|
||||
if (!_currentShadowArray && actor->getSortOrder() >= 100) {
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
@ -612,6 +624,16 @@ void GfxOpenGL::drawShadowPlanes() {
|
||||
}
|
||||
*/
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
if (g_grim->getGameType() == GType_MONKEY4) {
|
||||
// Apply the view transform.
|
||||
Math::Matrix4 worldRot = _currentQuat.toMatrix();
|
||||
glMultMatrixf(worldRot.getData());
|
||||
glTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
|
||||
}
|
||||
|
||||
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glDepthMask(GL_FALSE);
|
||||
glClearStencil(~0);
|
||||
@ -634,6 +656,8 @@ void GfxOpenGL::drawShadowPlanes() {
|
||||
|
||||
glStencilFunc(GL_EQUAL, 1, (GLuint)~0);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void GfxOpenGL::setShadowMode() {
|
||||
@ -671,7 +695,7 @@ void GfxOpenGL::drawEMIModelFace(const EMIModel *model, const EMIMeshFace *face)
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
if (face->_hasTexture)
|
||||
if (!_currentShadowArray && face->_hasTexture)
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
else
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
@ -680,16 +704,18 @@ void GfxOpenGL::drawEMIModelFace(const EMIModel *model, const EMIMeshFace *face)
|
||||
float dim = 1.0f - _dimLevel;
|
||||
for (uint j = 0; j < face->_faceLength * 3; j++) {
|
||||
int index = indices[j];
|
||||
if (face->_hasTexture) {
|
||||
glTexCoord2f(model->_texVerts[index].getX(), model->_texVerts[index].getY());
|
||||
|
||||
if (!_currentShadowArray) {
|
||||
if (face->_hasTexture) {
|
||||
glTexCoord2f(model->_texVerts[index].getX(), model->_texVerts[index].getY());
|
||||
}
|
||||
Math::Vector3d lighting = model->_lighting[index];
|
||||
byte r = (byte)(model->_colorMap[index].r * lighting.x() * dim);
|
||||
byte g = (byte)(model->_colorMap[index].g * lighting.y() * dim);
|
||||
byte b = (byte)(model->_colorMap[index].b * lighting.z() * dim);
|
||||
byte a = (int)(model->_colorMap[index].a * _alpha);
|
||||
glColor4ub(r, g, b, a);
|
||||
}
|
||||
|
||||
Math::Vector3d lighting = model->_lighting[index];
|
||||
byte r = (byte)(model->_colorMap[index].r * lighting.x() * dim);
|
||||
byte g = (byte)(model->_colorMap[index].g * lighting.y() * dim);
|
||||
byte b = (byte)(model->_colorMap[index].b * lighting.z() * dim);
|
||||
byte a = (int)(model->_colorMap[index].a * _alpha);
|
||||
glColor4ub(r, g, b, a);
|
||||
|
||||
Math::Vector3d normal = model->_normals[index];
|
||||
Math::Vector3d vertex = model->_drawVertices[index];
|
||||
@ -704,8 +730,9 @@ void GfxOpenGL::drawEMIModelFace(const EMIModel *model, const EMIMeshFace *face)
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
|
||||
if (!_currentShadowArray)
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
void GfxOpenGL::drawModelFace(const Mesh *mesh, const MeshFace *face) {
|
||||
|
@ -517,7 +517,16 @@ void GfxTinyGL::startActorDraw(const Actor *actor) {
|
||||
tglPushMatrix();
|
||||
tglMatrixMode(TGL_MODELVIEW);
|
||||
tglPushMatrix();
|
||||
|
||||
if (g_grim->getGameType() == GType_MONKEY4 && !actor->isInOverworld()) {
|
||||
// Apply the view transform.
|
||||
Math::Matrix4 worldRot = _currentQuat.toMatrix();
|
||||
tglMultMatrixf(worldRot.getData());
|
||||
tglTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
|
||||
}
|
||||
|
||||
if (_currentShadowArray) {
|
||||
tglDepthMask(TGL_FALSE);
|
||||
// TODO find out why shadowMask at device in woods is null
|
||||
if (!_currentShadowArray->shadowMask) {
|
||||
_currentShadowArray->shadowMask = new byte[_gameWidth * _gameHeight];
|
||||
@ -525,7 +534,11 @@ void GfxTinyGL::startActorDraw(const Actor *actor) {
|
||||
}
|
||||
assert(_currentShadowArray->shadowMask);
|
||||
//tglSetShadowColor(255, 255, 255);
|
||||
tglSetShadowColor(_shadowColorR, _shadowColorG, _shadowColorB);
|
||||
if (g_grim->getGameType() == GType_GRIM) {
|
||||
tglSetShadowColor(_shadowColorR, _shadowColorG, _shadowColorB);
|
||||
} else {
|
||||
tglSetShadowColor(_currentShadowArray->color.getRed(), _currentShadowArray->color.getGreen(), _currentShadowArray->color.getBlue());
|
||||
}
|
||||
tglSetShadowMaskBuf(_currentShadowArray->shadowMask);
|
||||
SectorListType::iterator i = _currentShadowArray->planeList.begin();
|
||||
Sector *shadowSector = i->sector;
|
||||
@ -559,10 +572,6 @@ void GfxTinyGL::startActorDraw(const Actor *actor) {
|
||||
tglTranslatef(pos.x(), pos.y(), pos.z());
|
||||
tglMultMatrixf(quat.toMatrix().getData());
|
||||
} else {
|
||||
Math::Matrix4 worldRot = _currentQuat.toMatrix();
|
||||
tglMultMatrixf(worldRot.getData());
|
||||
tglTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
|
||||
|
||||
Math::Matrix4 m = actor->getFinalMatrix();
|
||||
m.transpose();
|
||||
tglMultMatrixf(m.getData());
|
||||
@ -578,7 +587,7 @@ void GfxTinyGL::startActorDraw(const Actor *actor) {
|
||||
tglMultMatrixf(quat.toMatrix().getData());
|
||||
}
|
||||
|
||||
if (actor->getSortOrder() >= 100) {
|
||||
if (!_currentShadowArray && actor->getSortOrder() >= 100) {
|
||||
tglColorMask(TGL_FALSE, TGL_FALSE, TGL_FALSE, TGL_FALSE);
|
||||
tglDepthMask(TGL_TRUE);
|
||||
}
|
||||
@ -611,6 +620,16 @@ void GfxTinyGL::finishActorDraw() {
|
||||
|
||||
void GfxTinyGL::drawShadowPlanes() {
|
||||
tglEnable(TGL_SHADOW_MASK_MODE);
|
||||
tglDepthMask(TGL_FALSE);
|
||||
tglPushMatrix();
|
||||
|
||||
if (g_grim->getGameType() == GType_MONKEY4) {
|
||||
// Apply the view transform.
|
||||
Math::Matrix4 worldRot = _currentQuat.toMatrix();
|
||||
tglMultMatrixf(worldRot.getData());
|
||||
tglTranslatef(-_currentPos.x(), -_currentPos.y(), -_currentPos.z());
|
||||
}
|
||||
|
||||
if (!_currentShadowArray->shadowMask) {
|
||||
_currentShadowArray->shadowMask = new byte[_gameWidth * _gameHeight];
|
||||
_currentShadowArray->shadowMaskSize = _gameWidth * _gameHeight;
|
||||
@ -629,6 +648,8 @@ void GfxTinyGL::drawShadowPlanes() {
|
||||
}
|
||||
tglSetShadowMaskBuf(nullptr);
|
||||
tglDisable(TGL_SHADOW_MASK_MODE);
|
||||
|
||||
tglPopMatrix();
|
||||
}
|
||||
|
||||
void GfxTinyGL::setShadowMode() {
|
||||
@ -639,6 +660,7 @@ void GfxTinyGL::setShadowMode() {
|
||||
void GfxTinyGL::clearShadowMode() {
|
||||
GfxBase::clearShadowMode();
|
||||
tglDisable(TGL_SHADOW_MODE);
|
||||
tglDepthMask(TGL_TRUE);
|
||||
}
|
||||
|
||||
void GfxTinyGL::set3DMode() {
|
||||
@ -651,7 +673,7 @@ void GfxTinyGL::setShadow(Shadow *shadow) {
|
||||
_currentShadowArray = shadow;
|
||||
if (shadow)
|
||||
tglDisable(TGL_LIGHTING);
|
||||
else
|
||||
else if (g_grim->getGameType() == GType_GRIM)
|
||||
tglEnable(TGL_LIGHTING);
|
||||
}
|
||||
|
||||
@ -673,7 +695,7 @@ void GfxTinyGL::drawEMIModelFace(const EMIModel *model, const EMIMeshFace *face)
|
||||
tglEnable(TGL_DEPTH_TEST);
|
||||
tglDisable(TGL_ALPHA_TEST);
|
||||
//tglDisable(TGL_LIGHTING); // not apply here in TinyGL
|
||||
if (face->_hasTexture)
|
||||
if (!_currentShadowArray && face->_hasTexture)
|
||||
tglEnable(TGL_TEXTURE_2D);
|
||||
else
|
||||
tglDisable(TGL_TEXTURE_2D);
|
||||
@ -682,16 +704,18 @@ void GfxTinyGL::drawEMIModelFace(const EMIModel *model, const EMIMeshFace *face)
|
||||
float dim = 1.0f - _dimLevel;
|
||||
for (uint j = 0; j < face->_faceLength * 3; j++) {
|
||||
int index = indices[j];
|
||||
if (face->_hasTexture) {
|
||||
tglTexCoord2f(model->_texVerts[index].getX(), model->_texVerts[index].getY());
|
||||
}
|
||||
if (!_currentShadowArray) {
|
||||
if (face->_hasTexture) {
|
||||
tglTexCoord2f(model->_texVerts[index].getX(), model->_texVerts[index].getY());
|
||||
}
|
||||
|
||||
Math::Vector3d lighting = model->_lighting[index];
|
||||
byte r = (byte)(model->_colorMap[index].r * lighting.x() * dim);
|
||||
byte g = (byte)(model->_colorMap[index].g * lighting.y() * dim);
|
||||
byte b = (byte)(model->_colorMap[index].b * lighting.z() * dim);
|
||||
byte a = (int)(model->_colorMap[index].a * _alpha);
|
||||
tglColor4ub(r, g, b, a);
|
||||
Math::Vector3d lighting = model->_lighting[index];
|
||||
byte r = (byte)(model->_colorMap[index].r * lighting.x() * dim);
|
||||
byte g = (byte)(model->_colorMap[index].g * lighting.y() * dim);
|
||||
byte b = (byte)(model->_colorMap[index].b * lighting.z() * dim);
|
||||
byte a = (int)(model->_colorMap[index].a * _alpha);
|
||||
tglColor4ub(r, g, b, a);
|
||||
}
|
||||
|
||||
Math::Vector3d normal = model->_normals[index];
|
||||
Math::Vector3d vertex = model->_drawVertices[index];
|
||||
@ -706,8 +730,9 @@ void GfxTinyGL::drawEMIModelFace(const EMIModel *model, const EMIMeshFace *face)
|
||||
tglEnable(TGL_ALPHA_TEST);
|
||||
//tglEnable(TGL_LIGHTING); // not apply here in TinyGL
|
||||
tglDisable(TGL_BLEND);
|
||||
tglDepthMask(TGL_TRUE);
|
||||
tglColor3f(1.0f, 1.0f, 1.0f);
|
||||
|
||||
if (!_currentShadowArray)
|
||||
tglDepthMask(TGL_TRUE);
|
||||
}
|
||||
|
||||
void GfxTinyGL::drawModelFace(const Mesh *mesh, const MeshFace *face) {
|
||||
|
@ -55,8 +55,8 @@ Set::Set(const Common::String &sceneName, Common::SeekableReadStream *data) :
|
||||
Set::Set() :
|
||||
_cmaps(nullptr), _locked(false), _enableLights(false), _numSetups(0),
|
||||
_numLights(0), _numSectors(0), _numObjectStates(0), _minVolume(0),
|
||||
_maxVolume(0), _numCmaps(0), _currSetup(nullptr), _setups(nullptr),
|
||||
_lights(nullptr), _sectors(nullptr) {
|
||||
_maxVolume(0), _numCmaps(0), _numShadows(0), _currSetup(nullptr),
|
||||
_setups(nullptr), _lights(nullptr), _sectors(nullptr), _shadows(nullptr) {
|
||||
|
||||
}
|
||||
|
||||
@ -79,6 +79,7 @@ Set::~Set() {
|
||||
_states.pop_front();
|
||||
delete s;
|
||||
}
|
||||
delete[] _shadows;
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,6 +177,7 @@ void Set::loadBinary(Common::SeekableReadStream *data) {
|
||||
_numLights = 0;
|
||||
_lights = nullptr;
|
||||
_sectors = nullptr;
|
||||
_shadows = nullptr;
|
||||
|
||||
_minVolume = 0;
|
||||
_maxVolume = 0;
|
||||
@ -198,6 +200,13 @@ void Set::loadBinary(Common::SeekableReadStream *data) {
|
||||
_sectors[i]->loadBinary(data);
|
||||
}
|
||||
|
||||
_numShadows = data->readUint32LE();
|
||||
_shadows = new SetShadow[_numShadows];
|
||||
|
||||
for (int i = 0; i < _numShadows; ++i) {
|
||||
_shadows[i].loadBinary(data);
|
||||
}
|
||||
|
||||
// Enable lights by default
|
||||
_enableLights = true;
|
||||
}
|
||||
@ -553,6 +562,34 @@ bool Light::restoreState(SaveGame *savedState) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetShadow::loadBinary(Common::SeekableReadStream *data) {
|
||||
uint32 nameLen = data->readUint32LE();
|
||||
char *name = new char[nameLen];
|
||||
data->read(name, nameLen);
|
||||
_name = Common::String(name);
|
||||
|
||||
data->skip(5); // Unknown
|
||||
|
||||
data->read(&_shadowPoint.x(), 4);
|
||||
data->read(&_shadowPoint.y(), 4);
|
||||
data->read(&_shadowPoint.z(), 4);
|
||||
|
||||
int numSectors = data->readSint32LE();
|
||||
for (int i = 0; i < numSectors; ++i) {
|
||||
uint32 sectorNameLen = data->readUint32LE();
|
||||
char *sectorName = new char[sectorNameLen];
|
||||
data->read(sectorName, sectorNameLen);
|
||||
_sectorNames.push_back(sectorName);
|
||||
delete[] sectorName;
|
||||
}
|
||||
|
||||
data->skip(4); // Unknown
|
||||
_color._vals[0] = (byte)data->readSint32LE();
|
||||
_color._vals[1] = (byte)data->readSint32LE();
|
||||
_color._vals[2] = (byte)data->readSint32LE();
|
||||
delete[] name;
|
||||
}
|
||||
|
||||
void Set::Setup::setupCamera() const {
|
||||
// Ignore nclip_ and fclip_ for now. This fixes:
|
||||
// (a) Nothing was being displayed in the Land of the Living
|
||||
@ -931,4 +968,17 @@ void Set::moveObjectStateToBack(const ObjectState::Ptr &s) {
|
||||
_states.push_back(s);
|
||||
}
|
||||
|
||||
SetShadow *Set::getShadow(int i) {
|
||||
return &_shadows[i];
|
||||
}
|
||||
|
||||
SetShadow *Set::getShadowByName(const Common::String &name) {
|
||||
for (int i = 0; i < _numShadows; ++i) {
|
||||
SetShadow *shadow = &_shadows[i];
|
||||
if (shadow->_name.equalsIgnoreCase(name))
|
||||
return shadow;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // end of namespace Grim
|
||||
|
@ -39,6 +39,7 @@ namespace Grim {
|
||||
class SaveGame;
|
||||
class CMap;
|
||||
class Light;
|
||||
class SetShadow;
|
||||
|
||||
class Set : public PoolObject<Set> {
|
||||
public:
|
||||
@ -134,17 +135,22 @@ public:
|
||||
const Common::List<Light *> &getLights() { return _lightsList; }
|
||||
const Math::Frustum &getFrustum() { return _frustum; }
|
||||
|
||||
int getShadowCount() const { return _numShadows; }
|
||||
SetShadow *getShadow(int i);
|
||||
SetShadow *getShadowByName(const Common::String &name);
|
||||
|
||||
private:
|
||||
bool _locked;
|
||||
Common::String _name;
|
||||
int _numCmaps;
|
||||
ObjectPtr<CMap> *_cmaps;
|
||||
int _numSetups, _numLights, _numSectors, _numObjectStates;
|
||||
int _numSetups, _numLights, _numSectors, _numObjectStates, _numShadows;
|
||||
bool _enableLights;
|
||||
Sector **_sectors;
|
||||
Light *_lights;
|
||||
Common::List<Light *> _lightsList;
|
||||
Setup *_setups;
|
||||
SetShadow *_shadows;
|
||||
|
||||
Setup *_currSetup;
|
||||
typedef Common::List<ObjectState::Ptr> StateList;
|
||||
@ -179,6 +185,17 @@ public:
|
||||
int _id;
|
||||
};
|
||||
|
||||
class SetShadow { // Set shadow data (EMI)
|
||||
public:
|
||||
void loadBinary(Common::SeekableReadStream *data);
|
||||
|
||||
Common::String _name;
|
||||
Math::Vector3d _shadowPoint;
|
||||
int _numSectors;
|
||||
Common::List<Common::String> _sectorNames;
|
||||
Color _color;
|
||||
};
|
||||
|
||||
} // end of namespace Grim
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user