Command *Command::opItemLookDirection(Script *script, const ResourceReference &itemRef, int32 direction, bool suspend) { FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>(); Current *current = StarkGlobal->getCurrent(); Camera *camera = current->getCamera(); Math::Angle cameraAngle = camera->getHorizontalAngle(); Math::Angle targetAngle = direction + cameraAngle; Math::Matrix3 rot; rot.buildAroundZ(-targetAngle); Math::Vector3d directionVector(1.0, 0.0, 0.0); rot.transformVector(&directionVector); Turn *movement = new Turn(item); movement->setTargetDirection(directionVector); movement->start(); item->setMovement(movement); if (suspend) { script->suspend(item); item->setMovementSuspendedScript(script); return this; // Stay on the same command while suspended } else { return nextCommand(); } }
/* RotateVector takes a vector and rotates it around * the point (0,0,0) by the requested number of degrees. * This function is used to calculate the locations for * getting on and off of the Bone Wagon and for going up * and down the slide with the chain at the end of the world. */ void Lua_V1::RotateVector() { lua_Object vecObj = lua_getparam(1); lua_Object rotObj = lua_getparam(2); if (!lua_istable(vecObj) || !lua_istable(rotObj)) { lua_pushnil(); return; } lua_pushobject(vecObj); lua_pushstring("x"); float x = lua_getnumber(lua_gettable()); lua_pushobject(vecObj); lua_pushstring("y"); float y = lua_getnumber(lua_gettable()); lua_pushobject(vecObj); lua_pushstring("z"); float z = lua_getnumber(lua_gettable()); Math::Vector3d vec(x, y, z); lua_pushobject(rotObj); lua_pushstring("x"); Math::Angle pitch = lua_getnumber(lua_gettable()); lua_pushobject(rotObj); lua_pushstring("y"); Math::Angle yaw = lua_getnumber(lua_gettable()); lua_pushobject(rotObj); lua_pushstring("z"); Math::Angle roll = lua_getnumber(lua_gettable()); Math::Matrix3 mat; mat.buildFromPitchYawRoll(pitch, yaw, roll); mat.transformVector(&vec); lua_Object resObj = lua_createtable(); lua_pushobject(resObj); lua_pushstring("x"); lua_pushnumber(vec.x()); lua_settable(); lua_pushobject(resObj); lua_pushstring("y"); lua_pushnumber(vec.y()); lua_settable(); lua_pushobject(resObj); lua_pushstring("z"); lua_pushnumber(vec.z()); lua_settable(); lua_pushobject(resObj); }
Math::Transform Camera::getViewMatrix () { Math::Transform view; Vector3 at (m_camera.getBack ().x + m_camera.getPosition ().x, m_camera.getBack ().y + m_camera.getPosition ().y, m_camera.getBack ().z + m_camera.getPosition ().z); Vector3 eye (m_camera.getPosition ()); Vector3 up (m_camera.getUp ()); Vector3 back = eye - at; back.normalize (); Vector3 right = up.cross(back); right.normalize (); eye.negate (); Math::Matrix3 rotScale (right, up, back); rotScale.transpose (); view.setOrientation (rotScale); Vector3 translation = rotScale * eye; //Vector3 translation = -eye; view.setPosition (translation); return view; }
void Walk::onGameLoop() { if (!_path->hasSteps()) { // There is no path to the destination stop(); return; } Resources::Floor *floor = StarkGlobal->getCurrent()->getFloor(); // Get the target to walk to Math::Vector3d currentPosition = _item3D->getPosition3D(); Math::Vector3d target = _path->computeWalkTarget(currentPosition); // Compute the direction to walk into Math::Vector3d direction = target - currentPosition; direction.z() = 0; direction.normalize(); // Compute the angle with the current character direction Math::Vector3d currentDirection = _item3D->getDirectionVector(); float directionDeltaAngle = computeAngleBetweenVectorsXYPlane(currentDirection, direction); // If the angle between the current direction and the new one is too high, // make the character turn on itself until the angle is low enough if (ABS(directionDeltaAngle) > getAngularSpeed() + 0.1f) { _turnDirection = directionDeltaAngle < 0 ? kTurnLeft : kTurnRight; } else { _turnDirection = kTurnNone; } float distancePerGameloop = computeDistancePerGameLoop(); Math::Vector3d newPosition; if (_turnDirection == kTurnNone) { // Compute the new position using the distance per gameloop if (currentPosition.getDistanceTo(target) > distancePerGameloop) { newPosition = currentPosition + direction * distancePerGameloop; } else { newPosition = target; } } else { // The character does not change position when it is turning newPosition = currentPosition; direction = currentDirection; Math::Matrix3 rot; rot.buildAroundZ(_turnDirection == kTurnLeft ? -getAngularSpeed() : getAngularSpeed()); rot.transformVector(&direction); } // Some scripts expect the character position to be the exact destination if (newPosition == _destination) { _reachedDestination = true; stop(); } // Update the new position's height according to the floor int32 newFloorFaceIndex = floor->findFaceContainingPoint(newPosition); if (newFloorFaceIndex >= 0) { floor->computePointHeightInFace(newPosition, newFloorFaceIndex); } else { warning("Item %s is walking off the floor", _item->getName().c_str()); } // Update the item's properties _item3D->setPosition3D(newPosition); if (direction.getMagnitude() != 0.0) { _item3D->setDirection(computeAngleBetweenVectorsXYPlane(direction, Math::Vector3d(1.0, 0.0, 0.0))); } if (newFloorFaceIndex >= 0) { // When unable to find the face containing the new position, keep the previous one // to prevent draw order glitches. _item3D->setFloorFaceIndex(newFloorFaceIndex); } changeItemAnim(); }
void PolyhedronColliderGeometry::UpdateMassAndLocalCentroid(const ResolutionMaterial &material, float &mass, Math::Matrix3 &unitInertiaTensor, Math::Vector3 &localCentroid) { auto &verts = mAdjacency.Verts(); auto &edges = mAdjacency.Edges(); auto &faces = mAdjacency.Faces(); const Math::Vector3 &c = mAdjacency.Centroid(); mass = 0.0f; unitInertiaTensor.ZeroOut(); localCentroid.ZeroOut(); float totalVolume = 0.0f; for (auto &face : faces) { if (!face.active) continue; // grab face verts int e = face.edge; const Math::Vector3 &v0 = verts[edges[e].vert].position; e = edges[e].next; const Math::Vector3 &v1 = verts[edges[e].vert].position; e = edges[e].next; const Math::Vector3 &v2 = verts[edges[e].vert].position; // volume of tetrahedron formed by face & centroid (not divided by 6) const float tetrahedronVolume = std::fabs((v0 - c).Dot((v1 - c).Cross(v2 - c))); // accumulate volume totalVolume += tetrahedronVolume; // accumulate weighted centroid const Math::Vector3 tetrahedronCentroid = 0.25f * (c + v0 + v1 + v2); localCentroid += tetrahedronVolume * tetrahedronCentroid; } if (totalVolume == 0) totalVolume = 1; localCentroid /= totalVolume; //mass = material.mDensity * totalVolume / 6.0f; mass = mParent->Parent().mParent->cphy->mMass * totalVolume / 6.0f; // compute inertia tensor for (auto &face : faces) { if (!face.active) continue; // grab face verts int e = face.edge; const Math::Vector3 &v0 = verts[edges[e].vert].position; e = edges[e].next; const Math::Vector3 &v1 = verts[edges[e].vert].position; e = edges[e].next; const Math::Vector3 &v2 = verts[edges[e].vert].position; // accumulate inertia tensor unitInertiaTensor += UnitInertiaTensorTetrahedron(c, v0, v1, v2, localCentroid); } }