Exemplo n.º 1
0
        protected override void setupScene()
        {
            base.setupScene();

            laserOccDiskScene3d = new SSScene(mainShader, pssmShader, instancingShader, instancingPssmShader);
            laserFlareScene2d   = new SSScene(mainShader, pssmShader, instancingShader, instancingPssmShader);

            var mesh = SSAssetManager.GetInstance <SSMesh_wfOBJ>("./drone2/Drone2.obj");

            // add drones
            droneObj1     = new SSObjectMesh(mesh);
            droneObj1.Pos = new OpenTK.Vector3(-20f, 0f, -15f);
            droneObj1.Orient(Quaternion.FromAxisAngle(Vector3.UnitY, (float)Math.PI / 2f));
            //droneObj1.renderState.visible = false;
            droneObj1.Name = "attacker drone";
            main3dScene.AddObject(droneObj1);

            droneObj2           = new SSObjectMesh(mesh);
            droneObj2.Pos       = new OpenTK.Vector3(20f, 0f, -15f);
            droneObj2.Name      = "target drone";
            droneObj2.MainColor = new Color4(1f, 0f, 0.7f, 1f);
            //droneObj2.renderState.visible = false;
            main3dScene.AddObject(droneObj2);

            // manages laser objects
            laserManager = new SLaserManager(alpha3dScene, laserOccDiskScene3d, laserFlareScene2d);

            // tweak the laser start point (by adding an offset in object-local coordinates)
            laserSourceTxfm = Matrix4.CreateTranslation(0f, 1f, 2.75f);

            // debugging snippets:
            //droneObj1.MainColor = Color4.Green;
            //droneObj1.renderState.visible = false;
        }
Exemplo n.º 2
0
        protected override void setupScene()
        {
            base.setupScene();

            var droneMesh = SSAssetManager.GetInstance <SSMesh_wfOBJ> ("./drone2/Drone2.obj");
            //var droneMesh = SSAssetManager.GetInstance<SSMesh_wfOBJ> ("missiles", "missile.obj");
            var vandalMesh = SSAssetManager.GetInstance <SSMesh_wfOBJ> ("missiles/vandal_assembled.obj");

            // add drones
            attackerDrone     = new SSObjectMesh(droneMesh);
            attackerDrone.Pos = new OpenTK.Vector3(-20f, 0f, 0f);
            attackerDrone.Orient(Vector3.UnitX, Vector3.UnitY);
            attackerDrone.AmbientMatColor  = new Color4(0.1f, 0.1f, 0.1f, 0.1f);
            attackerDrone.DiffuseMatColor  = new Color4(0.3f, 0.3f, 0.3f, 0.3f);
            attackerDrone.SpecularMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f);
            attackerDrone.EmissionMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f);
            attackerDrone.Name             = "attacker drone";
            main3dScene.AddObject(attackerDrone);

            targetDrone     = new SSObjectMesh(droneMesh);
            targetDrone.Pos = new OpenTK.Vector3(200f, 0f, 0f);
            targetDrone.Orient(-Vector3.UnitX, Vector3.UnitY);
            targetDrone.AmbientMatColor  = new Color4(0.1f, 0.1f, 0.1f, 0.1f);
            targetDrone.DiffuseMatColor  = new Color4(0.3f, 0.3f, 0.3f, 0.3f);
            targetDrone.SpecularMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f);
            targetDrone.EmissionMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f);
            targetDrone.Name             = "target drone";
            targetDrone.MainColor        = new Color4(1f, 0f, 0.7f, 1f);
            main3dScene.AddObject(targetDrone);

            vandalShip                  = new SSObjectMesh(vandalMesh);
            vandalShip.Pos              = new OpenTK.Vector3(100f, 0f, 0f);
            vandalShip.Scale            = new Vector3(0.05f);
            vandalShip.AmbientMatColor  = new Color4(0.1f, 0.1f, 0.1f, 0.1f);
            vandalShip.DiffuseMatColor  = new Color4(0.1f, 0.1f, 0.1f, 0.1f);
            vandalShip.SpecularMatColor = new Color4(0.1f, 0.1f, 0.1f, 0.1f);
            vandalShip.EmissionMatColor = new Color4(0.0f, 0.0f, 0.0f, 0.0f);
            vandalShip.Name             = "Vandal ship";
            vandalShip.MainColor        = new Color4(0.6f, 0.6f, 0.6f, 1f);
            //vandalShip.MainColor = new Color4(1f, 0f, 0.7f, 1f);
            //droneObj2.renderState.visible = false;
            vandalShip.Orient((targetDrone.Pos - vandalShip.Pos).Normalized(), Vector3.UnitY);
            main3dScene.AddObject(vandalShip);

            // shows explosions
            explosionManager = new SExplosionRenderManager();
            explosionManager.particleSystem.doShockwave = false;
            explosionManager.particleSystem.doDebris    = false;
            explosionManager.particleSystem.timeScale   = 3f;
            //explosionManager.renderState.visible = false;
            alpha3dScene.AddObject(explosionManager);

            // attacker drone missile parameters
            attackerDroneFieldGen = new BodiesFieldGenerator(
                new ParticlesSphereGenerator(Vector3.Zero, 1f));
            attackerDroneMissileParams = new SSpaceMissileVisualParameters();

            // vandal missile params
            vandalShipFieldGen = new BodiesRingGenerator(
                new ParticlesOvalGenerator(1f, 1f),
                ringCenter: new Vector3(0f, 0f, 0f),
                up: Vector3.UnitZ,
                ringRadius: 80f,
                oriPolicy: BodiesFieldGenerator.OrientPolicy.None
                );

            vandalShipMissileParams = new SSpaceMissileVisualParameters();
            vandalShipMissileParams.ejectionMaxRotationVel = 0.05f;
            vandalShipMissileParams.ejectionVelocity       = 30f;
            vandalShipMissileParams.pursuitActivationTime  = 0.1f;
            vandalShipMissileParams.ejectionSmokeDuration  = 0.5f;
            vandalShipMissileParams.ejectionSmokeSizeMax   = 5f;

            cameraMissileParams = new SSpaceMissileVisualParameters();
            //cameraMissileParams.spawnGenerator = null;
            //cameraMissileParams.spawnTxfm = straightMissileSpawnTxfm;
            cameraMissileParams.ejectionMaxRotationVel = 0.05f;
            cameraMissileParams.ejectionVelocity       = 10f;

            // missile manager
            missileManager = new SSpaceMissilesRenderManager(main3dScene, alpha3dScene, hud2dScene);

            // additional statistics text
            missileStatsText = new SSObjectGDISurface_Text();
            missileStatsText.alphaBlendingEnabled = true;
            missileStatsText.Label = "stats placeholder...";
            missileStatsText.Pos   = new Vector3(100f, 100f, 0f);
            //missileStatsText.Size = 20f;
            hud2dScene.AddObject(missileStatsText);

            var targetsManager = new SHudTargetsManager(main3dScene, hud2dScene);

            targetHud = targetsManager.addTarget(
                (o) => Color4.Red,
                _showDistanceFunc,
                (o) => o != null ? o.Name : "none",
                getTargetObject()
                );
        }
