bool Actor::shouldDrawShadow(int shadowId) { Shadow *shadow = &_shadowArray[shadowId]; if (!shadow->active) return false; // Don't draw a shadow if the shadow caster and the actor are on different sides // of the the shadow plane. Sector *sector = shadow->planeList.front().sector; Math::Vector3d n = sector->getNormal(); Math::Vector3d p = sector->getVertices()[0]; float d = -(n.x() * p.x() + n.y() * p.y() + n.z() * p.z()); p = getPos(); // Move the tested point a bit above ground level. if (g_grim->getGameType() == GType_MONKEY4) p.y() += 0.01; else p.z() += 0.01; bool actorSide = n.x() * p.x() + n.y() * p.y() + n.z() * p.z() + d < 0.f; p = shadow->pos; bool shadowSide = n.x() * p.x() + n.y() * p.y() + n.z() * p.z() + d < 0.f; if (actorSide == shadowSide) return true; return false; }
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 Actor::walkForward() { float dist = g_grim->getPerSecond(_walkRate); // Limit the amount of the movement per frame, otherwise with low fps // scripts that use WalkActorForward and proximity may break. if ((dist > 0 && dist > _walkRate / 5.f) || (dist < 0 && dist < _walkRate / 5.f)) dist = _walkRate / 5.f; _walking = false; if (! _constrain) { Math::Vector3d forwardVec(-_moveYaw.getSine() * _pitch.getCosine(), _moveYaw.getCosine() * _pitch.getCosine(), _pitch.getSine()); // EMI: Y is up-down, sectors use an X-Z plane for movement if (g_grim->getGameType() == GType_MONKEY4) { float temp = forwardVec.z(); forwardVec.z() = forwardVec.y(); forwardVec.y() = temp; } _pos += forwardVec * dist; _walkedCur = true; return; } bool backwards = false; if (dist < 0) { dist = -dist; backwards = true; } int tries = 0; while (dist > 0.0f) { Math::Vector3d forwardVec(-_moveYaw.getSine() * _pitch.getCosine(), _moveYaw.getCosine() * _pitch.getCosine(), _pitch.getSine()); // EMI: Y is up-down, sectors use an X-Z plane for movement if (g_grim->getGameType() == GType_MONKEY4) { float temp = forwardVec.z(); forwardVec.z() = forwardVec.y(); forwardVec.y() = temp; } if (backwards) forwardVec = -forwardVec; Sector *currSector = NULL, *prevSector = NULL, *startSector = NULL; Sector::ExitInfo ei; g_grim->getCurrSet()->findClosestSector(_pos, &currSector, &_pos); if (!currSector) { // Shouldn't happen... moveTo(_pos + forwardVec * dist); _walkedCur = true; return; } startSector = currSector; float oldDist = dist; while (currSector) { prevSector = currSector; Math::Vector3d puckVec = currSector->getProjectionToPuckVector(forwardVec); puckVec /= puckVec.getMagnitude(); currSector->getExitInfo(_pos, puckVec, &ei); float exitDist = (ei.exitPoint - _pos).getMagnitude(); if (dist < exitDist) { moveTo(_pos + puckVec * dist); _walkedCur = true; return; } _pos = ei.exitPoint; dist -= exitDist; if (exitDist > 0.0001) _walkedCur = true; // Check for an adjacent sector which can continue // the path currSector = g_grim->getCurrSet()->findPointSector(ei.exitPoint + (float)0.0001 * puckVec, Sector::WalkType); // EMI: some sectors are significantly higher/lower than others. if (currSector && g_grim->getGameType() == GType_MONKEY4) { float planeDist = currSector->distanceToPoint(_pos); if (fabs(planeDist) < 1.f) _pos -= planeDist * currSector->getNormal(); } if (currSector == prevSector || currSector == startSector) break; } int turnDir = 1; if (ei.angleWithEdge > 90) { ei.angleWithEdge = 180 - ei.angleWithEdge; ei.edgeDir = -ei.edgeDir; turnDir = -1; } if (ei.angleWithEdge > _reflectionAngle) return; ei.angleWithEdge += (float)1.0f; turnTo(0, _moveYaw + ei.angleWithEdge * turnDir, 0); if (oldDist <= dist + 0.001f) { // If we didn't move at all, keep trying a couple more times // in case we can move in the new direction. tries++; if (tries > 3) break; } } }