Beispiel #1
0
        public void update(float absoluteTimeS)
        {
            float periodicT   = absoluteTimeS + _periodicTOffset;
            var   laserParams = _laser.parameters;

            // update variables
            _interferenceOffset = laserParams.middleInterferenceUFunc(periodicT);
            _periodicIntensity  = laserParams.intensityPeriodicFunction(periodicT);
            _periodicIntensity *= laserParams.intensityModulation(periodicT);

            // evaluate start position for this update
            Vector3 beamOriginLocal = Vector3.Zero;

            if (_laser.beamOriginPresets != null && _laser.beamOriginPresets.Count > 1)
            {
                var presetIdx = _beamId;
                if (presetIdx >= _laser.beamOriginPresets.Count)
                {
                    presetIdx %= _laser.beamOriginPresets.Count;
                }
                beamOriginLocal = _laser.beamOriginPresets [presetIdx];
            }
            _beamStartWorld = _laser.txfmSourceToWorld(beamOriginLocal);
            _beamEndWorld   = _laser.txfmTargetToWorld(Vector3.Zero);
            Vector3 beamDirWorld = (_beamEndWorld - _beamStartWorld).Normalized();
            Vector3 laserXaxisWorld, laserYaxisWorld;

            OpenTKHelper.TwoPerpAxes(beamDirWorld, out laserXaxisWorld, out laserYaxisWorld);
            // local placement to start start placement in world coordinates
            Vector3 localPlacement            = laserParams.getBeamPlacementVector(_beamId, laserParams.numBeams, absoluteTimeS);
            Vector3 startPlacement            = localPlacement * laserParams.beamStartPlacementScale;
            Vector3 startPlacementWorldOffset =
                laserXaxisWorld * startPlacement.X + laserYaxisWorld * startPlacement.Y + beamDirWorld * startPlacement.Z;

            _beamStartWorld += startPlacementWorldOffset;

            // end position in world coordinates including drift; before intersection test
            float   driftX              = laserParams.driftXFunc(periodicT);
            float   driftY              = laserParams.driftYFunc(periodicT);
            var     driftMod            = laserParams.driftModulationFunc(periodicT);
            Vector3 driftedEndPlacement = laserParams.beamDestSpread * localPlacement
                                          + new Vector3(driftX, driftY, 0f) * driftMod;
            Vector3 endPlacementWorldOffset =
                laserXaxisWorld * driftedEndPlacement.X + laserYaxisWorld * driftedEndPlacement.Y + beamDirWorld * driftedEndPlacement.Z;

            _beamEndWorld += endPlacementWorldOffset;

            _hitsAnObstacle = false;
            // intersects with any of the intersecting objects
            if (_laser.beamObstacles != null)
            {
                //if (false) {
                // TODO note the code below is slow. Wen you start having many lasers
                // this will cause problems. Consider using BVH for ray tests or analyzing
                // intersection math.
                float closestDistance = float.PositiveInfinity;
                foreach (var obj in _laser.beamObstacles)
                {
                    float distanceToInterect;
                    var   ray = new SSRay(_beamStartWorld, (_beamEndWorld - _beamStartWorld).Normalized());
                    if (obj.Intersect(ref ray, out distanceToInterect))
                    {
                        if (distanceToInterect < closestDistance)
                        {
                            closestDistance = distanceToInterect;
                            _hitsAnObstacle = true;
                            _beamEndWorld   = _beamStartWorld + ray.dir * closestDistance;
                        }
                    }
                }
            }
        }
Beispiel #2
0
        public static void SimpleShadowmapProjection(
            List <SSObject> objects,
            SSLight light,
            FrustumCuller frustum, // can be null (disabled)
            SSCamera camera,
            out float width, out float height, out float nearZ, out float farZ,
            out Vector3 viewEye, out Vector3 viewTarget, out Vector3 viewUp)
        {
            if (light.Type != SSLight.LightType.Directional)
            {
                throw new NotSupportedException();
            }

            // light-aligned unit vectors
            Vector3 lightZ = light.Direction.Normalized();
            Vector3 lightX, lightY;

            OpenTKHelper.TwoPerpAxes(lightZ, out lightX, out lightY);

            // Step 1: light-direction aligned AABB of the visible objects
            Vector3 projBBMin = new Vector3(float.PositiveInfinity);
            Vector3 projBBMax = new Vector3(float.NegativeInfinity);

            foreach (var obj in objects)
            {
                if (obj.renderState.toBeDeleted ||
                    !obj.renderState.visible ||
                    !obj.renderState.castsShadow)
                {
                    continue;
                }
                else if (frustum == null || (obj.boundingSphere != null &&
                                             frustum.isSphereInsideFrustum(obj.Pos, obj.ScaledRadius)))
                {
                    // determine AABB in light coordinates of the objects so far
                    Vector3 lightAlignedPos = OpenTKHelper.ProjectCoord(obj.Pos, lightX, lightY, lightZ);
                    Vector3 rad             = new Vector3(obj.ScaledRadius);
                    Vector3 localMin        = lightAlignedPos - rad;
                    Vector3 localMax        = lightAlignedPos + rad;
                    projBBMin = Vector3.ComponentMin(projBBMin, localMin);
                    projBBMax = Vector3.ComponentMax(projBBMax, localMax);
                }
            }

            if (frustum != null)
            {
                // then we need to do a second pass, including shadow-casters that
                // are between the camera-frusum and the light

                // compute the camera's position in lightspace, because we need to
                // include everything "closer" that the midline of the camera frustum
                Vector3 lightAlignedCameraPos = OpenTKHelper.ProjectCoord(camera.Pos, lightX, lightY, lightZ);
                float   minZTest = lightAlignedCameraPos.Z;

                // TODO what happens if all objects are exluded?

                // Step 2: Extend Z of AABB to cover objects "between" current AABB and the light
                foreach (var obj in objects)
                {
                    if (obj.renderState.toBeDeleted ||
                        !obj.renderState.visible ||
                        !obj.renderState.castsShadow)
                    {
                        continue;
                    }

                    Vector3 lightAlignedPos = OpenTKHelper.ProjectCoord(obj.Pos, lightX, lightY, lightZ);
                    Vector3 rad             = new Vector3(obj.ScaledRadius);
                    Vector3 localMin        = lightAlignedPos - rad;
                    Vector3 localMax        = lightAlignedPos + rad;

                    if (OpenTKHelper.RectsOverlap(projBBMin.Xy, projBBMax.Xy, localMin.Xy, localMax.Xy) &&
                        localMin.Z < minZTest)
                    {
                        projBBMin = Vector3.ComponentMin(projBBMin, localMin);
                        projBBMax = Vector3.ComponentMax(projBBMax, localMax);
                    }
                }
            }
            // Finish the projection matrix

            // Use center of AABB in regular coordinates to get the view matrix
            Vector3 centerAligned = (projBBMin + projBBMax) / 2f;

            viewTarget = centerAligned.X * lightX
                         + centerAligned.Y * lightY
                         + centerAligned.Z * lightZ;
            float farEnough = (centerAligned.Z - projBBMin.Z) + 1f;

            viewEye = viewTarget - farEnough * lightZ;
            viewUp  = lightY;

            width  = projBBMax.X - projBBMin.X;
            height = projBBMax.Y - projBBMin.Y;
            nearZ  = 1f;
            farZ   = 1f + (projBBMax.Z - projBBMin.Z);
        }