Exemplo n.º 3
0
        protected void moveShips(float timeElapsed)
        {
            if (timeElapsed <= 0f)
            {
                return;
            }

            // make the target drone move from side to side
            localTime += timeElapsed;
            Vector3 pos = targetDrone.Pos;

            pos.Z           = 30f * (float)Math.Sin(localTime);
            targetDrone.Pos = pos;

            // make the vandal ship orbit missile target
            Vector3 desiredPos;
            Vector3 desiredDir;
            float   angle          = localTime * 0.5f;
            float   desiredXOffset = 100f * (float)Math.Cos(angle);
            float   desiredYOffset = 20f * (float)Math.Sin(angle * 0.77f);
            float   desiredZOffset = 80f * (float)Math.Sin(angle * 0.88f);
            Vector3 desiredOffset  = new Vector3(desiredXOffset, desiredYOffset, desiredZOffset);

            var target = getTargetObject();

            if (missileLauncher != MissileLaunchers.VandalShip || target == null || target == vandalShip)
            {
                desiredPos = new Vector3(100f, 0f, 0f);
                desiredDir = -Vector3.UnitX;
            }
            else if (target == main3dScene.ActiveCamera)
            {
                desiredPos = main3dScene.ActiveCamera.Pos + -main3dScene.ActiveCamera.Dir * 300f;
                Quaternion cameraOrient = OpenTKHelper.neededRotation(Vector3.UnitZ, -main3dScene.ActiveCamera.Up);
                desiredPos += Vector3.Transform(desiredOffset * 0.1f, cameraOrient);
                desiredDir  = (target.Pos - vandalShip.Pos).Normalized();
            }
            else
            {
                //float desiredZOffset = 5f * (float)Math.Sin(angle + 0.2f);
                desiredPos = target.Pos + desiredOffset;
                desiredDir = (target.Pos - vandalShip.Pos).Normalized();
            }

            Vector3     desiredMotion = desiredPos - vandalShip.Pos;
            const float vel           = 100f;
            float       displacement  = vel * timeElapsed;
            Vector3     vandalNewPos;

            if (displacement > desiredMotion.LengthFast)
            {
                vandalNewPos = desiredPos;
            }
            else
            {
                vandalNewPos = vandalShip.Pos + desiredMotion.Normalized() * displacement;
            }

            vandalVelocity = (vandalNewPos - vandalShip.Pos) / timeElapsed;
            vandalShip.Pos = vandalNewPos;

            Quaternion vandalOrient = OpenTKHelper.neededRotation(Vector3.UnitZ, desiredDir);

            vandalShip.Orient(desiredDir, Vector3.Transform(Vector3.UnitY, vandalOrient));
        }
