Esempio n. 1
0
            public void preRenderUpdate(float timeElapsed)
            {
                var mParams = missile.parameters as SSpaceMissileVisualParameters;

                bodyObj.Pos = missile.displayPosition;
                bodyObj.Orient(missile.visualDirection, missile.up);

                bool  ejection       = missile.state == SSpaceMissileVisualData.State.Ejection;
                float smokeFrequency = Interpolate.Lerp(
                    mParams.smokeEmissionFrequencyMin, mParams.smokeEmissionFrequencyMax, missile.visualSmokeAmmount);
                float sizeMin   = ejection ? mParams.ejectionSmokeSizeMin : mParams.flameSmokeSizeMin;
                float sizeMax   = ejection ? mParams.ejectionSmokeSizeMax : mParams.flameSmokeSizeMax;
                float smokeSize = Interpolate.Lerp(sizeMin, sizeMax,
                                                   (float)SSpaceMissilesVisualSimulation.rand.NextDouble());

                //flameSmokeEmitter.velocity = -missile.velocity;
                flameSmokeEmitter.center           = missile.jetPosition();
                flameSmokeEmitter.up               = -missile.visualDirection;
                flameSmokeEmitter.emissionInterval = 1f / smokeFrequency;
                flameSmokeEmitter.componentScale   = new Vector3(smokeSize);
                flameSmokeEmitter.effectorMask     = (ushort)
                                                     (ejection ? ParticleEffectorMasks.EjectionSmoke : ParticleEffectorMasks.FlameToSmoke);
                var vel = missile.velocity.LengthFast;

                flameSmokeEmitter.velocityFromCenterMagnitudeMin = ejection ? -vel / 2f : (-vel / 8f);
                flameSmokeEmitter.velocityFromCenterMagnitudeMax = ejection ? vel / 2f : (vel / 5f);
                flameSmokeEmitter.life = ejection ? mParams.ejectionSmokeDuration : mParams.flameSmokeDuration;

                if (missile.state == SSpaceMissileData.State.FadingOut)
                {
                    float fadeFactor = 1f - (missile.timeSinceLaunch - missile.fadeTime) / mParams.fadeDuration;
                    var   color      = bodyObj.MainColor;
                    color.A                = fadeFactor;
                    bodyObj.MainColor      = color;
                    flameSmokeEmitter.life = flameSmokeEmitter.lifeMax * fadeFactor;
                }

                #if MISSILE_DEBUG
                RectangleF clientRect = OpenTKHelper.GetClientRect();
                var        xy         = OpenTKHelper.WorldToScreen(
                    missile.displayPosition, ref debugRays.viewProjMat, ref clientRect);
                debugCountdown.Pos   = new Vector3(xy.X, xy.Y, 0f);
                debugCountdown.Label = Math.Floor(missile.timeToHit).ToString();
                //debugCountdown.Label = missile.losRate.ToString("G3") + " : " + missile.losRateRate.ToString("G3");

                debugRays.renderState.visible      = mParams.debuggingAid;
                debugCountdown.renderState.visible = mParams.debuggingAid;
                #endif
            }
