public void GenerateRoof(GraphicsDevice gd, WorldRC world, Blueprint bp) { RoofTexture = bp.RoofComp.Texture; int baseIndex = 0; var verts = new List <VertexPositionTexture>(); var inds = new List <int>(); bp.RoofComp.RegenRoof(gd); var basepos = new Vector2(bp.Width - FLOOR_TILES, bp.Height - FLOOR_TILES) * 1.5f; for (int i = 1; i < bp.Stories + 1; i++) { var basetc = new Vector2((1 / 3f) * ((Math.Min(i, 4) % 3) + 1), (1 / 2f) * ((Math.Min(i, 4) / 3) + 1)); var data = bp.RoofComp.MeshRectData(i + 1); if (RoofOnFloor) { verts.AddRange(data.Item1.Select(x => new VertexPositionTexture(x.Position / 3f, basetc - new Vector2((x.Position.X - basepos.X) / (3f * FLOOR_TILES * 3), (x.Position.Z - basepos.Y) / (3f * FLOOR_TILES * 2))))); } else { verts.AddRange(data.Item1.Select(x => new VertexPositionTexture(x.Position / 3f, new Vector2(x.GrassInfo.Y, x.GrassInfo.Z)))); } inds.AddRange(data.Item2.Select(x => x + baseIndex)); baseIndex += data.Item1.Length; } RoofVerts = verts.ToArray(); RoofIndices = inds.ToArray(); }
public void Generate(GraphicsDevice gd, WorldRC world, Blueprint bp) { GenerateWalls(gd, world, bp, false); //GROUND_SUBDIV = 64; GenerateFloor(gd, world, bp, false); //SimplifyFloor(); GenerateRoof(gd, world, bp); }
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; } }
public FSOF GetFSOF(GraphicsDevice gd, WorldRC world, Blueprint bp, Action onNight, bool compressed) { var result = new FSOF(); RoofOnFloor = true; GenerateWalls(gd, world, bp, false); //GROUND_SUBDIV = 64; GenerateFloor(gd, world, bp, false); //SimplifyFloor(); GenerateRoof(gd, world, bp); result.TexCompressionType = (compressed) ? 1 : 0; result.FloorWidth = FloorTexture.Width; result.FloorHeight = FloorTexture.Height; result.WallWidth = WallTarget.Width; result.WallHeight = WallTarget.Height; result.FloorTextureData = TexToData(FloorTexture, compressed); result.WallTextureData = TexToData(WallTarget, compressed); var tVerts = new List <DGRP3DVert>(); var tInd = new List <int>(); var indOff = 0; for (int i = 0; i < 5; i++) { var tcOffset = new Vector2((i % 3) / 3f, (i / 3) / 2f); //save each floor. offset the floor for each level var posOffset = i * 2.95f; var fVerts = FloorVerts.Select(x => new DGRP3DVert(new Vector3(x.Position.X, x.Position.Y + posOffset, x.Position.Z), Vector3.Zero, x.TextureCoordinate + tcOffset)); tVerts.AddRange(fVerts); tInd.AddRange(FloorIndices.Select(x => x + indOff)); indOff = tVerts.Count; if (i == 0) { tcOffset = new Vector2((5 % 3) / 3f, (5 / 3) / 2f); //save each floor. offset the floor for each level posOffset = 0.5f * 2.95f; fVerts = FloorVerts.Select(x => new DGRP3DVert(new Vector3(x.Position.X, x.Position.Y + posOffset, x.Position.Z), Vector3.Zero, x.TextureCoordinate + tcOffset)); tVerts.AddRange(fVerts); tInd.AddRange(FloorIndices.Select(x => x + indOff)); indOff = tVerts.Count; } } tVerts.AddRange(RoofVerts.Select(x => new DGRP3DVert(x.Position, Vector3.Zero, x.TextureCoordinate))); tInd.AddRange(RoofIndices.Select(x => x + indOff)); DGRP3DVert.GenerateNormals(false, tVerts, FloorIndices); result.FloorVertices = tVerts.ToArray(); result.FloorIndices = tInd.ToArray(); var tempVerts = WallVerts.Select(x => new DGRP3DVert(x.Position, Vector3.Zero, x.TextureCoordinate)).ToList(); DGRP3DVert.GenerateNormals(false, tempVerts, WallIndices); result.WallVertices = tempVerts.ToArray(); result.WallIndices = WallIndices; onNight(); GenerateWalls(gd, world, bp, true); GenerateFloor(gd, world, bp, true); result.NightFloorTextureData = TexToData(FloorTexture, compressed); result.NightWallTextureData = TexToData(WallTarget, compressed); result.NightLightColor = world.State.OutsideColor; return(result); }
public void GenerateFloor(GraphicsDevice gd, WorldRC world, Blueprint bp, bool justTexture) { var dim = FLOOR_RES_PER_TILE * FLOOR_TILES; var tex = new RenderTarget2D(gd, dim * 3, dim * 2, false, SurfaceFormat.Color, DepthFormat.Depth24); gd.SetRenderTarget(tex); gd.Clear(Color.TransparentBlack); var lookat = Matrix.CreateLookAt(new Vector3(bp.Width * 1.5f, 200, bp.Height * 1.5f), new Vector3(bp.Width * 1.5f, 0, bp.Height * 1.5f), new Vector3(0, 0, 1)); var baseO = Matrix.CreateOrthographic(FLOOR_TILES * 3f, FLOOR_TILES * 3f, 0, 400); var oldLevel = world.State.SilentLevel; for (int i = 0; i < bp.Stories + 1; i++) { world.State.SilentLevel = (sbyte)(i + 1); var x = i % 3; var y = i / 3; var offMat = Matrix.CreateScale(1 / 3f, 1 / 2f, 1f) * Matrix.CreateTranslation(-1 + ((x + 0.5f) * 2 / 3f), 1 - ((y + 0.5f) * 2 / 2f), 0); gd.RasterizerState = Scissor; gd.ScissorRectangle = new Rectangle(dim * x + 1, dim * y + 1, dim - 2, dim - 2); if (i == bp.Stories) { var effect = WorldContent.RCObject; gd.BlendState = BlendState.NonPremultiplied; var vp = lookat * baseO * offMat; effect.Parameters["ViewProjection"].SetValue(vp); var frustrum = new BoundingFrustum(lookat * baseO); effect.CurrentTechnique = effect.Techniques["Draw"]; var objs = bp.Objects.Where(o => o.Level == 1 && frustrum.Intersects(((ObjectComponentRC)o).GetBounds())).OrderBy(o => ((ObjectComponentRC)o).SortDepth(vp)); foreach (var obj in objs) { obj.Draw(gd, world.State); } } else { var floors = new HashSet <sbyte>(); floors.Add((sbyte)i); var mat = baseO * offMat; bp.Terrain.DrawCustom(gd, world.State, lookat, mat, 1, floors); if (i == 0) { bp.Terrain.DrawMask(gd, world.State, lookat, mat); } var effect = WorldContent.RCObject; gd.BlendState = BlendState.NonPremultiplied; var vp = lookat * baseO * offMat; effect.Parameters["ViewProjection"].SetValue(vp); var frustrum = new BoundingFrustum(lookat * baseO); effect.CurrentTechnique = effect.Techniques["Draw"]; var objs = bp.Objects.Where(o => o.Level == i + 1 && frustrum.Intersects(((ObjectComponentRC)o).GetBounds())).OrderBy(o => ((ObjectComponentRC)o).SortDepth(vp)); foreach (var obj in objs) { obj.Draw(gd, world.State); } if (RoofOnFloor) { //gd.DepthStencilState = DepthStencilState.None; gd.DepthStencilState = DepthStencilState.Default; if (i > 0) { bp.RoofComp.DrawOne(gd, lookat, mat, world.State, i - 1); } if (i == bp.Stories - 1) { bp.RoofComp.DrawOne(gd, lookat, mat, world.State, i); } gd.DepthStencilState = DepthStencilState.Default; } } } world.State.SilentLevel = oldLevel; /* * using (var fs = new FileStream(@"C:\Users\Rhys\Desktop\floor.png", FileMode.Create, FileAccess.Write)) * tex.SaveAsPng(fs, tex.Width, tex.Height); */ if (!justTexture) { var vertDiv = GROUND_SUBDIV + 1; var inc = FLOOR_TILES / (float)GROUND_SUBDIV; var invDiv = 1 / (float)GROUND_SUBDIV; var basepos = new Vector2(bp.Width - FLOOR_TILES, bp.Height - FLOOR_TILES) / 2; var basetc = new Vector2(1 / 3f, 1 / 2f); FloorVerts = new VertexPositionTexture[vertDiv * vertDiv]; //output vertices int verti = 0; for (int y = 0; y < vertDiv; y++) { for (int x = 0; x < vertDiv; x++) { var pos = basepos + new Vector2(x * inc, y * inc); var height = bp.InterpAltitude(new Vector3(pos, 0)); FloorVerts[verti++] = new VertexPositionTexture(new Vector3(pos.X, height, pos.Y), basetc - new Vector2(x * invDiv / 3, y * invDiv / 2)); } } //output indices int indi = 0; FloorIndices = new int[GROUND_SUBDIV * GROUND_SUBDIV * 6]; for (int y = 0; y < GROUND_SUBDIV; y++) { for (int x = 0; x < GROUND_SUBDIV; x++) { var baseVert = x + y * vertDiv; FloorIndices[indi++] = baseVert + 1 + vertDiv; FloorIndices[indi++] = baseVert + 1; FloorIndices[indi++] = baseVert; FloorIndices[indi++] = baseVert; FloorIndices[indi++] = baseVert + vertDiv; FloorIndices[indi++] = baseVert + 1 + vertDiv; } } } FloorTexture = tex; gd.SetRenderTarget(null); }