void PhysicsFrameSplineEditor::addControlPoint() { if (m_spline.control.size() == 0) { m_spline.append(CFrame()); } else if (m_spline.control.size() == 1) { // Adding the 2nd point CFrame f = m_spline.control.last(); f.translation += f.lookVector(); m_spline.append(f); resizeControlPointDropDown(m_spline.control.size()); // Select the new point setSelectedControlPointIndex(m_selectedControlPointIndex + 1); } else { // Adding between two points float t0 = m_spline.time[m_selectedControlPointIndex]; float newT = t0; float evalT = 0; if (m_selectedControlPointIndex < m_spline.control.size() - 1) { // Normal interval newT = m_spline.time[m_selectedControlPointIndex + 1]; evalT = (t0 + newT) / 2; } else if (m_spline.extrapolationMode == SplineExtrapolationMode::CYCLIC) { // After the end on a cyclic spline newT = m_spline.getFinalInterval() + t0; evalT = (t0 + newT) / 2; } else { // After the end on a non-cyclic spline of length at least // 2; assume that we want to step the distance of the previous // interval newT = evalT = 2.0f * t0 - m_spline.time[m_selectedControlPointIndex - 1]; } const PhysicsFrame f = m_spline.evaluate(evalT); m_spline.control.insert(m_selectedControlPointIndex + 1, f); m_spline.time.insert(m_selectedControlPointIndex + 1, newT); // Select the new point resizeControlPointDropDown(m_spline.control.size()); setSelectedControlPointIndex(m_selectedControlPointIndex + 1); // Fix the rest of the times to be offset by the inserted duration float shift = newT - t0; for (int i = m_selectedControlPointIndex + 1; i < m_spline.time.size(); ++i) { m_spline.time[i] += shift; } } }
void AudioDevice::simulate (const float dt, const float timeScaleAtListener, const CFrame& wsListenerFrame, const Vector3& wsListenerVelocity) { m_listenerPosition = wsListenerFrame.translation; if (m_engine) { m_engine->setListenerPosition (g3dToirrKlang(wsListenerFrame.translation), g3dToirrKlang(wsListenerFrame.lookVector()), g3dToirrKlang(wsListenerVelocity), g3dToirrKlang(wsListenerFrame.upVector())); } m_timeScaleAtListener = timeScaleAtListener; if (m_music) { m_music->setPlaybackSpeed(speedAdjust(timeScaleAtListener)); if (m_music->isFinished()) { m_music->drop(); m_music = NULL; } } // Update already-playing 3D sounds for (int s = 0; s < m_active3D.size(); ++s) { ISound* sound = m_active3D[s]; if (sound->isFinished()) { // End m_active3D.fastRemove(s); --s; } else { sound->setPosition(sound->getPosition() + dt * sound->getVelocity()); } } }
void ShadowMap::computeMatrices (const shared_ptr<Light>& light, AABox sceneBounds, CFrame& lightFrame, Projection& lightProjection, Matrix4& lightProjectionMatrix, float lightProjX, float lightProjY, float lightProjNearMin, float lightProjFarMax, float intensityCutoff) { if (! sceneBounds.isFinite() || sceneBounds.isEmpty()) { // Produce some reasonable bounds sceneBounds = AABox(Point3(-20, -20, -20), Point3(20, 20, 20)); } lightFrame = light->frame(); if (light->type() == Light::Type::DIRECTIONAL) { Point3 center = sceneBounds.center(); if (! center.isFinite()) { center = Point3::zero(); } // Move directional light away from the scene. It must be far enough to see all objects lightFrame.translation = -lightFrame.lookVector() * min(1e6f, max(sceneBounds.extent().length() / 2.0f, lightProjNearMin, 30.0f)) + center; } const CFrame& f = lightFrame; float lightProjNear = finf(); float lightProjFar = 0.0f; // TODO: for a spot light, only consider objects this light can see // Find nearest and farthest corners of the scene bounding box for (int c = 0; c < 8; ++c) { const Vector3& v = sceneBounds.corner(c); const float distance = -f.pointToObjectSpace(v).z; lightProjNear = min(lightProjNear, distance); lightProjFar = max(lightProjFar, distance); } // Don't let the near get too close to the source, and obey // the specified hint. lightProjNear = max(lightProjNearMin, lightProjNear); // Don't bother tracking shadows past the effective radius lightProjFar = min(light->effectSphere(intensityCutoff).radius, lightProjFar); lightProjFar = max(lightProjNear + 0.1f, min(lightProjFarMax, lightProjFar)); debugAssert(lightProjNear < lightProjFar); if (light->type() != Light::Type::DIRECTIONAL) { // TODO: Square spot // Spot light; we can set the lightProj bounds intelligently alwaysAssertM(light->spotHalfAngle() <= halfPi(), "Spot light with shadow map and greater than 180-degree bounds"); // The cutoff is half the angle of extent (See the Red Book, page 193) const float angle = light->spotHalfAngle(); lightProjX = tan(angle) * lightProjNear; // Symmetric in x and y lightProjY = lightProjX; lightProjectionMatrix = Matrix4::perspectiveProjection (-lightProjX, lightProjX, -lightProjY, lightProjY, lightProjNear, lightProjFar); } else if (light->type() == Light::Type::DIRECTIONAL) { // Directional light // Construct a projection and view matrix for the camera so we can // render the scene from the light's point of view // // Since we're working with a directional light, // we want to make the center of projection for the shadow map // be in the direction of the light but at a finite distance // to preserve z precision. lightProjectionMatrix = Matrix4::orthogonalProjection (-lightProjX, lightProjX, -lightProjY, lightProjY, lightProjNear, lightProjFar); } else { // Omni light. Nothing good can happen here, but at least we // generate something lightProjectionMatrix = Matrix4::perspectiveProjection (-lightProjX, lightProjX, -lightProjY, lightProjY, lightProjNear, lightProjFar); } float fov = atan2(lightProjX, lightProjNear) * 2.0f; lightProjection.setFieldOfView(fov, FOVDirection::HORIZONTAL); lightProjection.setNearPlaneZ(-lightProjNear); lightProjection.setFarPlaneZ(-lightProjFar); }