Esempio n. 2
0
        public void updateSprites(SInstancedSpriteData instanceData, ref RectangleF clientRect,
                                  ref Vector3 cameraPos, ref Matrix4 camera3dView, ref Matrix4 camera3dProj)
        {
            Matrix4 camera3dViewProjMat = camera3dView * camera3dProj;

            if (_sunDiskOccObj != null)
            {
                Matrix4 viewInverted = _sunDiskOccScene.renderConfig.invCameraViewMatrix.Inverted();
                Vector3 viewRight    = Vector3.Transform(Vector3.UnitX, viewInverted).Normalized();
                Vector3 viewUp       = Vector3.Transform(Vector3.UnitY, viewInverted).Normalized();
                _sunDiskOccPos = OpenTKHelper.WorldToScreen(_sunDiskOccObj.Pos, ref camera3dViewProjMat, ref clientRect);
                float bbFullEstimate;
                // note that it is assumed that the sun object is fully symmertircal when it is in view
                if (_sunDiskOccObj.renderState.matchScaleToScreenPixels)
                {
                    _sunDiskScreenSize = 2f * _sunDiskOccObj.Scale.Xy;
                    bbFullEstimate     = (float)Math.PI * _sunDiskOccObj.Scale.X * _sunDiskOccObj.Scale.Y;
                }
                else
                {
                    Vector3 occRightMost   = _sunDiskOccObj.Pos + viewRight * _sunDiskOccObj.Scale.X;
                    Vector3 occTopMost     = _sunDiskOccObj.Pos + viewUp * _sunDiskOccObj.Scale.Y;
                    Vector2 occRightMostPt = OpenTKHelper.WorldToScreen(occRightMost, ref camera3dViewProjMat, ref clientRect);
                    Vector2 occTopMostPt   = OpenTKHelper.WorldToScreen(occTopMost, ref camera3dViewProjMat, ref clientRect);
                    _sunDiskScreenSize = 2f * new Vector2(occRightMostPt.X - _sunDiskOccPos.X, _sunDiskOccPos.Y - occTopMostPt.Y);
                    bbFullEstimate     = (float)Math.PI * (float)_sunDiskScreenSize.X * (float)_sunDiskScreenSize.Y / 4f;
                }
                _sunDiskOccIntensity = Math.Min((float)_sunDiskOccObj.OcclusionQueueryResult / bbFullEstimate, 1f);
            }

            int numElements = _spriteSlotIdxs.Length;

            if (_sunDiskOccIntensity <= 0f)
            {
                // hide all sprites
                for (int i = 0; i < numElements; ++i)
                {
                    instanceData.writePosition(_spriteSlotIdxs [i], new Vector2(float.NaN));  // hide all sprites
                }
            }
            else
            {
                Vector2 compScale = new Vector2(Math.Max(_sunDiskScreenSize.X, _sunDiskScreenSize.Y)
                                                * Math.Min(1.5f, 1f / (1f - _sunDiskOccIntensity)));
                Vector2 center = new Vector2(clientRect.X, clientRect.Y)
                                 + new Vector2(clientRect.Width, clientRect.Height) / 2f;
                Vector2 towardsCenter = center - _sunDiskOccPos;
                var     color4        = _sunDiskOccObj.MainColor;
                color4.A = _sunDiskOccIntensity;
                for (int i = 0; i < numElements; ++i)
                {
                    int writeIdx = _spriteSlotIdxs [i];
                    instanceData.writeComponentScale(writeIdx, compScale);
                    instanceData.writeColor(writeIdx, color4);

                    Vector2 spriteCenter = _sunDiskOccPos + towardsCenter * 2.5f
                                           / (float)numElements * (float)i;
                    instanceData.writePosition(_spriteSlotIdxs[i], spriteCenter);
                }
            }
        }