Exemplo n.º 4
0
        protected override void setupScene()
        {
            base.setupScene();

            // checkerboard floor
                        #if true
            {
                SSTexture   tex          = SSAssetManager.GetInstance <SSTexture> (".", "checkerboard.png");
                const float tileSz       = 4f;
                const int   gridSz       = 10;
                var         tileVertices = new SSVertex_PosNormTex[SSTexturedNormalQuad.c_doubleFaceVertices.Length];
                SSTexturedNormalQuad.c_doubleFaceVertices.CopyTo(tileVertices, 0);
                for (int v = 0; v < tileVertices.Length; ++v)
                {
                    tileVertices[v].TexCoord *= (float)gridSz;
                }

                var quadMesh = new SSVertexMesh <SSVertex_PosNormTex>(tileVertices);
                quadMesh.textureMaterial = new SSTextureMaterial(tex);
                var tileObj = new SSObjectMesh(quadMesh);
                tileObj.Name       = "Tiles";
                tileObj.selectable = false;
                tileObj.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, (float)Math.PI / 2f));
                tileObj.Scale = new Vector3(tileSz * gridSz);
                //tileObj.boundingSphere = new SSObjectSphere(0f);
                main3dScene.AddObject(tileObj);
            }
                        #endif

            // skeleton mesh test
                        #if true
            {
                SSSkeletalAnimation animIdle
                    = SSAssetManager.GetInstance <SSSkeletalAnimationMD5>("./boneman", "boneman_idle.md5anim");
                SSSkeletalAnimation animRunning
                    = SSAssetManager.GetInstance <SSSkeletalAnimationMD5>("./boneman", "boneman_running.md5anim");
                SSSkeletalAnimation animAttack
                    = SSAssetManager.GetInstance <SSSkeletalAnimationMD5>("./boneman", "boneman_attack.md5anim");

                SSSkeletalMesh[] meshes
                    = SSAssetManager.GetInstance <SSSkeletalMeshMD5[]>("./boneman", "boneman.md5mesh");
                var tex = SSAssetManager.GetInstance <SSTexture>("./boneman", "skin.png");
                foreach (var skeliMesh in meshes)
                {
                                #if true
                    var renderMesh0 = new SSSkeletalRenderMesh(skeliMesh);
                    var obj0        = new SSObjectMesh(renderMesh0);
                    obj0.MainColor = Color4.DarkGray;
                    obj0.Name      = "grey bones (bind pose)";
                    obj0.Pos       = new Vector3(-18f, 0f, -18f);
                    obj0.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f));
                    main3dScene.AddObject(obj0);

                    tracker0 = new SSSimpleObjectTrackingJoint(obj0);
                    tracker0.jointPositionLocal           = animIdle.computeJointFrame(11, 0).position;
                    tracker0.neutralViewOrientationLocal  = animIdle.computeJointFrame(11, 0).orientation;
                    tracker0.neutralViewDirectionBindPose = Vector3.UnitY;
                    tracker0.neutralViewUpBindPose        = Vector3.UnitZ;
                    renderMesh0.addCustomizedJoint(11, tracker0);
                                #endif

                                #if true
                    var renderMesh1 = new SSSkeletalRenderMesh(skeliMesh);
                    var obj1        = new SSObjectMesh(renderMesh1);
                    obj1.MainColor = Color4.DarkRed;
                    obj1.Name      = "red bones (running loop)";
                    obj1.Pos       = new Vector3(6f, 0f, -12f);
                    obj1.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f));
                    main3dScene.AddObject(obj1);

                    renderMesh1.playAnimationLoop(animRunning, 0f);
                                #endif

                                #if true
                    var renderMesh2 = new SSSkeletalRenderMesh(skeliMesh);
                    renderMesh2.playAnimationLoop(animIdle, 0f, "all");
                    renderMesh2.playAnimationLoop(animRunning, 0f, "LeftClavicle", "RightClavicle");
                    var obj2 = new SSObjectMesh(renderMesh2);
                    obj2.MainColor = Color.Green;
                    obj2.Name      = "green bones (idle + running loop mixed)";
                    obj2.Pos       = new Vector3(0f, 0f, -12f);
                    obj2.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f));
                    main3dScene.AddObject(obj2);
                                #endif

                                #if true
                    var renderMesh3 = new SSSkeletalRenderMesh(skeliMesh);
                    renderMesh3.playAnimationLoop(animIdle, 0f, "all");
                    var obj3 = new SSObjectMesh(renderMesh3);
                    obj3.MainColor = Color.DarkCyan;
                    obj3.Name      = "blue bones (idle loop)";
                    obj3.Pos       = new Vector3(-6f, 0f, -12f);
                    obj3.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f));
                    main3dScene.AddObject(obj3);
                                #endif

                    // state machines setup for skeletal render mesh 4 and 5
                    var skeletonWalkDescr = new SSAnimationStateMachine();
                    skeletonWalkDescr.addState("idle", animIdle, true);
                    skeletonWalkDescr.addState("running1", animRunning);
                    skeletonWalkDescr.addState("running2", animRunning);
                    skeletonWalkDescr.addAnimationEndsTransition("idle", "running1", 0.3f);
                    skeletonWalkDescr.addAnimationEndsTransition("running1", "running2", 0f);
                    skeletonWalkDescr.addAnimationEndsTransition("running2", "idle", 0.3f);

                    var skeletonAttackDescr = new SSAnimationStateMachine();
                    skeletonAttackDescr.addState("inactive", null, true);
                    skeletonAttackDescr.addState("attack", animAttack);
                    skeletonAttackDescr.addStateTransition(null, "attack", 0.5f);
                    skeletonAttackDescr.addAnimationEndsTransition("attack", "inactive", 0.5f);

                                #if true
                    // state machine test (in slow motion)
                    var renderMesh4 = new SSSkeletalRenderMesh(skeliMesh);
                    renderMesh4.timeScale = 0.25f;

                    var obj4 = new SSObjectMesh(renderMesh4);
                    obj4.MainColor = Color.DarkMagenta;
                    obj4.Name      = "magenta bones (looping idle/walk; interactive attack; slowmo)";
                    obj4.Pos       = new Vector3(-12f, 0f, 0f);
                    obj4.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f));
                    main3dScene.AddObject(obj4);

                    var renderMesh4WallSm = renderMesh4.addStateMachine(skeletonWalkDescr, "all");
                    renderMesh4AttackSm = renderMesh4.addStateMachine(skeletonAttackDescr, "LeftClavicle", "RightClavicle");

                    tracker4 = new SSSimpleObjectTrackingJoint(obj4);
                    tracker4.jointPositionLocal           = animRunning.computeJointFrame(11, 0).position;
                    tracker4.neutralViewOrientationLocal  = animRunning.computeJointFrame(11, 0).orientation;
                    tracker4.neutralViewDirectionBindPose = Vector3.UnitY;
                    renderMesh4.addCustomizedJoint(11, tracker4);
                                #endif

                                #if true
                    // another mesh, using the same state machine but running at normal speed
                    var renderMesh5       = new SSSkeletalRenderMesh(skeliMesh);
                    var renderMesh5WalkSm = renderMesh5.addStateMachine(skeletonWalkDescr, "all");
                    renderMesh5AttackSm = renderMesh5.addStateMachine(skeletonAttackDescr, "LeftClavicle", "RightClavicle");
                    var obj5 = new SSObjectMesh(renderMesh5);
                    obj5.Name = "orange bones (looping idle/walk, interactive attack + parametric neck rotation)";
                    obj5.Pos  = new Vector3(12f, 0f, 0f);
                    obj5.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f));
                    obj5.MainColor = Color4.DarkOrange;
                    main3dScene.AddObject(obj5);

                    renderMesh5NeckJoint = new SSPolarJoint();
                    renderMesh5NeckJoint.positionOffset = new Vector3(0f, 0.75f, 0f);
                    renderMesh5.addCustomizedJoint("UpperNek", renderMesh5NeckJoint);
                                #endif
                }
            }
                        #endif

                        #if true
            // bob mesh test
            {
                var bobMeshes = SSAssetManager.GetInstance <SSSkeletalMeshMD5[]>(
                    "./bob_lamp/", "bob_lamp_update.md5mesh");
                var bobAnim = SSAssetManager.GetInstance <SSSkeletalAnimationMD5>(
                    "./bob_lamp/", "bob_lamp_update.md5anim");
                var bobRender = new SSSkeletalRenderMesh(bobMeshes);
                bobRender.playAnimationLoop(bobAnim, 0f);
                bobRender.alphaBlendingEnabled = true;
                bobRender.timeScale            = 0.5f;
                var bobObj = new SSObjectMesh(bobRender);
                bobObj.Name = "Bob";
                bobObj.Pos  = new Vector3(10f, 0f, 10f);
                bobObj.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f));
                alpha3dScene.AddObject(bobObj);
            }
                        #endif
        }
Exemplo 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)
                    );
            }