void GfxTinyGL::positionCamera(Graphics::Vector3d pos, Graphics::Vector3d interest) { Graphics::Vector3d up_vec(0, 0, 1); if (pos.x() == interest.x() && pos.y() == interest.y()) up_vec = Graphics::Vector3d(0, 1, 0); lookAt(pos.x(), pos.y(), pos.z(), interest.x(), interest.y(), interest.z(), up_vec.x(), up_vec.y(), up_vec.z()); }
/** * @class Model */ Model::Model(const Common::String &filename, const char *data, int len, CMap *cmap, Model *parent) : Object(), _parent(parent), _numMaterials(0), _numGeosets(0), _cmap(cmap) { _fname = filename; if (g_grim->getGameType() == GType_MONKEY4) { Common::MemoryReadStream ms((const byte *)data, len); loadEMI(ms); } else if (len >= 4 && READ_BE_UINT32(data) == MKTAG('L','D','O','M')) loadBinary(data, cmap); else { TextSplitter ts(data, len); loadText(&ts, cmap); } Graphics::Vector3d max; _rootHierNode->update(); bool first = true; for (int i = 0; i < _numHierNodes; ++i) { ModelNode &node = _rootHierNode[i]; if (node._mesh) { Mesh &mesh = *node._mesh; //NOTE: Setting p to mesh._matrix._pos seems more similar to original // but, as in original, it also stops manny quite far away from the // bone wagon when approaching it from behind in set sg. // Using the node position looks instead more realistic, but, on the // other hand, it may not work right in all cases. Graphics::Vector3d &p = node._matrix._pos; float x = p.x(); float y = p.y(); float z = p.z(); for (int k = 0; k < mesh._numVertices * 3; k += 3) { if (first || mesh._vertices[k] + x < _bboxPos.x()) _bboxPos.x() = mesh._vertices[k] + x; if (mesh._vertices[k + 1] + y < _bboxPos.y()) _bboxPos.y() = mesh._vertices[k + 1] + y; if (mesh._vertices[k + 2] + z < _bboxPos.z()) _bboxPos.z() = mesh._vertices[k + 2] + z; if (first || mesh._vertices[k] + x > max.x()) max.x() = mesh._vertices[k] + x; if (mesh._vertices[k + 1] + y > max.y()) max.y() = mesh._vertices[k + 1] + y; if (mesh._vertices[k + 2] + z > max.z()) max.z() = mesh._vertices[k + 2] + z; first = false; } } } _bboxSize = max - _bboxPos; }
static void tglShadowProjection(Graphics::Vector3d light, Graphics::Vector3d plane, Graphics::Vector3d normal, bool dontNegate) { // Based on GPL shadow projection example by // (c) 2002-2003 Phaetos <*****@*****.**> float d, c; float mat[16]; float nx, ny, nz, lx, ly, lz, px, py, pz; nx = normal.x(); ny = normal.y(); nz = normal.z(); // for some unknown for me reason normal need negation if (!dontNegate) { nx = -nx; ny = -ny; nz = -nz; } lx = light.x(); ly = light.y(); lz = light.z(); px = plane.x(); py = plane.y(); pz = plane.z(); d = nx * lx + ny * ly + nz * lz; c = px * nx + py * ny + pz * nz - d; mat[0] = lx * nx + c; mat[4] = ny * lx; mat[8] = nz * lx; mat[12] = -lx * c - lx * d; mat[1] = nx * ly; mat[5] = ly * ny + c; mat[9] = nz * ly; mat[13] = -ly * c - ly * d; mat[2] = nx * lz; mat[6] = ny * lz; mat[10] = lz * nz + c; mat[14] = -lz * c - lz * d; mat[3] = nx; mat[7] = ny; mat[11] = nz; mat[15] = -d; tglMultMatrixf(mat); }
/* Given a position and a size this function calculates and pushes * the nearest point to that which will be valid if the boxes are * shrunk by the amount specified. */ void L1_GetShrinkPos() { lua_Object xObj = lua_getparam(1); lua_Object yObj = lua_getparam(2); lua_Object zObj = lua_getparam(3); lua_Object rObj = lua_getparam(4); if (!lua_isnumber(xObj) || !lua_isnumber(yObj) || !lua_isnumber(zObj) || !lua_isnumber(rObj)) return; float x = lua_getnumber(xObj); float y = lua_getnumber(yObj); float z = lua_getnumber(zObj); float r = lua_getnumber(rObj); Graphics::Vector3d pos; pos.set(x, y, z); Sector* sector; g_grim->getCurrScene()->shrinkBoxes(r); g_grim->getCurrScene()->findClosestSector(pos, §or, &pos); g_grim->getCurrScene()->unshrinkBoxes(); if (sector) { lua_pushnumber(pos.x()); lua_pushnumber(pos.y()); lua_pushnumber(pos.z()); } else { lua_pushnil(); } }
void GfxTinyGL::startActorDraw(Graphics::Vector3d pos, float scale, float yaw, float pitch, float roll) { tglEnable(TGL_TEXTURE_2D); tglMatrixMode(TGL_MODELVIEW); tglPushMatrix(); if (_currentShadowArray) { // TODO find out why shadowMask at device in woods is null if (!_currentShadowArray->shadowMask) { _currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight]; _currentShadowArray->shadowMaskSize = _screenWidth * _screenHeight; } assert(_currentShadowArray->shadowMask); //tglSetShadowColor(255, 255, 255); tglSetShadowColor(_shadowColorR, _shadowColorG, _shadowColorB); tglSetShadowMaskBuf(_currentShadowArray->shadowMask); SectorListType::iterator i = _currentShadowArray->planeList.begin(); Sector *shadowSector = i->sector; tglShadowProjection(_currentShadowArray->pos, shadowSector->getVertices()[0], shadowSector->getNormal(), _currentShadowArray->dontNegate); } tglTranslatef(pos.x(), pos.y(), pos.z()); tglScalef(scale, scale, scale); tglRotatef(yaw, 0, 0, 1); tglRotatef(pitch, 1, 0, 0); tglRotatef(roll, 0, 1, 0); }
void ModelNode::update() { if (!_initialized) return; Graphics::Vector3d animPos = _pos + _animPos; float animPitch = _pitch + _animPitch; float animYaw = _yaw + _animYaw; float animRoll = _roll + _animRoll; _localMatrix._pos.set(animPos.x(), animPos.y(), animPos.z()); _localMatrix._rot.buildFromPitchYawRoll(animPitch, animYaw, animRoll); _matrix *= _localMatrix; _pivotMatrix = _matrix; _pivotMatrix.translate(_pivot.x(), _pivot.y(), _pivot.z()); if (_mesh) { _mesh->_matrix = _pivotMatrix; } ModelNode *child = _child; while (child) { child->setMatrix(_matrix); child->update(); child = child->_sibling; } }
void GfxTinyGL::translateViewpointStart(Graphics::Vector3d pos, float pitch, float yaw, float roll) { tglPushMatrix(); tglTranslatef(pos.x(), pos.y(), pos.z()); tglRotatef(yaw, 0, 0, 1); tglRotatef(pitch, 1, 0, 0); tglRotatef(roll, 0, 1, 0); }
Coordinate::Coordinate(const Graphics::Vector3d &left) { _coords[0] = left.x(); _coords[1] = left.y(); _coords[2] = left.z(); _coords[3] = 1.f; _coords[4] = 0.f; _coords[5] = 0.f; _coords[6] = 0.f; }
void L1_GetSectorOppositeEdge() { lua_Object actorObj = lua_getparam(1); lua_Object nameObj = lua_getparam(2); if (!lua_isuserdata(actorObj) || lua_tag(actorObj) != MKTAG('A','C','T','R')) return; if (!lua_isstring(nameObj)) { lua_pushnil(); return; } Actor *actor = getactor(actorObj); const char *name = lua_getstring(nameObj); int numSectors = g_grim->getCurrScene()->getSectorCount(); for (int i = 0; i < numSectors; i++) { Sector *sector = g_grim->getCurrScene()->getSectorBase(i); if (strmatch(sector->getName(), name)) { if (sector->getNumVertices() != 4) warning("GetSectorOppositeEdge(): cheat box with %d (!= 4) edges!", sector->getNumVertices()); Graphics::Vector3d* vertices = sector->getVertices(); Sector::ExitInfo e; sector->getExitInfo(actor->getPos(), -actor->getPuckVector(), &e); float frac = (e.exitPoint - vertices[e.edgeVertex + 1]).magnitude() / e.edgeDir.magnitude(); e.edgeVertex -= 2; if (e.edgeVertex < 0) e.edgeVertex += sector->getNumVertices(); Graphics::Vector3d edge = vertices[e.edgeVertex + 1] - vertices[e.edgeVertex]; Graphics::Vector3d p = vertices[e.edgeVertex] + edge * frac; lua_pushnumber(p.x()); lua_pushnumber(p.y()); lua_pushnumber(p.z()); return; } } lua_pushnil(); }
void GfxTinyGL::getBoundingBoxPos(const Mesh *model, int *x1, int *y1, int *x2, int *y2) { if (_currentShadowArray) { *x1 = -1; *y1 = -1; *x2 = -1; *y2 = -1; return; } TGLfloat top = 1000; TGLfloat right = -1000; TGLfloat left = 1000; TGLfloat bottom = -1000; TGLfloat winX, winY, winZ; for (int i = 0; i < model->_numFaces; i++) { Graphics::Vector3d v; float* pVertices; for (int j = 0; j < model->_faces[i]._numVertices; j++) { TGLfloat modelView[16], projection[16]; TGLint viewPort[4]; tglGetFloatv(TGL_MODELVIEW_MATRIX, modelView); tglGetFloatv(TGL_PROJECTION_MATRIX, projection); tglGetIntegerv(TGL_VIEWPORT, viewPort); pVertices = model->_vertices + 3 * model->_faces[i]._vertices[j]; v.set(*(pVertices), *(pVertices + 1), *(pVertices + 2)); tgluProject(v.x(), v.y(), v.z(), modelView, projection, viewPort, &winX, &winY, &winZ); if (winX > right) right = winX; if (winX < left) left = winX; if (winY < top) top = winY; if (winY > bottom) bottom = winY; } } float t = bottom; bottom = 480 - top; top = 480 - t; if (left < 0) left = 0; if (right > 639) right = 639; if (top < 0) top = 0; if (bottom > 479) bottom = 479; if (top > 479 || left > 639 || bottom < 0 || right < 0) { *x1 = -1; *y1 = -1; *x2 = -1; *y2 = -1; return; } *x1 = (int)left; *y1 = (int)top; *x2 = (int)right; *y2 = (int)bottom; /* uint16 *dst = (uint16 *)_zb->pbuf; uint16 c = 0xffff; for (int x = left; x <= right; x++) { WRITE_LE_UINT16(dst + 640 * (int)top + x, c); } for (int x = left; x <= right; x++) { WRITE_LE_UINT16(dst + 640 * (int)bottom + x, c); } for (int y = top; y <= bottom; y++) { WRITE_LE_UINT16(dst + 640 * y + (int)left, c); } for (int y = top; y <= bottom; y++) { WRITE_LE_UINT16(dst + 640 * y + (int)right, c); }*/ }