Esempio n. 3
0
        public void updateSprites(SInstancedSpriteData instanceData, ref RectangleF clientRect,
                                  ref Vector3 cameraPos, ref Matrix4 camera3dView, ref Matrix4 camera3dProj)
        {
            var beam               = _laser.beam(_beamId);
            var ray                = beam.rayWorld();
            var laserParams        = _laser.parameters;
            var beamSrcInViewSpace = Vector3.Transform(beam.startPosWorld, camera3dView);

            bool    hideSprites = true;
            Vector3 intersectPt3d;

            if (beamSrcInViewSpace.Z < 0f)
            {
                Matrix4 cameraViewProjMat3d = camera3dView * camera3dProj;
                // extract a near plane from the camera view projection matrix
                // https://www.opengl.org/discussion_boards/showthread.php/159332-Extract-clip-planes-from-projection-matrix
                SSPlane3d nearPlane = new SSPlane3d()
                {
                    A = cameraViewProjMat3d.M14 + cameraViewProjMat3d.M13,
                    B = cameraViewProjMat3d.M24 + cameraViewProjMat3d.M23,
                    C = cameraViewProjMat3d.M34 + cameraViewProjMat3d.M33,
                    D = cameraViewProjMat3d.M44 + cameraViewProjMat3d.M43
                };

                if (nearPlane.intersects(ref ray, out intersectPt3d))
                {
                    #if false
                    Console.WriteLine("camera at world pos = " + cameraPos);
                    Console.WriteLine("camera in screen pos = " + OpenTKHelper.WorldToScreen(
                                          cameraPos, ref cameraViewProjMat3d, ref clientRect));
                    Console.WriteLine("screen hit at world pos = " + intersectPt3d);
                    #endif

                    float lengthToIntersectionSq =
                        (intersectPt3d - beam.startPosWorld).LengthSquared;
                    float beamLengthSq = beam.lengthSqWorld();
                    if (lengthToIntersectionSq < beamLengthSq)
                    {
                        hideSprites = false;
                        Vector2 drawScreenPos = OpenTKHelper.WorldToScreen(
                            intersectPt3d - ray.dir * 1f, ref cameraViewProjMat3d, ref clientRect);
                        //Console.WriteLine("screen hit at screen pos = " + drawScreenPos);
                        float   intensity = _laser.envelopeIntensity * beam.periodicIntensity;
                        Vector2 drawScale
                            = new Vector2(laserParams.hitFlareSizeMaxPx * (float)Math.Exp(intensity));
                        for (int i = 0; i < _spriteSlotIdxs.Length; ++i)
                        {
                            int writeIdx = _spriteSlotIdxs [i];
                            instanceData.writePosition(writeIdx, drawScreenPos);
                            instanceData.writeComponentScale(writeIdx, drawScale);
                            instanceData.writeOrientationZ(writeIdx, intensity * 2f * (float)Math.PI);
                        }

                        Color4 backgroundColor = laserParams.backgroundColor;
                        backgroundColor.A = intensity;
                        instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.coronaBackground], backgroundColor);

                        Color4 overlayColor = laserParams.overlayColor;
                        //overlayColor.A = intensity / _laser.parameters.intensityEnvelope.sustainLevel;
                        overlayColor.A = Math.Min(intensity * 2f, 1f);
                        instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.coronaOverlay], overlayColor);
                        //System.Console.WriteLine("overlay.alpha == " + overlayColor.A);

                        Color4 ring1Color = laserParams.overlayColor;
                        //ring1Color.A = (float)Math.Pow(intensity, 5.0);
                        ring1Color.A = 0.1f * intensity;
                        instanceData.writeComponentScale(_spriteSlotIdxs[(int)SpriteId.ring1],
                                                         drawScale * (float)Math.Exp(intensity));
                        instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.ring1], ring1Color);
                        //instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.ring1], Color4.LimeGreen);

                        Color4 ring2Color = laserParams.backgroundColor;
                        //ring2Color.A = (float)Math.Pow(intensity, 10.0);
                        ring2Color.A = intensity * 0.1f;
                        instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.ring2], ring2Color);
                        //instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.ring2], Color4.Magenta);
                    }
                }
            }

            if (hideSprites)
            {
                // hide sprites
                for (int i = 0; i < _spriteSlotIdxs.Length; ++i)
                {
                    instanceData.writeComponentScale(_spriteSlotIdxs[i], Vector2.Zero);
                }
            }
            //System.Console.WriteLine("beam id " + _beamId + " hitting screen at xy " + hitPosOnScreen);
        }
        public void updateSprites(SInstancedSpriteData instanceData, ref RectangleF screenClientRect,
                                  ref Vector3 cameraPos, ref Matrix4 camera3dView, ref Matrix4 camera3dProj)
        {
            float occDiskScreenAreaUsed = (float)_occDiskObj.OcclusionQueueryResult;

            if (occDiskScreenAreaUsed <= 0f)
            {
                // hide all sprites
                var nanVec = new Vector2(float.NaN);
                instanceData.writePosition(_backgroundSpriteIdx, nanVec);
                instanceData.writePosition(_overlaySpriteIdx, nanVec);
                return;
            }

            var   laserParams   = _laser.parameters;
            var   beam          = _laser.beam(_beamId);
            float beamIntensity = _laser.envelopeIntensity * beam.periodicIntensity;

            // position sprites at the beam start in screen space
            Matrix4 camera3dViewProjMat = camera3dView * camera3dProj;
            var     beamStartScreen     = OpenTKHelper.WorldToScreen(beam.startPosWorld,
                                                                     ref camera3dViewProjMat, ref screenClientRect);

            instanceData.writePosition(_backgroundSpriteIdx, beamStartScreen);
            instanceData.writePosition(_overlaySpriteIdx, beamStartScreen);

            // compute screen space needed to occupy the area where the start of the middle's crossbeam
            // would be displayed
            Matrix4 viewInverted   = camera3dView.Inverted();
            Vector3 viewRight      = Vector3.Transform(Vector3.UnitX, viewInverted).Normalized();
            Vector3 occRightMost   = _occDiskObj.Pos + viewRight * laserParams.middleBackgroundWidth;
            Vector2 occRightMostPt = OpenTKHelper.WorldToScreen(occRightMost,
                                                                ref camera3dViewProjMat, ref screenClientRect);
            Vector2 occCenterPt = OpenTKHelper.WorldToScreen(_occDiskObj.Pos,
                                                             ref camera3dViewProjMat, ref screenClientRect);
            float crossBeamRadiusScreenPx = Math.Abs(occRightMostPt.X - occCenterPt.X);

            // write sprite size big enough to cover up the starting section of the cross beam (middle)
            float scale = Math.Max(laserParams.emissionFlareScreenSizeMin, crossBeamRadiusScreenPx * 2.5f)
                          * beamIntensity;

            instanceData.writeMasterScale(_backgroundSpriteIdx, scale * 1.2f);
            instanceData.writeMasterScale(_overlaySpriteIdx, scale * 1f);

            // add some variety to orientation to make the sprites look less static
            instanceData.writeOrientationZ(_backgroundSpriteIdx, beamIntensity * 1f * (float)Math.PI);
            instanceData.writeOrientationZ(_overlaySpriteIdx, beamIntensity * 1f * (float)Math.PI);

            // color intensity: depends on the dot product between to-camera vector and beam direction;
            // also depends on how of the occlusion disk area is visible
            float maxScreenArea = (float)Math.PI
                                  * laserParams.emissionOccDiskRadiusPx * laserParams.emissionOccDiskRadiusPx;
            float occDiskAreaRatio = occDiskScreenAreaUsed / maxScreenArea;
            //System.Console.WriteLine("occDiskAreaRatio = " + occDiskAreaRatio);

            Vector3 toCamera = (cameraPos - beam.startPosWorld).Normalized();
            float   dot      = Math.Max(0f, Vector3.Dot(toCamera, beam.directionWorld()));
            //System.Console.WriteLine("dot = " + dot);

            var alpha = occDiskAreaRatio * 1.2f * (float)Math.Pow(beamIntensity, 0.1) * (float)Math.Pow(dot, 0.1);

            alpha = Math.Min(alpha, 1f);

            // finish background color
            var backgroundColor = laserParams.backgroundColor;

            backgroundColor.A = alpha;
            instanceData.writeColor(_backgroundSpriteIdx, backgroundColor);

            // finish overlay color
            var overlayColor = laserParams.overlayColor;

            overlayColor.A = alpha;
            instanceData.writeColor(_overlaySpriteIdx, overlayColor);
        }
