Example #1
0
    public void RenderObject(IGameViewport viewport, GameObject obj, bool showInvisible)
    {
        mTotalLastFrame++;

        var type  = obj.type;
        var flags = obj.GetFlags();

        // Dont render destroyed or disabled objects
        const ObjectFlag dontDrawFlags = ObjectFlag.OFF | ObjectFlag.DESTROYED | ObjectFlag.DONTDRAW;

        if ((flags & dontDrawFlags) != 0)
        {
            return;
        }

        // Hide invisible objects we're supposed to show them
        if ((flags & ObjectFlag.INVISIBLE) != 0 && !showInvisible)
        {
            return;
        }

        // Dont draw secret doors that haven't been found yet
        var secretDoorFlags = obj.GetSecretDoorFlags();

        if (secretDoorFlags.HasFlag(SecretDoorFlag.SECRET_DOOR))
        {
            var found = secretDoorFlags.HasFlag(SecretDoorFlag.SECRET_DOOR_FOUND);
            if (!found && type != ObjectType.portal)
            {
                return;
            }
        }

        var animatedModel = obj.GetOrCreateAnimHandle();

        var animParams = obj.GetAnimParams();

        locXY worldLoc;

        GameObject parent = null;

        if (type.IsEquipment())
        {
            parent = GameSystems.Item.GetParent(obj);
        }

        var alpha = GetAlpha(obj);

        if (parent != null)
        {
            var parentAlpha = GetAlpha(parent);
            alpha = (alpha + parentAlpha) / 2;

            worldLoc = parent.GetLocation();
        }
        else
        {
            worldLoc = obj.GetLocation();
        }

        if (alpha == 0)
        {
            return;
        }

        // Handle fog occlusion of the world position
        if (type != ObjectType.container &&
            (type == ObjectType.projectile ||
             type.IsCritter() ||
             type.IsEquipment()) &&
            (GameSystems.MapFogging.GetFogStatus(worldLoc, animParams.offsetX, animParams.offsetY) & 1) == 0)
        {
            return;
        }

        LocAndOffsets worldPosFull;

        worldPosFull.off_x    = animParams.offsetX;
        worldPosFull.off_y    = animParams.offsetY;
        worldPosFull.location = worldLoc;

        var radius       = obj.GetRadius();
        var renderHeight = obj.GetRenderHeight(true);

        if (!IsObjectOnScreen(viewport.Camera, worldPosFull, animParams.offsetZ, radius, renderHeight))
        {
            return;
        }

        if (Globals.Config.drawObjCylinders)
        {
            Tig.ShapeRenderer3d.DrawCylinder(
                viewport,
                worldPosFull.ToInches3D(animParams.offsetZ),
                radius,
                renderHeight
                );
        }

        var lightSearchRadius = 0.0f;

        if (!flags.HasFlag(ObjectFlag.DONTLIGHT))
        {
            lightSearchRadius = radius;
        }

        LocAndOffsets locAndOffsets;

        locAndOffsets.location = worldLoc;
        locAndOffsets.off_x    = animParams.offsetX;
        locAndOffsets.off_y    = animParams.offsetY;
        var lights = FindLights(locAndOffsets, lightSearchRadius);

        if (type == ObjectType.weapon)
        {
            int glowType;
            if (flags.HasFlag(ObjectFlag.INVENTORY) && parent != null)
            {
                glowType = GameSystems.D20.GetWeaponGlowType(parent, obj);
            }
            else
            {
                glowType = GameSystems.D20.GetWeaponGlowType(null, obj);
            }

            if (glowType != 0 && glowType <= mGlowMaterials.Length)
            {
                var glowMaterial = mGlowMaterials[glowType - 1];
                if (glowMaterial.IsValid)
                {
                    RenderObjectHighlight(viewport, obj, glowMaterial);
                }
            }
        }

        if (GameSystems.ItemHighlight.ShowHighlights &&
            (type.IsEquipment() &&
             !(flags.HasFlag(ObjectFlag.INVENTORY) || flags.HasFlag(ObjectFlag.CLICK_THROUGH)) ||
             GameSystems.Critter.IsLootableCorpse(obj) ||
             type == ObjectType.portal))
        {
            RenderObjectHighlight(viewport, obj, mHighlightMaterial);

            // Add a single light with full ambient color to make the object appear fully lit
            lights.Clear();
            Light3d fullBrightLight = new Light3d();
            fullBrightLight.ambient = LinearColor.White;
            fullBrightLight.color   = new LinearColor(0, 0, 0);
            fullBrightLight.dir     = Vector4.UnitZ;
            fullBrightLight.type    = Light3dType.Directional;
            lights.Add(fullBrightLight);
        }

        mRenderedLastFrame++;
        MdfRenderOverrides overrides = new MdfRenderOverrides();

        overrides.alpha = alpha / 255.0f;
        mAasRenderer.Render(viewport, animatedModel, animParams, lights, overrides);

        Light3d globalLight = new Light3d();

        if (lights.Count > 0)
        {
            globalLight = lights[0];
        }

        if (type.IsCritter())
        {
            if (alpha > 16)
            {
                if (mShadowType == ShadowType.ShadowMap)
                {
                    RenderShadowMapShadow(viewport, obj, animParams, animatedModel, globalLight, alpha);
                }
                else if (mShadowType == ShadowType.Geometry)
                {
                    mAasRenderer.RenderGeometryShadow(
                        viewport.Camera,
                        animatedModel,
                        animParams,
                        globalLight,
                        alpha / 255.0f);
                }
                else if (mShadowType == ShadowType.Blob)
                {
                    RenderBlobShadow(viewport, obj, animatedModel, ref animParams, alpha);
                }
            }

            /*
             * This renders the equipment in a critter's hand separately, but
             * I am not certain *why* exactly. I thought this would have been
             * handled by addmeshes, but it might be that there's a distinct
             * difference between addmeshes that are skinned onto the mobile's
             * skeleton and equipment that is unskinned and just positioned
             * in the player's hands.
             */
            var weaponPrim = GameSystems.Critter.GetWornItem(obj, EquipSlot.WeaponPrimary);
            if (weaponPrim != null)
            {
                RenderObject(viewport, weaponPrim, showInvisible);
            }

            var weaponSec = GameSystems.Critter.GetWornItem(obj, EquipSlot.WeaponSecondary);
            if (weaponSec != null)
            {
                RenderObject(viewport, weaponSec, showInvisible);
            }

            var shield = GameSystems.Critter.GetWornItem(obj, EquipSlot.Shield);
            if (shield != null)
            {
                RenderObject(viewport, shield, showInvisible);
            }
        }
        else if (type.IsEquipment() && mShadowType == ShadowType.Geometry)
        {
            mAasRenderer.RenderGeometryShadow(
                viewport.Camera,
                animatedModel,
                animParams,
                globalLight,
                alpha / 255.0f);
        }

        RenderMirrorImages(
            viewport,
            obj,
            animParams,
            animatedModel,
            lights);

        if (mGrappleController.IsGiantFrog(obj))
        {
            mGrappleController.AdvanceAndRender(
                viewport,
                obj,
                animParams,
                animatedModel,
                lights,
                alpha / 255.0f);
        }
    }
