void BaseRenderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) { // Screen coords to 3D coords Math::Vector3d obj; Math::gluMathUnProject(Math::Vector3d(screen.x, _system->getHeight() - screen.y, 0.9f), _mvpMatrix, frameViewport(), obj); // 3D coords to polar coords obj.normalize(); Math::Vector2d horizontalProjection = Math::Vector2d(obj.x(), obj.z()); horizontalProjection.normalize(); pitch = 90 - Math::Angle::arcCosine(obj.y()).getDegrees(); heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees(); if (horizontalProjection.getX() > 0.0) heading = 360 - heading; }
void TinyGLRenderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) { // Screen coords to 3D coords Math::Vector3d obj; Math::gluMathUnProject<float, int>(Math::Vector3d(screen.x, kOriginalHeight - screen.y, 0.9), _cubeModelViewMatrix, _cubeProjectionMatrix, _cubeViewport, obj); // 3D coords to polar coords obj.normalize(); Math::Vector2d horizontalProjection = Math::Vector2d(obj.x(), obj.z()); horizontalProjection.normalize(); pitch = 90 - Math::Angle::arcCosine(obj.y()).getDegrees(); heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees(); if (horizontalProjection.getX() > 0.0) heading = 360 - heading; }
void Renderer::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) { double x, y, z; // Screen coords to 3D coords gluUnProject(screen.x, kOriginalHeight - screen.y, 0.9, _cubeModelViewMatrix, _cubeProjectionMatrix, (GLint *)_cubeViewport, &x, &y, &z); // 3D coords to polar coords Math::Vector3d v = Math::Vector3d(x, y, z); v.normalize(); Math::Vector2d horizontalProjection = Math::Vector2d(v.x(), v.z()); horizontalProjection.normalize(); pitch = 90 - Math::Angle::arcCosine(v.y()).getDegrees(); heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees(); if (horizontalProjection.getX() > 0.0) heading = 360 - heading; }
void Lua_V1::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->getCurrSet()->getSectorCount(); for (int i = 0; i < numSectors; i++) { Sector *sector = g_grim->getCurrSet()->getSectorBase(i); if (strmatch(sector->getName(), name)) { if (sector->getNumVertices() != 4) warning("GetSectorOppositeEdge(): cheat box with %d (!= 4) edges!", sector->getNumVertices()); Math::Vector3d* vertices = sector->getVertices(); Sector::ExitInfo e; sector->getExitInfo(actor->getPos(), -actor->getPuckVector(), &e); float frac = (e.exitPoint - vertices[e.edgeVertex + 1]).getMagnitude() / e.edgeDir.getMagnitude(); e.edgeVertex -= 2; if (e.edgeVertex < 0) e.edgeVertex += sector->getNumVertices(); Math::Vector3d edge = vertices[e.edgeVertex + 1] - vertices[e.edgeVertex]; Math::Vector3d p = vertices[e.edgeVertex] + edge * frac; lua_pushnumber(p.x()); lua_pushnumber(p.y()); lua_pushnumber(p.z()); return; } } lua_pushnil(); }
void Lua_V2::GetActorPuckVector() { lua_Object actorObj = lua_getparam(1); lua_Object addObj = lua_getparam(2); if (!lua_isuserdata(actorObj) || lua_tag(actorObj) != MKTAG('A','C','T','R')) { lua_pushnil(); return; } Actor *actor = getactor(actorObj); if (!actor) { lua_pushnil(); return; } Math::Vector3d result = actor->getPuckVector(); if (!lua_isnil(addObj)) result += actor->getPos(); lua_pushnumber(result.x()); lua_pushnumber(result.y()); lua_pushnumber(result.z()); }
/** * Generates a lookat matrix. For reference, see * http://clb.demon.fi/MathGeoLib/docs/float3x3_LookAt.php */ void Matrix<3, 3>::buildFromTargetDir(const Math::Vector3d &modelForward, const Math::Vector3d &targetDirection, const Math::Vector3d &modelUp, const Math::Vector3d &worldUp) { Math::Vector3d modelRight = Math::Vector3d::crossProduct(modelUp, modelForward); modelRight.normalize(); Math::Vector3d worldRight = Math::Vector3d::crossProduct(worldUp, targetDirection); worldRight.normalize(); Math::Vector3d perpWorldUp = Math::Vector3d::crossProduct(targetDirection, worldRight); perpWorldUp.normalize(); Math::Matrix3 m1; m1.getRow(0) << worldRight.x() << worldRight.y() << worldRight.z(); m1.getRow(1) << perpWorldUp.x() << perpWorldUp.y() << perpWorldUp.z(); m1.getRow(2) << targetDirection.x() << targetDirection.y() << targetDirection.z(); m1.transpose(); Math::Matrix3 m2; m2.getRow(0) << modelRight.x() << modelRight.y() << modelRight.z(); m2.getRow(1) << modelUp.x() << modelUp.y() << modelUp.z(); m2.getRow(2) << modelForward.x() << modelForward.y() << modelForward.z(); this->operator=(m1 * m2); }
void SaveGame::writeVector3d(const Math::Vector3d &vec) { writeFloat(vec.x()); writeFloat(vec.y()); writeFloat(vec.z()); }
void AnimationEmi::animate(Skeleton *skel, float delta) { _time += delta; if (_time > _duration) { _time = _duration; } for (int bone = 0; bone < _numBones; ++bone) { Bone &curBone = _bones[bone]; if (!curBone._target) curBone._target = skel->getJointNamed(curBone._boneName); Math::Matrix4 &relFinal = curBone._target->_finalMatrix; Math::Quaternion &quatFinal = curBone._target->_finalQuat; if (curBone._rotations) { int keyfIdx = 0; Math::Quaternion quat; Math::Vector3d relPos = relFinal.getPosition(); for (int curKeyFrame = 0; curKeyFrame < curBone._count; curKeyFrame++) { if (curBone._rotations[curKeyFrame]._time >= _time) { keyfIdx = curKeyFrame; break; } } if (keyfIdx == 0) { quat = curBone._rotations[keyfIdx]._quat; } else if (keyfIdx == curBone._count - 1) { quat = curBone._rotations[keyfIdx - 1]._quat; } else { float timeDelta = curBone._rotations[keyfIdx - 1]._time - curBone._rotations[keyfIdx]._time; float interpVal = (_time - curBone._rotations[keyfIdx]._time) / timeDelta; // Might be the other way around (keyfIdx - 1 slerped against keyfIdx) quat = curBone._rotations[keyfIdx]._quat.slerpQuat(curBone._rotations[keyfIdx - 1]._quat, interpVal); } quat.toMatrix(relFinal); quatFinal = quat; relFinal.setPosition(relPos); } if (curBone._translations) { int keyfIdx = 0; Math::Vector3d vec; for (int curKeyFrame = 0; curKeyFrame < curBone._count; curKeyFrame++) { if (curBone._translations[curKeyFrame]._time >= _time) { keyfIdx = curKeyFrame; break; } } if (keyfIdx == 0) { vec = curBone._translations[keyfIdx]._vec; } else if (keyfIdx == curBone._count - 1) { vec = curBone._translations[keyfIdx - 1]._vec; } else { float timeDelta = curBone._translations[keyfIdx - 1]._time - curBone._translations[keyfIdx]._time; float interpVal = (_time - curBone._translations[keyfIdx]._time) / timeDelta; vec.x() = curBone._translations[keyfIdx - 1]._vec.x() + (curBone._translations[keyfIdx]._vec.x() - curBone._translations[keyfIdx - 1]._vec.x()) * interpVal; vec.y() = curBone._translations[keyfIdx - 1]._vec.y() + (curBone._translations[keyfIdx]._vec.y() - curBone._translations[keyfIdx - 1]._vec.y()) * interpVal; vec.z() = curBone._translations[keyfIdx - 1]._vec.z() + (curBone._translations[keyfIdx]._vec.z() - curBone._translations[keyfIdx - 1]._vec.z()) * interpVal; } relFinal.setPosition(vec); } } }
void ResourceSerializer::syncAsVector3d(Math::Vector3d &value) { syncAsFloat(value.x()); syncAsFloat(value.y()); syncAsFloat(value.z()); }
//------------------------------------------------------------------------------ void AudioInterface::setSourceVelocity( int iId, math::Vector3d iV ) { ALfloat v[3]; v[0] = iV.x(); v[1] = iV.y(); v[2] = iV.z(); alSourcefv( iId, AL_VELOCITY, v ); }
//------------------------------------------------------------------------------ void AudioInterface::setSourceDirection( int iId, math::Vector3d iV ) { ALfloat d[3]; d[0] = iV.x(); d[1] = iV.y(); d[2] = iV.z(); alSourcefv( iId, AL_DIRECTION, d ); }
void Head::lookAt(bool entering, const Math::Vector3d &point, float rate, const Math::Matrix4 &matrix) { if (_joint1Node) { float step = g_grim->getPerSecond(rate); float yawStep = step; float pitchStep = step / 3.f; if (!entering) { //animate yaw if (_headYaw > yawStep) { _headYaw -= yawStep; } else if (_headYaw < -yawStep) { _headYaw += yawStep; } else { _headYaw = 0; } //animate pitch if (_headPitch > pitchStep) { _headPitch -= pitchStep; } else if (_headPitch < -pitchStep) { _headPitch += pitchStep; } else { _headPitch = 0; } _joint1Node->_animYaw = _headYaw; Math::Angle pi = _headPitch / 3.f; _joint1Node->_animPitch += pi; _joint2Node->_animPitch += pi; _joint3Node->_animPitch += pi; _joint1Node->_animRoll = (_joint1Node->_animYaw.getDegrees() / 20.f) * _headPitch.getDegrees() / -5.f; if (_joint1Node->_animRoll > _maxRoll) _joint1Node->_animRoll = _maxRoll; if (_joint1Node->_animRoll < -_maxRoll) _joint1Node->_animRoll = -_maxRoll; return; } ModelNode *p = _joint3Node; while (p->_parent) { p = p->_parent; } p->setMatrix(matrix); p->update(); Math::Vector3d v = point - _joint3Node->_matrix.getPosition(); if (v.isZero()) { return; } float magnitude = sqrt(v.x() * v.x() + v.y() * v.y()); float a = v.x() / magnitude; float b = v.y() / magnitude; float yaw; yaw = acos(a) * (180.0f / LOCAL_PI); if (b < 0.0f) yaw = 360.0f - yaw; Math::Angle bodyYaw = matrix.getYaw(); p = _joint1Node->_parent; while (p) { bodyYaw += p->_yaw + p->_animYaw; p = p->_parent; } _joint1Node->_animYaw = (- 90 + yaw - bodyYaw); if (_joint1Node->_animYaw < -180.) { _joint1Node->_animYaw += 360; } if (_joint1Node->_animYaw > 180.) { _joint1Node->_animYaw -= 360; } if (_joint1Node->_animYaw > _maxYaw) _joint1Node->_animYaw = _maxYaw; if (_joint1Node->_animYaw < -_maxYaw) _joint1Node->_animYaw = -_maxYaw; float sqLenght = v.x() * v.x() + v.y() * v.y(); float h; if (sqLenght > 0) { h = sqrt(sqLenght); } else { h = -sqrt(sqLenght); } magnitude = sqrt(v.z() * v.z() + h * h); a = h / magnitude; b = v.z() / magnitude; Math::Angle pitch; pitch = acos(a) * (180.0f / LOCAL_PI); if (b < 0.0f) pitch = 360.0f - pitch; if (pitch > 180) pitch -= 360; if (pitch > _maxPitch) pitch = _maxPitch; if (pitch < -_maxPitch) pitch = -_maxPitch; if ((_joint1Node->_animYaw > 0 && pitch < 0) || (_joint1Node->_animYaw < 0 && pitch > 0)) { pitch += _joint1Node->_animYaw / 10.f; } else { pitch -= _joint1Node->_animYaw / 10.f; } //animate pitch if (pitch - _headPitch > pitchStep) pitch = _headPitch + pitchStep; if (_headPitch - pitch > pitchStep) pitch = _headPitch - pitchStep; Math::Angle pi = pitch / 3.f; _joint1Node->_animPitch += pi; _joint2Node->_animPitch += pi; _joint3Node->_animPitch += pi; //animate yaw if (_joint1Node->_animYaw - _headYaw > yawStep) _joint1Node->_animYaw = _headYaw + yawStep; if (_headYaw - _joint1Node->_animYaw > yawStep) _joint1Node->_animYaw = _headYaw - yawStep; _joint1Node->_animRoll = (_joint1Node->_animYaw.getDegrees() / 20.f) * pitch.getDegrees() / -5.f; if (_joint1Node->_animRoll > _maxRoll) _joint1Node->_animRoll = _maxRoll; if (_joint1Node->_animRoll < -_maxRoll) _joint1Node->_animRoll = -_maxRoll; _headPitch = pitch; _headYaw = _joint1Node->_animYaw; } }
void GfxOpenGL::drawModel(Model *m) { glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)_screenWidth/(GLfloat)_screenHeight,0.01f,10.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor4ub(255, 255, 255, 255); gluLookAt( 0, 0, 1, 0, 0, 0, 0, 1, 0 ); glPushMatrix(); glTranslatef((_cameraX/(float)_screenWidth), -(_cameraY/(float)_screenHeight), (_cameraZ/(float)_screenHeight)); glRotatef(_rotY, 1, 0, 0); glRotatef(_rotX, 0, 1, 0); for (uint j = 0; j < m->_numPolygons; j++) { Polygon *p = &m->_polygons[j]; glBegin(GL_POLYGON); for (int i = 0; i < m->_polygons->_num; ++i) { uint32 vert = p->_data[i]; if (vert > m->_numVerticies || vert == 0) { break; } glColor4ub(_palette->_palette[p->_colour]._r, _palette->_palette[p->_colour]._g, _palette->_palette[p->_colour]._b, 255); Vertex *v = &m->_verticies[vert]; if (v->_bone == 0) { continue; } Math::Vector3d mv = v->getPos(m); Normal *n = &m->_normals[vert]; glNormal3f(n->_x, n->_y, n->_z); glVertex3fv(mv.getData()); } glEnd(); } for (uint j = 0; j < m->_numPoints; j++) { Point *p = &m->_points[j]; glColor4ub(_palette->_palette[p->_colour]._r, _palette->_palette[p->_colour]._g, _palette->_palette[p->_colour]._b, 255); Vertex *v1 = &m->_verticies[p->_v1]; Math::Vector3d vec1 = v1->getPos(m); Vertex *v2 = &m->_verticies[p->_v2]; Math::Vector3d vec2 = v2->getPos(m); glBegin(GL_LINES); glVertex3fv(vec1.getData()); glVertex3fv(vec2.getData()); glEnd(); } for (uint j = 0; j < m->_numSpheres; j++) { Sphere *s = &m->_spheres[j]; Vertex *v = &m->_verticies[s->_vertex]; Math::Vector3d vec = v->getPos(m); glColor4ub(_palette->_palette[s->_colour]._r, _palette->_palette[s->_colour]._g, _palette->_palette[s->_colour]._b, 255); glPushMatrix(); glTranslatef(vec.x(), vec.y(), vec.z()); drawSphere(s->_size, 8, 8); glPopMatrix(); } glPopMatrix(); glDisable(GL_DEPTH_TEST); }
bool Actor::handleCollisionWith(Actor *actor, CollisionMode mode, Math::Vector3d *vec) const { if (actor->_collisionMode == CollisionOff) { return false; } Model *model1 = getCurrentCostume()->getModel(); Model *model2 = actor->getCurrentCostume()->getModel(); Math::Vector3d p1 = _pos + model1->_insertOffset; Math::Vector3d p2 = actor->_pos + model2->_insertOffset; float size1 = model1->_radius * _collisionScale; float size2 = model2->_radius * actor->_collisionScale; CollisionMode mode1 = mode; CollisionMode mode2 = actor->_collisionMode; if (mode1 == CollisionSphere && mode2 == CollisionSphere) { Math::Vector3d pos = p1 + *vec; float distance = (pos - p2).getMagnitude(); if (distance < size1 + size2) { // Move the destination point so that its distance from the // center of the circle is size1+size2. Math::Vector3d v = pos - p2; v.normalize(); v *= size1 + size2; *vec = v + p2 - p1; collisionHandlerCallback(actor); return true; } } else if (mode1 == CollisionBox && mode2 == CollisionBox) { warning("Collision between box and box not implemented!"); return false; } else { Math::Rect2d rect; Math::Vector3d bboxPos; Math::Vector3d size; float scale; Math::Vector3d pos; Math::Vector3d circlePos; Math::Angle yaw; Math::Vector2d circle; float radius; if (mode1 == CollisionBox) { pos = p1 + *vec; bboxPos = pos + model1->_bboxPos; size = model1->_bboxSize; scale = _collisionScale; yaw = _yaw; circle.setX(p2.x()); circle.setY(p2.y()); circlePos = p2; radius = size2; } else { pos = p2; bboxPos = p2 + model2->_bboxPos; size = model2->_bboxSize; scale = actor->_collisionScale; yaw = actor->_yaw; circle.setX(p1.x() + vec->x()); circle.setY(p1.y() + vec->y()); circlePos = p1; radius = size1; } rect._topLeft = Math::Vector2d(bboxPos.x(), bboxPos.y() + size.y()); rect._topRight = Math::Vector2d(bboxPos.x() + size.x(), bboxPos.y() + size.y()); rect._bottomLeft = Math::Vector2d(bboxPos.x(), bboxPos.y()); rect._bottomRight = Math::Vector2d(bboxPos.x() + size.x(), bboxPos.y()); rect.scale(scale); rect.rotateAround(Math::Vector2d(pos.x(), pos.y()), yaw); if (rect.intersectsCircle(circle, radius)) { Math::Vector2d center = rect.getCenter(); // Draw a line from the center of the rect to the place the character // would go to. Math::Vector2d v = circle - center; v.normalize(); Math::Segment2d edge; // That line intersects (usually) an edge rect.getIntersection(center, v, &edge); // Take the perpendicular of that edge Math::Line2d perpendicular = edge.getPerpendicular(circle); Math::Vector3d point; Math::Vector2d p; // If that perpendicular intersects the edge if (edge.intersectsLine(perpendicular, &p)) { Math::Vector2d direction = perpendicular.getDirection(); direction.normalize(); // Move from the intersection until we are at a safe distance Math::Vector2d point1(p - direction * radius); Math::Vector2d point2(p + direction * radius); if (center.getDistanceTo(point1) < center.getDistanceTo(point2)) { point = point2.toVector3d(); } else { point = point1.toVector3d(); } } else { //if not we're around a corner // Find the nearest vertex of the rect Math::Vector2d vertex = rect.getTopLeft(); float distance = vertex.getDistanceTo(circle); Math::Vector2d other = rect.getTopRight(); float otherDist = other.getDistanceTo(circle); if (otherDist < distance) { distance = otherDist; vertex = other; } other = rect.getBottomLeft(); otherDist = other.getDistanceTo(circle); if (otherDist < distance) { distance = otherDist; vertex = other; } other = rect.getBottomRight(); if (other.getDistanceTo(circle) < distance) { vertex = other; } // and move on a circle around it Math::Vector2d dst = circle - vertex; dst.normalize(); dst = dst * radius; point = (vertex + dst).toVector3d(); } float z = vec->z(); *vec = point - circlePos; vec->z() = z; collisionHandlerCallback(actor); return true; } } return false; }