Esempio n. 5
0
            public void preRenderUpdate(float timeElapsed)
            {
                bool visible = (targetObj != null);

                _outline.renderState.visible    = visible;
                _labelBelow.renderState.visible = visible;
                _labelAbove.renderState.visible = visible;
                if (!visible)
                {
                    return;
                }

                RectangleF clientRect     = OpenTKHelper.GetClientRect();
                var        targetRc       = _targetObj3dScene.renderConfig;
                Matrix4    targetViewProj = targetRc.invCameraViewMatrix * targetRc.projectionMatrix;

                // outline
                Quaternion viewRotOnly     = targetRc.invCameraViewMatrix.ExtractRotation();
                Quaternion viewRotInverted = viewRotOnly.Inverted();
                Vector3    viewRight       = Vector3.Transform(Vector3.UnitX, viewRotInverted).Normalized();
                Vector3    viewUp          = Vector3.Transform(Vector3.UnitY, viewRotInverted).Normalized();
                Vector2    targetScreenPos = OpenTKHelper.WorldToScreen(targetObj.Pos, ref targetViewProj, ref clientRect);

                targetScreenPos.X = (float)Math.Round(targetScreenPos.X); // fixes off-by-one pixel jitter
                targetScreenPos.Y = (float)Math.Round(targetScreenPos.Y);

                // animate outline line stipple
                _outline.enableLineStipple = this.isSelected;
                if (_outline.enableLineStipple)
                {
                    ushort stipplePattern = _outline.lineStipplePattern;
                    _stippleTimeAccumulator += timeElapsed;
                    while (_stippleTimeAccumulator >= stippleStepInterval)
                    {
                        ushort firstBit = (ushort)((uint)stipplePattern & 0x1);
                        stipplePattern >>= 1;
                        stipplePattern  |= (ushort)((uint)firstBit << 15);
                        _outline.lineStipplePattern = stipplePattern;

                        _stippleTimeAccumulator -= stippleStepInterval;
                    }
                }

                float outlineHalfWidth;
                float outlineHalfHeight;

                if (fixedSizeTargets)
                {
                    outlineHalfWidth  = outlineMinPixelSz;
                    outlineHalfHeight = outlineMinPixelSz;
                }
                else
                {
                    // assumes target is a convential SSObject without billboarding, match scale to screen, etc.
                    var     size              = targetObj.worldBoundingSphereRadius;
                    Vector3 targetRightMost   = targetObj.Pos + viewRight * size;
                    Vector3 targetTopMost     = targetObj.Pos + viewUp * size;
                    Vector2 screenRightMostPt = OpenTKHelper.WorldToScreen(targetRightMost, ref targetViewProj, ref clientRect);
                    Vector2 screenTopMostPt   = OpenTKHelper.WorldToScreen(targetTopMost, ref targetViewProj, ref clientRect);
                    outlineHalfWidth  = 2f * (screenRightMostPt.X - targetScreenPos.X);
                    outlineHalfWidth  = Math.Max(outlineHalfWidth, outlineMinPixelSz);
                    outlineHalfHeight = 2f * (targetScreenPos.Y - screenTopMostPt.Y);
                    outlineHalfHeight = Math.Max(outlineHalfHeight, outlineMinPixelSz);
                }

                Vector3 targetViewPos = Vector3.Transform(targetObj.Pos, targetRc.invCameraViewMatrix);

                _targetViewDepth = targetViewPos.Z;
                bool  targetIsInFront = _targetViewDepth < 0f;
                float lineWidth = targetIsInFront ? outlineWidthWhenInFront : outlinelineWidthWhenBehind;
                bool  above, below, left, right;

                if (targetIsInFront)
                {
                    left  = targetScreenPos.X + outlineHalfWidth < 0f;
                    right = !left && targetScreenPos.X - outlineHalfWidth > clientRect.Width;
                    above = targetScreenPos.Y + outlineHalfHeight < 0f;
                    below = !above && targetScreenPos.Y + outlineHalfHeight > clientRect.Height;
                }
                else     // target is behind
                {
                    float halfScrWidth   = clientRect.Width / 2f;
                    float halfScrHeight  = clientRect.Height / 2f;
                    float quartScrWidth  = halfScrWidth / 2f;
                    float quartScrHeight = halfScrHeight / 2f;
                    right = targetScreenPos.X < quartScrWidth;
                    left  = !right && targetScreenPos.X > halfScrWidth + quartScrWidth;
                    below = targetScreenPos.Y < quartScrHeight;
                    above = !below && targetScreenPos.Y > halfScrHeight + quartScrHeight;
                }
                int  orientIdx   = (above ? 1 : 0) + (below ? 2 : 0) + (left ? 4 : 0) + (right ? 8 : 0);
                bool inTheCenter = (orientIdx == 0);

                if (!inTheCenter)
                {
                    outlineHalfWidth  = outlineMinPixelSz;
                    outlineHalfHeight = outlineMinPixelSz;
                    if (left)
                    {
                        targetScreenPos.X = outlineHalfWidth;
                    }
                    else if (right)
                    {
                        targetScreenPos.X = clientRect.Width - outlineHalfWidth - lineWidth * 2f;
                    }
                    if (above)
                    {
                        targetScreenPos.Y = outlineHalfHeight + _labelAbove.getGdiSize.Height;
                    }
                    else if (below)
                    {
                        targetScreenPos.Y = clientRect.Height - outlineHalfHeight - _labelBelow.getGdiSize.Height;
                    }
                }
                _outline.Mesh = inTheCenter ? (targetIsInFront ? hudRectLinesMesh : hudCircleMesh)
                                            : hudTriMesh;
                _outline.Scale = new Vector3(outlineHalfWidth, outlineHalfHeight, 1f);
                _outline.Orient(outlineOrients [orientIdx]);
                _outline.Pos = new Vector3(targetScreenPos.X, targetScreenPos.Y, +1f);

                // labels
                _labelBelow.Label = fetchTextBelow(targetObj);
                var labelBelowPos = targetScreenPos;

                if (left)
                {
                    labelBelowPos.X = 0f;
                }
                else if (right)
                {
                    labelBelowPos.X = clientRect.Width - _labelBelow.getGdiSize.Width - 10f;
                }
                else
                {
                    labelBelowPos.X -= _labelBelow.getGdiSize.Width / 2f;
                }
                labelBelowPos.Y += outlineHalfHeight;
                if ((left || right) && !below)
                {
                    labelBelowPos.Y += outlineHalfHeight;
                }
                _labelBelow.Pos = new Vector3(labelBelowPos.X, labelBelowPos.Y, 0f);

                _labelAbove.Label = fetchTextAbove(targetObj);
                var labelAbovePos = targetScreenPos;

                if (left)
                {
                    labelAbovePos.X = 0f;
                }
                else if (right)
                {
                    labelAbovePos.X = clientRect.Width - _labelAbove.getGdiSize.Width - 10f;
                }
                else
                {
                    labelAbovePos.X -= _labelAbove.getGdiSize.Width / 2f;
                }
                if ((left || right) && !above)
                {
                    labelAbovePos.Y -= outlineHalfHeight;
                }
                labelAbovePos.Y -= (outlineHalfHeight + _labelAbove.getGdiSize.Height);
                _labelAbove.Pos  = new Vector3(labelAbovePos.X, labelAbovePos.Y, 0f);

                Color4 color = fetchColor(targetObj);

                _outline.MainColor    = color;
                _labelBelow.MainColor = color;
                _labelAbove.MainColor = color;

                _outlineScreenRect = new Rectangle(
                    (int)(targetScreenPos.X - outlineHalfWidth),
                    (int)(targetScreenPos.Y - outlineHalfHeight),
                    (int)(outlineHalfWidth * 2f),
                    (int)(outlineHalfHeight * 2f)
                    );
            }