Пример #1
0
            public bool TryAdd(LotFacadeWall wall)
            {
                var effectiveLength = wall.Length;

                if (Walls.Count > 0)
                {
                    effectiveLength += GAP;                  //we need space behind us
                }
                if (effectiveLength > Space)
                {
                    return(false);                         //try the next bin
                }
                else
                {
                    //space after us is not necessary when we hit the edge, so this gap is added after the space check.
                    effectiveLength += GAP;
                    Space           -= effectiveLength;
                    if (Space < 0)
                    {
                        Space = 0;
                    }
                    wall.EffectiveLength = effectiveLength;
                    Walls.Add(wall);
                    return(true);
                }
            }
Пример #2
0
        private int AddToBin(LotFacadeWall wall)
        {
            int i = 0;

            while (true)
            {
                if (i >= WallBins.Count)
                {
                    WallBins.Add(new LotFacadeWallBin());
                }
                if (WallBins[i].TryAdd(wall))
                {
                    return(i);
                }
                i++;
            }
        }
Пример #3
0
        public void GenerateWalls(GraphicsDevice gd, WorldRC world, Blueprint bp, bool justTexture)
        {
            //generate wall geometry and texture.
            if (!justTexture)
            {
                foreach (var room in bp.Rooms)
                {
                    //add walls for each outside room.
                    if (room.Base == room.RoomID && room.IsOutside)
                    {
                        var walls = new List <Vector2[]>(room.WallLines);
                        walls.AddRange(room.FenceLines);
                        foreach (var wall in walls)
                        {
                            var facadeWall = new LotFacadeWall(wall, room);
                            AddToBin(facadeWall);
                        }
                    }
                }
            }

            //ok, allocate the texture for the wall.
            var tex = new RenderTarget2D(gd, MAX_WALL_WIDTH * WALL_WIDTH, CeilToFour(Math.Max(1, WallBins.Count * (WALL_HEIGHT + GAP * 2) - GAP * 2)), false, SurfaceFormat.Color, DepthFormat.Depth24);

            gd.SetRenderTarget(tex);
            gd.DepthStencilState = DepthStencilState.Default;
            gd.Clear(Color.TransparentBlack);
            //ace, let's draw each wall

            var oldLevel = world.State.Level;

            world.State.SilentLevel    = bp.Stories;
            world.State.ZeroWallOffset = true;
            var cuts = bp.Cutaway;

            bp.Cutaway = new bool[cuts.Length];
            bp.WCRC?.Generate(gd, world.State, false);

            int wallCount = 0;
            int bini      = 0;

            foreach (var bin in WallBins)
            {
                var yPos = bini * (WALL_HEIGHT + GAP * 2);
                var xPos = 0;
                foreach (var wall in bin.Walls)
                {
                    wallCount++;
                    //get a camera for this wall first
                    //create a look at matrix for the wall. first find a camera point at one side of the wall,
                    //then create an orthographic projection with the size of the wall in mind.

                    var ctr   = (wall.Points[0] + wall.Points[1]) / (2 * 16);
                    var rNorm = wall.Points[1] - wall.Points[0];
                    rNorm = new Vector2(rNorm.Y, -rNorm.X);
                    rNorm.Normalize();
                    //which side is "outside"?
                    //check one side. assume the other is outside if we fail
                    var testPos = (ctr + rNorm * 0.6f).ToPoint();
                    if (testPos.X >= 0 && testPos.X < bp.Width && testPos.Y >= 0 && testPos.Y < bp.Height)
                    {
                        var room = bp.RoomMap[wall.Room.Floor][testPos.X + testPos.Y * bp.Width];
                        if (!bp.Rooms[bp.Rooms[(ushort)room].Base].IsOutside)
                        {
                            rNorm *= -1;
                        }
                    }

                    var height = (wall.Room.Floor + 0.5f) * 2.95f * 3 + bp.InterpAltitude(new Vector3(ctr, 0)) * 3f + 0.2f;
                    var camp   = (ctr + rNorm) * 3;
                    var objp   = ctr * 3;
                    var lookat = Matrix.CreateLookAt(new Vector3(camp.X, height, camp.Y), new Vector3(objp.X, height, objp.Y), Vector3.Up);
                    var ortho  = Matrix.CreateOrthographic(3 * wall.PhysicalLength, 2.90f * 3, 0, 6);

                    //rescale our camera matrix to render to the correct part of the render target. Apply scissor test for that area.
                    var rect = new Rectangle(xPos + (wall.EffectiveLength - (wall.Length + GAP)), yPos, wall.Length, WALL_HEIGHT);
                    gd.RasterizerState  = Scissor;
                    gd.ScissorRectangle = rect;

                    var trans = Matrix.CreateScale((rect.Width / ((float)tex.Width)), (rect.Height / ((float)tex.Height)), 1) *
                                Matrix.CreateTranslation((-(rect.X * -2 - wall.Length) / (float)tex.Width) - 1f, (-(rect.Y * 2 + WALL_HEIGHT - 2) / (float)tex.Height) + 1f, 0);

                    var frustrum = new BoundingFrustum(lookat * ortho);
                    ortho = ortho * trans;

                    //draw the walls and objects for this wall segment. this is a little slow right now.
                    var effect = WorldContent.RCObject;
                    gd.BlendState = BlendState.NonPremultiplied;
                    var vp = lookat * ortho;
                    effect.Parameters["ViewProjection"].SetValue(vp);

                    bp.WCRC?.Draw(gd, world.State);

                    effect.CurrentTechnique = effect.Techniques["Draw"];

                    var objs = bp.Objects.Where(x => x.Level >= wall.Room.Floor - 5 && frustrum.Intersects(((ObjectComponentRC)x).GetBounds()))
                               .OrderBy(x => ((ObjectComponentRC)x).SortDepth(vp));
                    foreach (var obj in objs)
                    {
                        obj.Draw(gd, world.State);
                    }

                    xPos += wall.EffectiveLength;
                }
                bini++;
            }
            gd.RasterizerState = RasterizerState.CullNone;

            bp.Cutaway = cuts;
            bp.WCRC?.Generate(gd, world.State, false);
            world.State.ZeroWallOffset = false;
            world.State.SilentLevel    = oldLevel;

            //generate wall geometry
            var data = new Color[tex.Width * tex.Height];

            tex.GetData(data);

            var verts   = new VertexPositionTexture[wallCount * 4];
            var indices = new int[wallCount * 6];

            bini = 0;
            var verti = 0;
            var indi  = 0;

            foreach (var bin in WallBins)
            {
                var xInt = 0;
                var yInt = bini * (WALL_HEIGHT + GAP * 2);
                var yPos = bini * (WALL_HEIGHT + GAP * 2) / (float)tex.Height;
                var xPos = 0f;
                var div  = WALL_HEIGHT / (float)tex.Height;
                foreach (var wall in bin.Walls)
                {
                    var rect = new Rectangle(xInt + (wall.EffectiveLength - (wall.Length + GAP)), yInt, wall.Length, WALL_HEIGHT);
                    BleedRect(data, rect, tex.Width, tex.Height);

                    if (!justTexture)
                    {
                        var ctr     = (wall.Points[0] + wall.Points[1]) / (2 * 16);
                        var off     = (wall.EffectiveLength - (wall.Length + GAP)) / (float)tex.Width;
                        var height1 = ((wall.Room.Floor) * 2.95f + bp.InterpAltitude(new Vector3(ctr, 0)));
                        var height2 = height1 + 2.95f;
                        var pt1     = wall.Points[0] / 16f;
                        var pt2     = wall.Points[1] / 16f;
                        verts[verti++] = new VertexPositionTexture(new Vector3(pt1.X, height2, pt1.Y), new Vector2(xPos + off, yPos));
                        verts[verti++] = new VertexPositionTexture(new Vector3(pt2.X, height2, pt2.Y), new Vector2(xPos + off + wall.Length / (float)tex.Width, yPos));
                        verts[verti++] = new VertexPositionTexture(new Vector3(pt2.X, height1, pt2.Y), new Vector2(xPos + off + wall.Length / (float)tex.Width, (yPos + div)));
                        verts[verti++] = new VertexPositionTexture(new Vector3(pt1.X, height1, pt1.Y), new Vector2(xPos + off, (yPos + div)));

                        indices[indi++] = verti - 2;
                        indices[indi++] = verti - 3;
                        indices[indi++] = verti - 4;

                        indices[indi++] = verti - 4;
                        indices[indi++] = verti - 1;
                        indices[indi++] = verti - 2;

                        xInt += wall.EffectiveLength;
                        xPos += wall.EffectiveLength / (float)tex.Width;
                    }
                }
                bini++;
            }

            //using (var fs = new FileStream(@"C:\Users\Rhys\Desktop\walls.png", FileMode.Create, FileAccess.Write))
            //    tex.SaveAsPng(fs, tex.Width, tex.Height);

            tex.SetData(data);

            if (!justTexture)
            {
                WallTarget  = tex;
                WallVerts   = verts;
                WallIndices = indices;
            }
        }