Example #2
0
    public List <Light3d> FindLights(LocAndOffsets atLocation, float radius)
    {
        List <Light3d> lights = new List <Light3d>();

        if (GameSystems.Light.IsGlobalLightEnabled)
        {
            Light3d light       = new Light3d();
            var     legacyLight = GameSystems.Light.GlobalLight;
            light.type  = (Light3dType)legacyLight.type;
            light.color = legacyLight.Color;
            light.dir.X = legacyLight.dir.X;
            light.dir.Y = legacyLight.dir.Y;
            light.dir.Z = legacyLight.dir.Z;
            light.pos.X = legacyLight.pos.X;
            light.pos.Y = legacyLight.pos.Y;
            light.pos.Z = legacyLight.pos.Z;
            light.range = legacyLight.range;
            light.phi   = legacyLight.phi;
            lights.Add(light);
        }

        if (radius == 0)
        {
            return(lights);
        }

        // Build a box that has twice the radius convert to tiles as it's width/height
        // For some reason, ToEE will add one more INCH_PER_TILE here, which translates to
        // roughly 28 tiles more search radius than is needed
        var boxDimensions = (int)(radius / locXY.INCH_PER_TILE + locXY.INCH_PER_TILE);
        var tileX1        = atLocation.location.locx - 1 - boxDimensions;
        var tileX2        = atLocation.location.locx + 1 + boxDimensions;
        var tileY1        = atLocation.location.locy - 1 - boxDimensions;
        var tileY2        = atLocation.location.locy + 1 + boxDimensions;

        using var sectorIterator = new SectorIterator(tileX1, tileX2, tileY1, tileY2);

        var atPos = atLocation.ToInches2D();

        while (sectorIterator.HasNext)
        {
            using var sector = sectorIterator.Next();

            foreach (ref var light in sector.Lights)
            {
                int         type;
                LinearColor color;
                Vector3     direction;
                float       range, phi;
                var         lightPos = light.position.ToInches2D();

                if ((light.flags & 0x40) != 0)
                {
                    if (GameSystems.Light.IsNight)
                    {
                        type      = light.light2.type;
                        color     = light.light2.color;
                        direction = light.light2.direction;
                        range     = light.range; // Notice how it's using light 1's range
                        phi       = light.light2.phi;

                        /*
                         * Kill the daytime particle system if it's night and the
                         * daytime particle system is still alive.
                         */
                        if (light.partSys.handle != null)
                        {
                            GameSystems.ParticleSys.Remove(light.partSys.handle);
                            light.partSys.handle = null;
                        }

                        /*
                         * If the nighttime particle system has not yet been started,
                         * do it here.
                         */
                        ref var nightPartSys = ref light.light2.partSys;
                        if (nightPartSys.handle == null && nightPartSys.hashCode != 0)
                        {
                            var centerOfTile = light.position.ToInches3D(light.offsetZ);
                            nightPartSys.handle = GameSystems.ParticleSys.CreateAt(
                                nightPartSys.hashCode, centerOfTile
                                );
                        }
                    }
                    else
                    {
                        type      = light.type;
                        color     = light.color;
                        direction = light.direction;
                        range     = light.range;
                        phi       = light.phi;

                        // This is just the inverse of what we're doing at night (see above)
                        ref var nightPartSys = ref light.light2.partSys;
                        if (nightPartSys.handle != null)
                        {
                            GameSystems.ParticleSys.Remove(nightPartSys.handle);
                            nightPartSys.handle = null;
                        }

                        ref var dayPartSys = ref light.partSys;
                        if (dayPartSys.handle == null && dayPartSys.hashCode != 0)
                        {
                            var centerOfTile = light.position.ToInches3D(light.offsetZ);
                            dayPartSys.handle = GameSystems.ParticleSys.CreateAt(
                                dayPartSys.hashCode, centerOfTile
                                );
                        }
                    }
                }