diff --git a/engines/trecision/3d.cpp b/engines/trecision/3d.cpp index fb17c3aa846..65a275b4dd4 100644 --- a/engines/trecision/3d.cpp +++ b/engines/trecision/3d.cpp @@ -21,6 +21,9 @@ */ #include "trecision/3d.h" +#include "trecision/anim.h" +#include "trecision/sound.h" +#include "trecision/text.h" #include "trecision/actor.h" #include "trecision/graphics.h" #include "trecision/trecision.h" @@ -129,18 +132,12 @@ Renderer3D::Renderer3D(TrecisionEngine *vm) : _vm(vm) { _shadowIntens[i] = 0; for (int i = 0; i < MAXVERTEX; ++i) { - _vVertex[i]._x = 0; - _vVertex[i]._y = 0; - _vVertex[i]._z = 0; - _vVertex[i]._angle = 0; - - _shVertex[i]._x = 0; - _shVertex[i]._y = 0; - _shVertex[i]._z = 0; - _shVertex[i]._nx = 0; - _shVertex[i]._ny = 0; - _shVertex[i]._nz = 0; + _vVertex[i].clear(); + _shVertex[i].clear(); } + + DObj.rect = Common::Rect(0, 0, 0, 0); + DObj.l = Common::Rect(0, 0, 0, 0); } Renderer3D::~Renderer3D() { @@ -841,6 +838,198 @@ void Renderer3D::drawCharacter(uint8 flag) { } } +void Renderer3D::paintScreen(bool flag) { + _vm->_animTypeMgr->next(); + + _vm->_actorRect = nullptr; + _vm->_dirtyRects.clear(); + _vm->_flagPaintCharacter = true; // always redraws the character + + int x1 = _vm->_actor->_lim[0]; + int y1 = _vm->_actor->_lim[2] - TOP; + int x2 = _vm->_actor->_lim[1]; + int y2 = _vm->_actor->_lim[3] - TOP; + + // erase character + if (_vm->_flagShowCharacter && x2 > x1 && y2 > y1) { // if a description exists + DObj.rect = Common::Rect(0, TOP, MAXX, AREA + TOP); + DObj.l = Common::Rect(x1, y1, x2, y2); + DObj.objIndex = -1; + DObj.drawMask = false; + _vm->_graphicsMgr->DrawObj(DObj); + + _vm->addDirtyRect(DObj.l); + _vm->_actorRect = &_vm->_dirtyRects.back(); + } else if (_vm->_animMgr->_animRect.left != MAXX) { + DObj.rect = Common::Rect(0, TOP, MAXX, AREA + TOP); + DObj.l = _vm->_animMgr->_animRect; + DObj.objIndex = -1; + DObj.drawMask = false; + _vm->_graphicsMgr->DrawObj(DObj); + + _vm->addDirtyRect(DObj.l); + _vm->_actorRect = &_vm->_dirtyRects.back(); + } + + // If there's text to remove + if (TextStatus & TEXT_DEL) { + // remove text + DObj.rect = Common::Rect(0, TOP, MAXX, MAXY + TOP); + DObj.l = _vm->_textMgr->getOldTextRect(); + DObj.l.translate(0, -TOP); + DObj.objIndex = -1; + DObj.drawMask = false; + + if (DObj.l.top >= 0 && DObj.l.bottom < AREA) { + _vm->_graphicsMgr->DrawObj(DObj); + } else { + _vm->_graphicsMgr->EraseObj(DObj); + } + _vm->_textMgr->clearOldText(); + _vm->addDirtyRect(DObj.l); + + if (!(TextStatus & TEXT_DRAW)) // if there's no new text + TextStatus = TEXT_OFF; // stop updating text + } + + // Suppress all the objects you removed + for (Common::List::iterator i = _vm->_sortTable.begin(); i != _vm->_sortTable.end(); ++i) { + if (i->_remove) { + DObj.rect = Common::Rect(0, TOP, MAXX, AREA + TOP); + + DObj.l = _vm->_obj[i->_objectId]._rect; + DObj.objIndex = -1; + DObj.drawMask = false; + _vm->_graphicsMgr->DrawObj(DObj); + _vm->addDirtyRect(DObj.l); + } + } + + // Find the position of the character + _vm->_pathFind->actorOrder(); + + // For every box from the horizon forward... + // Copy per level + for (int liv = _vm->_pathFind->_numSortPan; liv >= 0; liv--) { + uint16 curBox = _vm->_pathFind->_sortPan[liv]._num; + + // draws all objects and animations that intersect the boundaries and refer to the current box + paintObjAnm(curBox); + } + + if (TextStatus & TEXT_DRAW) { + _vm->_textMgr->drawCurString(); + TextStatus = TEXT_DRAW; // Activate text update + } + + _vm->_soundMgr->SoundPasso((_vm->_actor->_lim[1] + _vm->_actor->_lim[0]) / 2, (_vm->_actor->_lim[5] + _vm->_actor->_lim[4]) / 2, _vm->_actor->_curAction, _vm->_actor->_curFrame, _vm->_room[_vm->_curRoom]._sounds); + + if (!flag && !_vm->_flagDialogActive) { + _vm->_graphicsMgr->copyToScreen(0, 0, MAXX, MAXY); + } + + _vm->_sortTable.clear(); + + _vm->_flagPaintCharacter = false; + _vm->_flagWaitRegen = false; + + // Handle papaverine delayed action + if ((_vm->_curRoom == kRoom4A) && (_vm->_obj[oCHOCOLATES4A]._flag & kObjFlagExtra)) { + if (_vm->_animMgr->smkCurFrame(kSmackerBackground) > 480) { + _vm->playScript(s4AHELLEN); + _vm->_obj[oCHOCOLATES4A]._flag &= ~kObjFlagExtra; + } + } + // +} + +/* ------------------------------------------------- + Draw all objects and animations that intersect + boundaries belonging to curbox + --------------------------------------------------*/ +void Renderer3D::paintObjAnm(uint16 curBox) { + _vm->_animMgr->refreshAnim(curBox); + + // draws new cards belonging to the current box + for (Common::List::iterator i = _vm->_sortTable.begin(); i != _vm->_sortTable.end(); ++i) { + if (!i->_remove && _vm->_obj[i->_objectId]._nbox == curBox) { + // the bitmap object at the desired level + SObject obj = _vm->_obj[i->_objectId]; + DObj.rect = obj._rect; + DObj.rect.translate(0, TOP); + DObj.l = Common::Rect(DObj.rect.width(), DObj.rect.height()); + DObj.objIndex = _vm->getRoomObjectIndex(i->_objectId); + DObj.drawMask = obj._mode & OBJMODE_MASK; + _vm->_graphicsMgr->DrawObj(DObj); + _vm->_dirtyRects.push_back(DObj.rect); + } + } + + for (DirtyRectsIterator d = _vm->_dirtyRects.begin(); d != _vm->_dirtyRects.end(); ++d) { + for (int b = 0; b < MAXOBJINROOM; b++) { + const uint16 curObject = _vm->_room[_vm->_curRoom]._object[b]; + if (!curObject) + break; + + SObject obj = _vm->_obj[curObject]; + + if ((obj._mode & (OBJMODE_FULL | OBJMODE_MASK)) && _vm->isObjectVisible(curObject) && (obj._nbox == curBox)) { + Common::Rect r = *d; + Common::Rect r2 = obj._rect; + + r2.translate(0, TOP); + + // Include the bottom right of the rect in the intersects() check + r2.bottom++; + r2.right++; + + if (r.intersects(r2)) { + DObj.rect = obj._rect; + DObj.rect.translate(0, TOP); + + // Restore the bottom right of the rect + r2.bottom--; + r2.right--; + + // TODO: Simplify this? + const int16 xr1 = (r2.left > r.left) ? 0 : r.left - r2.left; + const int16 yr1 = (r2.top > r.top) ? 0 : r.top - r2.top; + const int16 xr2 = MIN(r.right, r2.right) - r2.left; + const int16 yr2 = MIN(r.bottom, r2.bottom) - r2.top; + DObj.l = Common::Rect(xr1, yr1, xr2, yr2); + DObj.objIndex = b; + DObj.drawMask = obj._mode & OBJMODE_MASK; + + _vm->_graphicsMgr->DrawObj(DObj); + } + } + } + } + + if (_vm->_actorPos == curBox && _vm->_flagShowCharacter && _vm->_flagCharacterExists) { + drawCharacter(CALCPOINTS); + + int x1 = _vm->_actor->_lim[0]; + int y1 = _vm->_actor->_lim[2]; + int x2 = _vm->_actor->_lim[1]; + int y2 = _vm->_actor->_lim[3]; + + if (x2 > x1 && y2 > y1) { + // enlarge the rectangle of the character + Common::Rect l(x1, y1, x2, y2); + if (_vm->_actorRect) + _vm->_actorRect->extend(l); + + resetZBuffer(x1, y1, x2, y2); + } + + drawCharacter(DRAWFACES); + + } else if (_vm->_actorPos == curBox && !_vm->_flagDialogActive) { + _vm->_animMgr->refreshSmkAnim(_vm->_animMgr->_playingAnims[kSmackerAction]); + } +} + // Path Finding PathFinding3D::PathFinding3D(TrecisionEngine *vm) : _vm(vm) { _lookX = 0.0f; @@ -853,13 +1042,8 @@ PathFinding3D::PathFinding3D(TrecisionEngine *vm) : _vm(vm) { _panelNum = 0; - for (int i = 0; i < MAXPATHNODES; ++i) { - _pathNode[i]._x = 0.0f; - _pathNode[i]._z = 0.0f; - _pathNode[i]._dist = 0.0f; - _pathNode[i]._oldPanel = 0; - _pathNode[i]._curPanel = 0; - } + for (int i = 0; i < MAXPATHNODES; ++i) + _pathNode[i].clear(); _curPanel = -1; _oldPanel = -1; @@ -872,6 +1056,23 @@ PathFinding3D::PathFinding3D(TrecisionEngine *vm) : _vm(vm) { _curX = 0.0f; _curZ = 0.0f; + + for (int i = 0; i < 3; ++i) { + _invP[i][0] = 0.0f; + _invP[i][1] = 0.0f; + _invP[i][2] = 0.0f; + } + + for (int i = 0; i < MAXPANELSINROOM; ++i) + _panel[i].clear(); + + for (int i = 0; i < 32; ++i) { + _sortPan[i]._num = 0; + _sortPan[i]._min = 0.0f; + } + + for (int i = 0; i < MAXSTEP; ++i) + _step[i].clear(); } PathFinding3D::~PathFinding3D() { @@ -1345,7 +1546,7 @@ void PathFinding3D::findShortPath() { --------------------------------------------------*/ float PathFinding3D::evalPath(int a, float destX, float destZ, int nearP) { int b = 0; - float len = 0.0; + float len = 0.0f; int curPanel = _pathNode[a]._curPanel; float curX = _pathNode[a]._x; @@ -1635,7 +1836,7 @@ void PathFinding3D::buildFramelist() { } float len = 0.0; - float curlen = 0.0; + float curLen = 0.0; float ox = _pathNode[0]._x; float oz = _pathNode[0]._z; @@ -1655,77 +1856,77 @@ void PathFinding3D::buildFramelist() { int a = 0; // compute offset SVertex *v = _vm->_actor->_characterArea; - float firstframe = _vm->_actor->FRAMECENTER(v); - float startpos = 0.0; + float firstFrame = _vm->_actor->FRAMECENTER(v); + float startPos = 0.0; // if he was already walking - int CurA, CurF, cfp; + int curAction, curFrame, cfp; if (_vm->_actor->_curAction == hWALK) { // compute current frame cfp = _vm->_defActionLen[hSTART] + 1 + _vm->_actor->_curFrame; v += cfp * _vm->_actor->_vertexNum; - CurA = hWALK; - CurF = _vm->_actor->_curFrame; + curAction = hWALK; + curFrame = _vm->_actor->_curFrame; // if it wasn't the last frame, take the next step if (_vm->_actor->_curFrame < _vm->_defActionLen[hWALK] - 1) { cfp++; - CurF++; + curFrame++; v += _vm->_actor->_vertexNum; } } else if ((_vm->_actor->_curAction >= hSTOP0) && (_vm->_actor->_curAction <= hSTOP9)) { // if he was stopped, starts moving again // compute current frame - CurA = hWALK; + curAction = hWALK; //o CurF = _vm->_actor->_curAction - hSTOP1; - CurF = _vm->_actor->_curAction - hSTOP0; + curFrame = _vm->_actor->_curAction - hSTOP0; - cfp = _vm->_defActionLen[hSTART] + 1 + CurF; + cfp = _vm->_defActionLen[hSTART] + 1 + curFrame; v += cfp * _vm->_actor->_vertexNum; } else { // if he was standing, start working or turn oz = 0.0; cfp = 1; - CurA = hSTART; - CurF = 0; + curAction = hSTART; + curFrame = 0; // start from the first frame v += _vm->_actor->_vertexNum; } - oz = -_vm->_actor->FRAMECENTER(v) + firstframe; + oz = -_vm->_actor->FRAMECENTER(v) + firstFrame; // at this point, CurA / _curAction is either hSTART or hWALK // until it arrives at the destination - while (((curlen = oz + _vm->_actor->FRAMECENTER(v) - firstframe) < len) || (!a)) { - _step[a]._pz = oz - firstframe; // where to render - _step[a]._dz = curlen; // where it is - _step[a]._curAction = CurA; - _step[a]._curFrame = CurF; + while (((curLen = oz + _vm->_actor->FRAMECENTER(v) - firstFrame) < len) || (!a)) { + _step[a]._pz = oz - firstFrame; // where to render + _step[a]._dz = curLen; // where it is + _step[a]._curAction = curAction; + _step[a]._curFrame = curFrame; a++; v += _vm->_actor->_vertexNum; - CurF++; + curFrame++; cfp++; - if (CurF >= _vm->_defActionLen[CurA]) { - if (CurA == hSTART) { - CurA = hWALK; - CurF = 0; + if (curFrame >= _vm->_defActionLen[curAction]) { + if (curAction == hSTART) { + curAction = hWALK; + curFrame = 0; cfp = _vm->_defActionLen[hSTART] + 1; ox = 0.0; - } else if (CurA == hWALK) { - CurA = hWALK; - CurF = 0; + } else if (curAction == hWALK) { + curAction = hWALK; + curFrame = 0; cfp = _vm->_defActionLen[hSTART] + 1; // end walk frame - ox = _vm->_actor->FRAMECENTER(v) - firstframe; + ox = _vm->_actor->FRAMECENTER(v) - firstFrame; v = &_vm->_actor->_characterArea[cfp * _vm->_actor->_vertexNum]; ox -= _vm->_actor->FRAMECENTER(v); @@ -1734,7 +1935,7 @@ void PathFinding3D::buildFramelist() { v = &_vm->_actor->_characterArea[cfp * _vm->_actor->_vertexNum]; // only if it doesn't end - if ((oz + ox + _vm->_actor->FRAMECENTER(v) - firstframe) < len) + if ((oz + ox + _vm->_actor->FRAMECENTER(v) - firstFrame) < len) oz += ox; else break; @@ -1748,35 +1949,35 @@ void PathFinding3D::buildFramelist() { // if he was walking if (_step[a - 1]._curAction == hWALK) - CurA = _step[a - 1]._curFrame + hSTOP0; // stop previous step. + curAction = _step[a - 1]._curFrame + hSTOP0; // stop previous step. else - CurA = hSTOP0; // stop step 01 + curAction = hSTOP0; // stop step 01 - assert(CurA <= hLAST); // _defActionLen below has a size of hLAST + 1 + assert(curAction <= hLAST); // _defActionLen below has a size of hLAST + 1 - CurF = 0; + curFrame = 0; int b = 0; cfp = 0; - while (b != CurA) + while (b != curAction) cfp += _vm->_defActionLen[b++]; v = &_vm->_actor->_characterArea[cfp * _vm->_actor->_vertexNum]; - for (b = 0; b < _vm->_defActionLen[CurA]; b++) { - curlen = oz + _vm->_actor->FRAMECENTER(v) - firstframe; - _step[a]._pz = oz - firstframe; // where to render - _step[a]._dz = curlen; // where it is - _step[a]._curAction = CurA; - _step[a]._curFrame = CurF; + for (b = 0; b < _vm->_defActionLen[curAction]; b++) { + curLen = oz + _vm->_actor->FRAMECENTER(v) - firstFrame; + _step[a]._pz = oz - firstFrame; // where to render + _step[a]._dz = curLen; // where it is + _step[a]._curAction = curAction; + _step[a]._curFrame = curFrame; a++; - CurF++; + curFrame++; v += _vm->_actor->_vertexNum; } // how far is it from the destination? - float approx = (len - curlen - EPSILON) / (a - 2); + float approx = (len - curLen - EPSILON) / (a - 2); float theta = 0.0; // Adjust all the steps so it arrives exactly where clicked for (b = 1; b < a; b++) { @@ -1799,9 +2000,9 @@ void PathFinding3D::buildFramelist() { b = 0; len = 0.0; - startpos = 0.0; + startPos = 0.0; for (a = 0; a < _numPathNodes - 1; a++) { - curlen = 0.0; + curLen = 0.0; len += _vm->dist3D(_pathNode[a]._x, 0.0, _pathNode[a]._z, _pathNode[a + 1]._x, 0.0, _pathNode[a + 1]._z); @@ -1824,19 +2025,19 @@ void PathFinding3D::buildFramelist() { theta += 360.0; while ((b < _lastStep) && (_step[b]._dz <= len)) { - curlen = (_step[b]._dz - _step[b]._pz); + curLen = (_step[b]._dz - _step[b]._pz); - _step[b]._px = _pathNode[a]._x + (_step[b]._pz - startpos) * ox; - _step[b]._pz = _pathNode[a]._z + (_step[b]._pz - startpos) * oz; - _step[b]._dx = curlen * ox; - _step[b]._dz = curlen * oz; + _step[b]._px = _pathNode[a]._x + (_step[b]._pz - startPos) * ox; + _step[b]._pz = _pathNode[a]._z + (_step[b]._pz - startPos) * oz; + _step[b]._dx = curLen * ox; + _step[b]._dz = curLen * oz; _step[b]._theta = theta; _step[b]._curPanel = _pathNode[a]._curPanel; b++; } - startpos = len; + startPos = len; } reset(b, _curX, _curZ, theta); @@ -1845,13 +2046,13 @@ void PathFinding3D::buildFramelist() { _curStep = 0; // current step // starting angle - float oldtheta = _vm->_actor->_theta; + float oldTheta = _vm->_actor->_theta; // first angle walk theta = _step[0]._theta; // if he starts from standstill position if ((_step[0]._curAction == hSTART) && (_step[0]._curFrame == 0) && (_lastStep > 4) && (_step[0]._theta == _step[1]._theta)) { - approx = theta - oldtheta; + approx = theta - oldTheta; if (approx > 180.0) approx = -360.0 + approx; @@ -1861,16 +2062,16 @@ void PathFinding3D::buildFramelist() { approx /= 3.0; for (b = 0; b < 2; b++) { - _step[b]._theta = oldtheta + (float)(b + 1) * approx; + _step[b]._theta = oldTheta + (float)(b + 1) * approx; _step[b]._theta = (_step[b]._theta > 360.0) ? _step[b]._theta - 360.0 : (_step[b]._theta < 0.0) ? _step[b]._theta + 360.0 : _step[b]._theta; theta = _step[b]._theta; - curlen = sqrt(_step[b]._dx * _step[b]._dx + _step[b]._dz * _step[b]._dz); + curLen = sqrt(_step[b]._dx * _step[b]._dx + _step[b]._dz * _step[b]._dz); theta = ((270.0 - theta) * PI) / 180.0; - ox = cos(theta) * curlen; - oz = sin(theta) * curlen; + ox = cos(theta) * curLen; + oz = sin(theta) * curLen; cx = _step[b]._px + _step[b]._dx; float cz = _step[b]._pz + _step[b]._dz; @@ -1884,13 +2085,13 @@ void PathFinding3D::buildFramelist() { } // makes the curve - oldtheta = _step[2]._theta; + oldTheta = _step[2]._theta; for (b = 3; b <= _lastStep; b++) { theta = _step[b]._theta; // if it made a curve - if (oldtheta != theta) { - approx = theta - oldtheta; + if (oldTheta != theta) { + approx = theta - oldTheta; if (approx > 180.0) approx = -360.0 + approx; @@ -1903,14 +2104,14 @@ void PathFinding3D::buildFramelist() { _step[b - 1]._theta += approx; _step[b - 1]._theta = (_step[b - 1]._theta > 360.0) ? _step[b - 1]._theta - 360.0 : (_step[b - 1]._theta < 0.0) ? _step[b - 1]._theta + 360.0 : _step[b - 1]._theta; - oldtheta = _step[b - 1]._theta; - startpos = oldtheta; + oldTheta = _step[b - 1]._theta; + startPos = oldTheta; - curlen = sqrt(_step[b - 1]._dx * _step[b - 1]._dx + _step[b - 1]._dz * _step[b - 1]._dz); + curLen = sqrt(_step[b - 1]._dx * _step[b - 1]._dx + _step[b - 1]._dz * _step[b - 1]._dz); - oldtheta = ((270.0 - oldtheta) * PI) / 180.0; - ox = cos(oldtheta) * curlen; - oz = sin(oldtheta) * curlen; + oldTheta = ((270.0 - oldTheta) * PI) / 180.0; + ox = cos(oldTheta) * curLen; + oz = sin(oldTheta) * curLen; cx = _step[b - 1]._px + _step[b - 1]._dx; float cz = _step[b - 1]._pz + _step[b - 1]._dz; @@ -1925,14 +2126,14 @@ void PathFinding3D::buildFramelist() { _step[b]._theta -= approx; _step[b]._theta = (_step[b]._theta > 360.0) ? _step[b]._theta - 360.0 : (_step[b]._theta < 0.0) ? _step[b]._theta + 360.0 : _step[b]._theta; - oldtheta = theta; + oldTheta = theta; theta = _step[b]._theta; - curlen = sqrt(_step[b]._dx * _step[b]._dx + _step[b]._dz * _step[b]._dz); + curLen = sqrt(_step[b]._dx * _step[b]._dx + _step[b]._dz * _step[b]._dz); theta = ((270.0 - theta) * PI) / 180.0; - ox = cos(theta) * curlen; - oz = sin(theta) * curlen; + ox = cos(theta) * curLen; + oz = sin(theta) * curLen; cx = _step[b]._px + _step[b]._dx; cz = _step[b]._pz + _step[b]._dz; @@ -1944,7 +2145,7 @@ void PathFinding3D::buildFramelist() { _step[b]._dz = cz - _step[b]._pz; } else - oldtheta = theta; + oldTheta = theta; } lookAt(_lookX, _lookZ); diff --git a/engines/trecision/3d.h b/engines/trecision/3d.h index 00ecf586c15..0f60ffb691b 100644 --- a/engines/trecision/3d.h +++ b/engines/trecision/3d.h @@ -30,6 +30,11 @@ namespace Trecision { struct SVVertex { int32 _x, _y, _z; int32 _angle; + + void clear() { + _x = _y = _z = 0; + _angle = 0; + } }; struct SSortPan { @@ -42,6 +47,13 @@ struct SPathNode { float _dist; int16 _oldPanel; int16 _curPanel; + + void clear() { + _x = _z = 0.0f; + _dist = 0.0f; + _oldPanel = 0; + _curPanel = 0; + } }; struct SPan { @@ -53,6 +65,15 @@ struct SPan { char _near2; char _col1; char _col2; + + void clear() { + _x1 = _z1 = 0.0f; + _x2 = _z2 = 0.0f; + _h = 0.0f; + _flags = 0; + _near1 = _near2 = 0; + _col1 = _col2 = 0; + } }; struct SStep { @@ -62,6 +83,15 @@ struct SStep { int _curAction; int _curFrame; int16 _curPanel; + + void clear() { + _px = _pz = 0.0f; + _dx = _dz = 0.0f; + _theta = 0.0f; + _curAction = 0; + _curFrame = 0; + _curPanel = 0; + } }; class Renderer3D { @@ -100,12 +130,15 @@ private: uint16 _lTextY[480]; uint16 _rTextY[480]; + SDObj DObj; + void setZBufferRegion(int16 sx, int16 sy, int16 dx); int8 clockWise(int16 x1, int16 y1, int16 x2, int16 y2, int16 x3, int16 y3); void textureTriangle(int32 x1, int32 y1, int32 z1, int32 c1, int32 tx1, int32 ty1, int32 x2, int32 y2, int32 z2, int32 c2, int32 tx2, int32 ty2, int32 x3, int32 y3, int32 z3, int32 c3, int32 tx3, int32 ty3, STexture *t); void textureScanEdge(int32 x1, int32 y1, int32 z1, int32 c1, int32 tx1, int32 ty1, int32 x2, int32 y2, int32 z2, int32 c2, int32 tx2, int32 ty2); void shadowTriangle(int32 x1, int32 y1, int32 x2, int32 y2, int32 x3, int32 y3, uint8 cv, int32 zv); void shadowScanEdge(int32 x1, int32 y1, int32 x2, int32 y2); + void paintObjAnm(uint16 curBox); public: Renderer3D(TrecisionEngine *vm); @@ -115,6 +148,8 @@ public: void resetZBuffer(int x1, int y1, int x2, int y2); void setClipping(int16 x1, int16 y1, int16 x2, int16 y2); void drawCharacter(uint8 flag); + void paintScreen(bool flag); + }; // end of class class PathFinding3D { diff --git a/engines/trecision/dialog.cpp b/engines/trecision/dialog.cpp index 5515daaf2fa..9907f055b9e 100644 --- a/engines/trecision/dialog.cpp +++ b/engines/trecision/dialog.cpp @@ -126,7 +126,7 @@ void DialogManager::playDialog(uint16 i) { _vm->_inventoryCounter = INVENTORY_HIDE; _vm->_textMgr->clearLastText(); _vm->_textMgr->drawTexts(); - PaintScreen(true); + g_vm->_renderer->paintScreen(true); _vm->_graphicsMgr->clearScreenBufferTop(); _vm->_graphicsMgr->copyToScreen(0, 0, MAXX, TOP); diff --git a/engines/trecision/logic.cpp b/engines/trecision/logic.cpp index 06173494e32..00902e2c3c2 100644 --- a/engines/trecision/logic.cpp +++ b/engines/trecision/logic.cpp @@ -3055,7 +3055,7 @@ bool LogicManager::mouseOperate(uint16 curObj) { _comb49[0] = curObj; _vm->_soundMgr->play(wASTA49); if ((_comb49[3] == oFORO749) && (_comb49[2] == oFORO849) && (_comb49[1] == oFORO449) && (_comb49[0] == oFORO549)) { - PaintScreen(false); + _vm->_renderer->paintScreen(false); _vm->waitDelay(60); _vm->setObjectVisible(oOMBRAS49, true); _vm->setObjectVisible(oSCOMPARTO49, true); @@ -3111,7 +3111,7 @@ bool LogicManager::mouseOperate(uint16 curObj) { _vm->_soundMgr->play(wPAD1 + curObj - oNUMERO14C); if (a < 5) break; - PaintScreen(false); + _vm->_renderer->paintScreen(false); _vm->waitDelay(60); if ((_comb4CT[0] == 5) && (_comb4CT[1] == 6) && (_comb4CT[2] == 2) && (_comb4CT[3] == 3) && (_comb4CT[4] == 9) && (_comb4CT[5] == 6)) { @@ -3283,7 +3283,7 @@ bool LogicManager::mouseOperate(uint16 curObj) { if (_count58 < 6) break; - PaintScreen(false); + _vm->_renderer->paintScreen(false); _vm->waitDelay(60); _count58 = 0; for (int a = 0; a < 6; a++) diff --git a/engines/trecision/module.mk b/engines/trecision/module.mk index ead173adcec..edd97475a08 100644 --- a/engines/trecision/module.mk +++ b/engines/trecision/module.mk @@ -18,7 +18,6 @@ MODULE_OBJS = \ utils.o \ 3d.o \ video.o \ - nl/regen.o \ nl/schedule.o \ nl/3d/3dwalk.o \ nl/ll/llmouse.o \ diff --git a/engines/trecision/nl/ll/llscreen.cpp b/engines/trecision/nl/ll/llscreen.cpp index fc6acce28ab..998dcd7cce9 100644 --- a/engines/trecision/nl/ll/llscreen.cpp +++ b/engines/trecision/nl/ll/llscreen.cpp @@ -24,6 +24,7 @@ #include "common/scummsys.h" #include "common/str.h" #include "common/system.h" +#include "trecision/3d.h" #include "trecision/anim.h" #include "trecision/defines.h" @@ -32,7 +33,6 @@ #include "trecision/sound.h" #include "trecision/trecision.h" #include "trecision/video.h" -#include "trecision/nl/proto.h" #include "trecision/nl/struct.h" #include "trecision/nl/ll/llinc.h" @@ -93,7 +93,7 @@ void TendIn() { g_vm->_flagPaintCharacter = true; g_vm->_soundMgr->waitEndFading(); - PaintScreen(true); + g_vm->_renderer->paintScreen(true); g_vm->_graphicsMgr->copyToScreen(0, 0, MAXX, MAXY); } @@ -230,7 +230,7 @@ void RedrawRoom() { TextStatus = TEXT_OFF; g_vm->_flagPaintCharacter = true; - PaintScreen(true); + g_vm->_renderer->paintScreen(true); g_vm->_graphicsMgr->copyToScreen(0, 0, 640, 480); } diff --git a/engines/trecision/nl/proto.h b/engines/trecision/nl/proto.h index c815dae2c40..945b2b1a786 100644 --- a/engines/trecision/nl/proto.h +++ b/engines/trecision/nl/proto.h @@ -23,21 +23,14 @@ #ifndef TRECISION_PROTO_H #define TRECISION_PROTO_H -#include "common/scummsys.h" - namespace Common { class SeekableReadStream; } namespace Trecision { -struct SDObj; -struct STexture; - - -void PaintScreen(bool flag); -void PaintObjAnm(uint16 CurBox); void ProcessTheMessage(); -#endif } // End of namespace Trecision + +#endif diff --git a/engines/trecision/nl/regen.cpp b/engines/trecision/nl/regen.cpp deleted file mode 100644 index 88b9cf26fb0..00000000000 --- a/engines/trecision/nl/regen.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/util.h" -#include "common/scummsys.h" - -#include "trecision/3d.h" -#include "trecision/actor.h" -#include "trecision/anim.h" -#include "trecision/defines.h" -#include "trecision/graphics.h" -#include "trecision/sound.h" -#include "trecision/text.h" -#include "trecision/trecision.h" -#include "trecision/video.h" -#include "trecision/nl/proto.h" -#include "trecision/nl/struct.h" -#include "trecision/nl/ll/llinc.h" - -namespace Trecision { - -SDObj DObj; - -void PaintScreen(bool flag) { - g_vm->_animTypeMgr->next(); - - g_vm->_actorRect = nullptr; - g_vm->_dirtyRects.clear(); - g_vm->_flagPaintCharacter = true; // always redraws the character - - int x1 = g_vm->_actor->_lim[0]; - int y1 = g_vm->_actor->_lim[2] - TOP; - int x2 = g_vm->_actor->_lim[1]; - int y2 = g_vm->_actor->_lim[3] - TOP; - - // erase character - if (g_vm->_flagShowCharacter && x2 > x1 && y2 > y1) { // if a description exists - DObj.rect = Common::Rect(0, TOP, MAXX, AREA + TOP); - DObj.l = Common::Rect(x1, y1, x2, y2); - DObj.objIndex = -1; - DObj.drawMask = false; - g_vm->_graphicsMgr->DrawObj(DObj); - - g_vm->addDirtyRect(DObj.l); - g_vm->_actorRect = &g_vm->_dirtyRects.back(); - } else if (g_vm->_animMgr->_animRect.left != MAXX) { - DObj.rect = Common::Rect(0, TOP, MAXX, AREA + TOP); - DObj.l = g_vm->_animMgr->_animRect; - DObj.objIndex = -1; - DObj.drawMask = false; - g_vm->_graphicsMgr->DrawObj(DObj); - - g_vm->addDirtyRect(DObj.l); - g_vm->_actorRect = &g_vm->_dirtyRects.back(); - } - - // CANCELLO LA SCRITTA - if (TextStatus & TEXT_DEL) { - // cancello scritta - DObj.rect = Common::Rect(0, TOP, MAXX, MAXY + TOP); - DObj.l = g_vm->_textMgr->getOldTextRect(); - DObj.l.translate(0, -TOP); - DObj.objIndex = -1; - DObj.drawMask = false; - - if (DObj.l.top >= 0 && DObj.l.bottom < AREA) { - g_vm->_graphicsMgr->DrawObj(DObj); - } else { - g_vm->_graphicsMgr->EraseObj(DObj); - } - g_vm->_textMgr->clearOldText(); - g_vm->addDirtyRect(DObj.l); - - if (!(TextStatus & TEXT_DRAW)) // se non c'e' nuova scritta - TextStatus = TEXT_OFF; // non aggiorna piu' scritta - } - - // CANCELLA TUTTI GLI OGGETTI TOGLI - for (Common::List::iterator i = g_vm->_sortTable.begin(); i != g_vm->_sortTable.end(); ++i) { - if (i->_remove) { - DObj.rect = Common::Rect(0, TOP, MAXX, AREA + TOP); - - DObj.l = g_vm->_obj[i->_objectId]._rect; - DObj.objIndex = -1; - DObj.drawMask = false; - g_vm->_graphicsMgr->DrawObj(DObj); - g_vm->addDirtyRect(DObj.l); - } - } - - // trova la posizione dell'omino - g_vm->_pathFind->actorOrder(); - - // PER OGNI BOX DALL'ORIZZONTE IN AVANTI... - // COPIA PER LIVELLO - for (int liv = g_vm->_pathFind->_numSortPan; liv >= 0; liv--) { - uint16 CurBox = g_vm->_pathFind->_sortPan[liv]._num; - - // disegna tutti gli oggetti e le animazioni che intersecano - // i limiti e si riferiscono al box corrente - PaintObjAnm(CurBox); - - } - - if (TextStatus & TEXT_DRAW) { - g_vm->_textMgr->drawCurString(); - TextStatus = TEXT_DRAW; // Activate text update - } - - g_vm->_soundMgr->SoundPasso((g_vm->_actor->_lim[1] + g_vm->_actor->_lim[0]) / 2, (g_vm->_actor->_lim[5] + g_vm->_actor->_lim[4]) / 2, g_vm->_actor->_curAction, g_vm->_actor->_curFrame, g_vm->_room[g_vm->_curRoom]._sounds); - - if (!flag && !g_vm->_flagDialogActive) { - g_vm->_graphicsMgr->copyToScreen(0, 0, MAXX, MAXY); - } - - g_vm->_sortTable.clear(); - - g_vm->_flagPaintCharacter = false; - g_vm->_flagWaitRegen = false; - - // Handle papaverine delayed action - if ((g_vm->_curRoom == kRoom4A) && (g_vm->_obj[oCHOCOLATES4A]._flag & kObjFlagExtra)) { - if (g_vm->_animMgr->smkCurFrame(kSmackerBackground) > 480) { - g_vm->playScript(s4AHELLEN); - g_vm->_obj[oCHOCOLATES4A]._flag &= ~kObjFlagExtra; - } - } - // -} - -int getRoomObjectIndex(uint16 objectId) { - for (uint16 index = 0; index < MAXOBJINROOM; index++) { - const uint16 curObjId = g_vm->_room[g_vm->_curRoom]._object[index]; - if (curObjId == 0) - return -1; - if (curObjId == objectId) - return index; - } - - return -1; -} - -/* -----------------12/06/97 21.35------------------- - Disegna tutti gli oggetti e le animazioni che intersecano i limiti - appartenenti a curbox - --------------------------------------------------*/ -void PaintObjAnm(uint16 CurBox) { - g_vm->_animMgr->refreshAnim(CurBox); - - // disegna nuove schede appartenenti al box corrente - for (Common::List::iterator i = g_vm->_sortTable.begin(); i != g_vm->_sortTable.end(); ++i) { - if (!i->_remove) { - if (g_vm->_obj[i->_objectId]._nbox == CurBox) { - // l'oggetto bitmap al livello desiderato - SObject o = g_vm->_obj[i->_objectId]; - DObj.rect = o._rect; - DObj.rect.translate(0, TOP); - DObj.l = Common::Rect(DObj.rect.width(), DObj.rect.height()); - DObj.objIndex = getRoomObjectIndex(i->_objectId); - DObj.drawMask = o._mode & OBJMODE_MASK; - g_vm->_graphicsMgr->DrawObj(DObj); - g_vm->_dirtyRects.push_back(DObj.rect); - } - } - } - - for (DirtyRectsIterator d = g_vm->_dirtyRects.begin(); d != g_vm->_dirtyRects.end(); ++d) { - for (int b = 0; b < MAXOBJINROOM; b++) { - const uint16 curObject = g_vm->_room[g_vm->_curRoom]._object[b]; - if (!curObject) - break; - - SObject obj = g_vm->_obj[curObject]; - - if ((obj._mode & (OBJMODE_FULL | OBJMODE_MASK)) && - g_vm->isObjectVisible(curObject) && - (obj._nbox == CurBox)) { - - Common::Rect r = *d; - Common::Rect r2 = obj._rect; - - r2.translate(0, TOP); - - // Include the bottom right of the rect in the intersects() check - r2.bottom++; - r2.right++; - - if (r.intersects(r2)) { - DObj.rect = obj._rect; - DObj.rect.translate(0, TOP); - - // Restore the bottom right of the rect - r2.bottom--; - r2.right--; - - // TODO: Simplify this? - const int16 xr1 = (r2.left > r.left) ? 0 : r.left - r2.left; - const int16 yr1 = (r2.top > r.top) ? 0 : r.top - r2.top; - const int16 xr2 = MIN(r.right, r2.right) - r2.left; - const int16 yr2 = MIN(r.bottom, r2.bottom) - r2.top; - DObj.l = Common::Rect(xr1, yr1, xr2, yr2); - DObj.objIndex = b; - DObj.drawMask = obj._mode & OBJMODE_MASK; - - g_vm->_graphicsMgr->DrawObj(DObj); - } - } - } - } - - if (g_vm->_actorPos == CurBox && g_vm->_flagShowCharacter && g_vm->_flagCharacterExists) { - g_vm->_renderer->drawCharacter(CALCPOINTS); - - int x1 = g_vm->_actor->_lim[0]; - int y1 = g_vm->_actor->_lim[2]; - int x2 = g_vm->_actor->_lim[1]; - int y2 = g_vm->_actor->_lim[3]; - - if (x2 > x1 && y2 > y1) { - // enlarge the rectangle of the character - Common::Rect l(x1, y1, x2, y2); - if (g_vm->_actorRect) - g_vm->_actorRect->extend(l); - - g_vm->_renderer->resetZBuffer(x1, y1, x2, y2); - } - - g_vm->_renderer->drawCharacter(DRAWFACES); - - } else if (g_vm->_actorPos == CurBox && !g_vm->_flagDialogActive) { - g_vm->_animMgr->refreshSmkAnim(g_vm->_animMgr->_playingAnims[kSmackerAction]); - } -} - -} // End of namespace Trecision diff --git a/engines/trecision/trecision.h b/engines/trecision/trecision.h index 1d224368f39..20d8f221d7e 100644 --- a/engines/trecision/trecision.h +++ b/engines/trecision/trecision.h @@ -76,6 +76,11 @@ typedef Common::List::iterator DirtyRectsIterator; struct SVertex { float _x, _y, _z; float _nx, _ny, _nz; + + void clear() { + _x = _y = _z = 0.0f; + _nx = _ny = _nz = 0.0f; + } }; struct SFace { @@ -202,7 +207,8 @@ public: static bool isGameArea(Common::Point pos); static bool isInventoryArea(Common::Point pos); static bool isIconArea(Common::Point pos); - + int getRoomObjectIndex(uint16 objectId); + // Others void checkSystem(); bool dataSave(); diff --git a/engines/trecision/utils.cpp b/engines/trecision/utils.cpp index 0065477ed14..b2e288c16a7 100644 --- a/engines/trecision/utils.cpp +++ b/engines/trecision/utils.cpp @@ -20,6 +20,7 @@ * */ +#include "3d.h" #include "common/system.h" #include "trecision/scheduler.h" @@ -269,7 +270,7 @@ void TrecisionEngine::ProcessTime() { OldLightIcon = _lightIcon; } - PaintScreen(false); + _renderer->paintScreen(false); _textMgr->clearTextStack(); uint32 paintTime = readTime(); @@ -350,4 +351,16 @@ bool TrecisionEngine::isIconArea(Common::Point pos) { return pos.y >= TOP + AREA && pos.y < MAXY && pos.x >= ICONMARGSX && pos.x <= MAXX - ICONMARGDX; } +int TrecisionEngine::getRoomObjectIndex(uint16 objectId) { + for (uint16 index = 0; index < MAXOBJINROOM; index++) { + const uint16 curObjId = _room[g_vm->_curRoom]._object[index]; + if (curObjId == 0) + return -1; + if (curObjId == objectId) + return index; + } + + return -1; +} + } // End of namespace Trecision