rendered paste bodyusing System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Fds.Xna.Enigma.Graphics;
using Microsoft.Xna.Framework.Graphics;
using Fds.Xna.Enigma.Graphics.Lighting;
namespace Fds.Xna.Enigma.Sandbox
{
public enum EditType
{
Terrain,
Texture
}
public class TerrainManipulationScene : Scene
{
const int width = 256;
const int depth = 256;
Vector4[] weights = new Vector4[] {
new Vector4(1, 0, 0, 0),
new Vector4(0, 1, 0, 0),
new Vector4(0, 0, 1, 0),
new Vector4(0, 0, 0, 1),
};
SpriteBatch spriteBatch;
Effect effect;
Texture2D[] textures;
KeyboardState previousKeyboardState;
MouseState previousMouseState;
VertexDeclaration vertexDeclaration;
Matrix world = Matrix.CreateTranslation(Vector3.Zero);
VertexTerrain[] vertices = new VertexTerrain[width * depth];
Vector3 pickTarget;
EditType editType = EditType.Terrain;
int[] indices = new int[(width * depth * 6)];
int triangleCount;
int? selctedIndex;
float morphRadius = 1;
float morphPower = 1;
int currentTextureIndex = 0;
public TerrainManipulationScene(Game game)
: base(game)
{
}
protected override void LoadContent()
{
base.LoadContent();
Game.IsMouseVisible = true;
spriteBatch = new SpriteBatch(GraphicsDevice);
vertexDeclaration = new VertexDeclaration(GraphicsDevice, VertexTerrain.VertexElements);
effect = Game.Content.Load<Effect>("Effects\\DeferredRendering\\DeferredTerrain");
DirectionalLight dlight = new DirectionalLight();
dlight.Direction = new Vector3(0f, -1f, 0);
dlight.Color = Color.White;
Lights.Add(dlight);
textures = new Texture2D[5];
textures[0] = Game.Content.Load<Texture2D>("Textures\\Sand01");
textures[1] = Game.Content.Load<Texture2D>("Textures\\Grass01");
textures[2] = Game.Content.Load<Texture2D>("Textures\\Rock01");
textures[3] = Game.Content.Load<Texture2D>("Textures\\Snow01");
textures[4] = Game.Content.Load<Texture2D>("Textures\\TerrainCursor");
Camera = new Camera();
Camera.Move(0f, 75f, -50f);
Camera.Perspective(45f, 4f / 3f, 1f, 1000f);
Camera.Rotate(0f, -90f, 0f);
for (int z = 0; z < depth; z++)
{
for (int x = 0; x < width; x++)
{
int index = x + (z * width);
vertices[index].Position = new Vector3(x + width / -2, 0, z + depth / -2);
vertices[index].Normal = new Vector3(0, 1, 0);
vertices[index].TextureWeight = new Vector4(1, 0, 0, 0);
}
}
for (int z = 0; z < depth - 1; z++)
{
for (int x = 0; x < width - 1; x++)
{
indices[(x + (z * width)) * 6] = (x + z * width);
indices[(x + (z * width)) * 6 + 1] = (x + z * width) + 1;
indices[(x + (z * width)) * 6 + 2] = (x + (z + 1) * width);
indices[(x + (z * width)) * 6 + 3] = (x + (z + 1) * width);
indices[(x + (z * width)) * 6 + 4] = (x + z * width) + 1;
indices[(x + (z * width)) * 6 + 5] = (x + (z + 1) * width) + 1;
}
}
triangleCount = indices.Length / 3;
}
public void ProcessNormals()
{
for (int z = 1; z < depth - 1; z++)
{
for (int x = 1; x < width - 1; x++)
{
int index = x + (z * width);
Vector3 normX =
new Vector3((vertices[index - 1].Position.Y -
vertices[index + 1].Position.Y) / 2,
1, 0);
Vector3 normZ =
new Vector3(0, 1,
(vertices[x + ((z - 1) * width)].Position.Y -
vertices[x + ((z + 1) * width)].Position.Y) / 2);
vertices[index].Normal = normX + normZ;
vertices[index].Normal.Normalize();
}
}
}
public void SmoothTerrain(int smoothingPasses)
{
if (smoothingPasses < 0)
{
smoothingPasses = 0;
}
int passes = (int)smoothingPasses;
VertexTerrain[] newVertices;
while (passes > 0)
{
passes--;
newVertices = new VertexTerrain[width * depth];
for (int x = 0; x < width; x++)
{
for (int z = 0; z < depth; z++)
{
int adjacentSections = 0;
float sectionsTotal = 0.0f;
if (x == 0 || x == width - 1 || z == 0 || z == depth - 1)
{
continue;
}
// =================================================================
if ((x - 1) > 0) // Check to left
{
sectionsTotal += vertices[z + ((x - 1) * depth)].Position.Y;
adjacentSections++;
if ((z - 1) > 0) // Check up and to the left
{
sectionsTotal += vertices[(z - 1) + ((x - 1) * depth)].Position.Y;
adjacentSections++;
}
if ((z + 1) < depth) // Check down and to the left
{
sectionsTotal += vertices[(z + 1) + ((x - 1) * depth)].Position.Y;
adjacentSections++;
}
}
// =================================================================
// =================================================================
if ((x + 1) < width) // Check to right
{
sectionsTotal += vertices[z + ((x + 1) * depth)].Position.Y;
adjacentSections++;
if ((z - 1) > 0) // Check up and to the right
{
sectionsTotal += vertices[(z - 1) + ((x + 1) * depth)].Position.Y;
adjacentSections++;
}
if ((z + 1) < depth) // Check down and to the right
{
sectionsTotal += vertices[(z + 1) + ((x + 1) * depth)].Position.Y;
adjacentSections++;
}
}
// =================================================================
// =================================================================
if ((z - 1) > 0) // Check above
{
sectionsTotal += vertices[(z - 1) + (x * depth)].Position.Y;
adjacentSections++;
}
// =================================================================
// =================================================================
if ((z + 1) < depth) // Check below
{
sectionsTotal += vertices[(z + 1) + (x * depth)].Position.Y;
adjacentSections++;
}
// =================================================================
newVertices[z + (x * depth)].Position.Y = (vertices[z + (x * depth)].Position.Y + (sectionsTotal / adjacentSections)) * 0.5f;
}
}
// Overwrite the HeightData info with our new smoothed info
for (int x = 0; x < width; x++)
for (int z = 0; z < depth; z++)
{
vertices[z + (x * depth)].Position.Y = newVertices[z + (x * depth)].Position.Y;
}
}
}
public int? FindPickingTarget(MouseState mouseState)
{
Viewport viewport = GraphicsDevice.Viewport;
Vector3 minSource = new Vector3(mouseState.X, mouseState.Y, viewport.MinDepth);
Vector3 maxSource = new Vector3(mouseState.X, mouseState.Y, viewport.MaxDepth);
Vector3 nearSource = viewport.Unproject(minSource, Camera.Projection, Camera.View, world);
Vector3 farSource = viewport.Unproject(maxSource, Camera.Projection, Camera.View, world);
Vector3 direction = farSource - nearSource;
Ray ray = new Ray(nearSource, direction);
for (int i = 0; i < vertices.Length - 3; i++)
{
Vector3 pos = Vector3.Transform(vertices[i].Position, world);
BoundingBox bb = new BoundingBox(pos + Vector3.One * -1f, pos + Vector3.One * 1f);
float? length;
ray.Intersects(ref bb, out length);
if (length.HasValue)
{
pickTarget = ray.Position + ray.Direction * length.Value;
return i;
}
}
return null;
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
KeyboardState currentKeyboardState = Keyboard.GetState();
MouseState currentMouseState = Mouse.GetState();
if (currentKeyboardState.IsKeyDown(Keys.Left)) Camera.Move(-50 * elapsed, 0, 0);
if (currentKeyboardState.IsKeyDown(Keys.Right)) Camera.Move(50 * elapsed, 0, 0);
if (currentKeyboardState.IsKeyDown(Keys.Up)) Camera.Move(0, 0, 50 * elapsed);
if (currentKeyboardState.IsKeyDown(Keys.Down)) Camera.Move(0, 0, -50 * elapsed);
if (currentKeyboardState.IsKeyDown(Keys.PageUp)) Camera.Move(0, 50 * elapsed, 0);
if (currentKeyboardState.IsKeyDown(Keys.PageDown)) Camera.Move(0, -50 * elapsed, 0);
if (currentKeyboardState.IsKeyDown(Keys.A)) Camera.Rotate(50 * elapsed, 0, 0);
if (currentKeyboardState.IsKeyDown(Keys.D)) Camera.Rotate(-50 * elapsed, 0, 0);
if (currentKeyboardState.IsKeyDown(Keys.W)) Camera.Rotate(0, 50 * elapsed, 0);
if (currentKeyboardState.IsKeyDown(Keys.S)) Camera.Rotate(0, -50 * elapsed, 0);
if (currentKeyboardState.IsKeyDown(Keys.OemMinus)) morphRadius = MathHelper.Clamp(morphRadius - (morphRadius * 0.5f) * elapsed, 1f, 6f);
if (currentKeyboardState.IsKeyDown(Keys.OemPlus)) morphRadius = MathHelper.Clamp(morphRadius + (morphRadius * 0.5f) * elapsed, 1f, 6f);
if (currentKeyboardState.IsKeyDown(Keys.Q)) morphPower = MathHelper.Clamp(morphPower - (morphPower * 0.5f) * elapsed, 1f, 30f);
if (currentKeyboardState.IsKeyDown(Keys.E)) morphPower = MathHelper.Clamp(morphPower + (morphPower * 0.5f) * elapsed, 1f, 30f);
if (previousKeyboardState != null)
{
if (currentKeyboardState.IsKeyDown(Keys.Tab) && !previousKeyboardState.IsKeyDown(Keys.Tab))
{
editType = (editType == EditType.Terrain) ? EditType.Texture : EditType.Terrain;
}
if (currentKeyboardState.IsKeyDown(Keys.T) && !previousKeyboardState.IsKeyDown(Keys.T))
{
currentTextureIndex++;
if (currentTextureIndex > 3)
{
currentTextureIndex = 0;
}
}
if (currentKeyboardState.IsKeyDown(Keys.F1) && !previousKeyboardState.IsKeyDown(Keys.F1))
{
SmoothTerrain(1);
ProcessNormals();
}
if (currentKeyboardState.IsKeyDown(Keys.F2))
{
SmoothTerrain(1);
ProcessNormals();
}
if (currentKeyboardState.IsKeyDown(Keys.F12) && !previousKeyboardState.IsKeyDown(Keys.F12))
{
float min = float.MaxValue;
float max = float.MinValue;
for (int i = 0; i < vertices.Length; i++)
{
if (vertices[i].Position.Y > max) max = vertices[i].Position.Y;
if (vertices[i].Position.Y < min) min = vertices[i].Position.Y;
}
max -= min;
min = 0;
if (max < 256)
{
max = 256;
}
Texture2D heightmap = new Texture2D(GraphicsDevice, width, depth, 1, TextureUsage.None, SurfaceFormat.Vector4);
Vector4[] colors = new Vector4[width * depth];
for (int z = 0; z < depth; z++)
{
for (int x = 0; x < width; x++)
{
float posY = vertices[x + z * width].Position.Y;
float height = MathHelper.Clamp(posY / max, 0.0f, 1f);
float w = 1.0f;
colors[x + z * width] = new Vector4(height, height, height, w);
}
}
heightmap.SetData<Vector4>(colors);
heightmap.Save("heightmap.png", ImageFileFormat.Png);
}
if (currentKeyboardState.IsKeyDown(Keys.F11) && !previousKeyboardState.IsKeyDown(Keys.F11))
{
Texture2D colormap = new Texture2D(GraphicsDevice, width, depth, 1, TextureUsage.None, SurfaceFormat.Vector4);
Vector4[] colors = new Vector4[width * depth];
for (int z = 0; z < depth; z++)
{
for (int x = 0; x < width; x++)
{
Vector4 color = vertices[x + z * width].TextureWeight;
color.W = 1 - color.W;
colors[x + z * width] = color;
}
}
colormap.SetData<Vector4>(colors);
colormap.Save("colormap.png", ImageFileFormat.Png);
}
}
if (previousMouseState != null)
{
if (currentMouseState.LeftButton == ButtonState.Pressed && selctedIndex.HasValue)
{
for (int i = 0; i < vertices.Length; i++)
{
Vector3 delta = pickTarget - vertices[i].Position;
float length = delta.Length();
float scalar = MathHelper.Clamp(morphRadius - (length / morphRadius), 0.0f, 1f);
if (editType == EditType.Terrain)
{
vertices[i].Position.Y += morphPower * scalar * elapsed;
}
else
{
vertices[i].TextureWeight -= vertices[i].TextureWeight * scalar * elapsed;
vertices[i].TextureWeight += weights[currentTextureIndex] * scalar * elapsed;
}
}
if (editType == EditType.Terrain)
{
ProcessNormals();
}
}
else if (currentMouseState.RightButton == ButtonState.Pressed && selctedIndex.HasValue)
{
for (int i = 0; i < vertices.Length; i++)
{
Vector3 delta = pickTarget - vertices[i].Position;
float length = delta.Length();
float scalar = MathHelper.Clamp(morphRadius - (length / morphRadius), 0.0f, 1f);
vertices[i].Position.Y -= morphPower * scalar * elapsed;
}
if (editType == EditType.Terrain)
{
ProcessNormals();
}
}
selctedIndex = FindPickingTarget(currentMouseState);
}
Game.Window.Title = String.Format("Edit Type: {2} Morph Power: {0} Morph Radius: {1}",
morphPower, morphRadius, Enum.GetName(typeof(EditType), editType));
previousKeyboardState = currentKeyboardState;
previousMouseState = currentMouseState;
}
public override void Draw(GameTime gameTime)
{
base.Draw(gameTime);
Matrix world = Matrix.CreateTranslation(Vector3.Zero);
GraphicsDevice.VertexDeclaration = vertexDeclaration;
GraphicsDevice.RenderState.DepthBufferEnable = true;
GraphicsDevice.RenderState.CullMode = CullMode.None;
GraphicsDevice.RenderState.PointSpriteEnable = false;
if (selctedIndex.HasValue)
{
effect.Parameters["EditTexture"].SetValue(textures[4]);
}
else
{
effect.Parameters["EditTexture"].SetValue((Texture)null);
}
effect.Parameters["WorldViewProj"].SetValue(world * Camera.View * Camera.Projection);
effect.Parameters["World"].SetValue(world);
effect.Parameters["DirtTexture"].SetValue(textures[0]);
effect.Parameters["GrassTexture"].SetValue(textures[1]);
effect.Parameters["RockTexture"].SetValue(textures[2]);
effect.Parameters["SnowTexture"].SetValue(textures[3]);
effect.Parameters["Scale"].SetValue(new Vector3(1, 1, 1));
effect.Parameters["UVScale"].SetValue(new Vector2(0.05f, 0.05f));
effect.Parameters["EditMode"].SetValue(true);
effect.Parameters["EditRadius"].SetValue(morphRadius);
effect.Parameters["EditPosition"].SetValue(pickTarget);
effect.Parameters["HeightmapSize"].SetValue(new Vector2(width, depth));
effect.Begin();
effect.CurrentTechnique.Passes[0].Begin();
GraphicsDevice.DrawUserIndexedPrimitives<VertexTerrain>(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indices, 0, triangleCount);
effect.CurrentTechnique.Passes[0].End();
effect.End();
}
public void DrawDiagnosticInfo()
{
spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState);
spriteBatch.Draw(textures[currentTextureIndex], new Rectangle(0, 0, 50, 50), Color.White);
spriteBatch.End();
}
}
}