budnhead/org.niclasundharald.engine/graphics/SquaredMap.cs

262 lines
5.2 KiB
C#

using System;
using System.IO;
using System.Collections.Generic;
using ImageSharp;
using ImageSharp.PixelFormats;
using OpenTK.Graphics.OpenGL4;
using OpenTK;
using org.niclasundharald.engine;
namespace org.niclasundharald.engine.graphics
{
public class SquaredMap : WorldObject
{
public static SquaredMap activeMap;
private static float edge = 5;
private static float maxHeight = 128.0f;
private int width,
height;
private float[] heightMap;
private MapModel3D model;
public SquaredMap(int width,int height)
{
activeMap = this;
this.width = width;
this.height = height;
this.heightMap = new float[ (width + 1) * (height + 1) ];
generateHeightMap();
computeModel();
}
public override Model3D getModel3D()
{
return this.model;
}
public SquaredMap(Image heightMap)
{
activeMap = this;
this.width = heightMap.Width-1;
this.height = heightMap.Height-1;
this.heightMap = new float[ (width + 1) * (height + 1) ];
loadHeightMap(heightMap);
computeModel();
}
public void generateHeightMap(){
Random rand = new Random();
for (int y = 0; y <= height; y++)
{
for (int x = 0; x <= width; x++)
{
float h = (float)rand.NextDouble();
heightMap[x + (y * width)] = (float)(maxHeight * (h * h));
}
}
}
public void loadHeightMap(Image _heightMap){
Rgba32[] pixels = _heightMap.Pixels;
for (int y = 0; y <= height; y++)
{
for (int x = 0; x <= width; x++)
{
Rgba32 pixel = pixels[ x + (y * (width + 1))];
float h = (pixel.R + pixel.G + pixel.B) * maxHeight / 768;
heightMap[x + (y * (width + 1))] = (float)(h);
}
}
}
public void computeModel(){
float left,
right,
bottom,
top,
vcenter,
hcenter;
Vector3[] vertexes = new Vector3[ 12 * width * height ];
Console.WriteLine("Creating geometry");
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int i = x + ((width + 1) * y);
int j = x + ((width + 1) * (y + 1));
float[] h = new float[4];
h[0] = heightMap[i];
h[1] = heightMap[i+1];
h[2] = heightMap[j];
h[3] = heightMap[j+1];
float ah = (h[0] + h[1] + h[2] + h[3]) / 4.0f;
left = edge * x;
right = edge * (x + 1);
bottom = edge * y;
top = edge * (y + 1);
vcenter = (top + bottom) / 2.0f;
hcenter = (left + right) / 2.0f;
int b = 4 * (x + (width * y));
Model3D.setTriangle(
vertexes,
b,
new Vector3(left, top, h[2]),
new Vector3(right, top, h[3]),
new Vector3(hcenter,vcenter,ah)
);
Model3D.setTriangle(
vertexes,
b + 1,
new Vector3(right, top, h[3]),
new Vector3(right, bottom, h[1]),
new Vector3(hcenter, vcenter, ah)
);
Model3D.setTriangle(
vertexes,
b + 2,
new Vector3(right, bottom, h[1]),
new Vector3(left, bottom, h[0]),
new Vector3(hcenter, vcenter, ah)
);
Model3D.setTriangle(
vertexes,
b + 3,
new Vector3(left, bottom, h[0]),
new Vector3(left, top, h[2]),
new Vector3(hcenter, vcenter, ah)
);
}
}
this.model = new MapModel3D( vertexes );
}
private int indHeightMap(int x,int y){
return x + ((width + 1) * y);
}
public Vector3 ground(Vector2 _xy){
Vector2 xy = _xy / edge;
int i1 = indHeightMap((int)xy.X,(int)xy.Y);
int i2 = indHeightMap((int)xy.X,(int)xy.Y+1);
if ((xy.X < 0)||(xy.Y<0)||(xy.X>=width)||(xy.Y>=height)){
throw new OutOfWorldException();
}
float h = heightMap[i1] +
heightMap[i1 + 1] +
heightMap[i2] +
heightMap[i2 + 1];
h /= 4;
Vector3 v3 = new Vector3(_xy.X,_xy.Y,h);
Console.WriteLine("Grounding: {0}",v3);
return v3;
}
}
class MapModel3D : Model3D {
int nDraw;
public MapModel3D(Vector3[] vertexes){
Vector4[] colors = new Vector4[ vertexes.Length ];
for (int n=0; n< vertexes.Length; n++){
if (vertexes[n].Z >= 256 ){
Console.WriteLine("Max. Height : {0}",vertexes[n].Z / 256);
}
colors[n] = new Vector4(
0.50f + (0.2f * vertexes[n].Z / 256),
0.25f + (0.50f * vertexes[n].Z / 256),
0.10f + (0.80f * vertexes[n].Z / 256),
1.0f
);
}
Vector3[] normals = Model3D.computeNormals(vertexes);
Dictionary<Vector3,List<Vector3>> dNormals = new Dictionary<Vector3, List<Vector3>>();
foreach (Vector3 v in vertexes){
if (!dNormals.ContainsKey(v)){
dNormals.Add(v,new List<Vector3>());
}
}
for (int n=0;n<vertexes.Length;n++){
dNormals[ vertexes[n] ].Add(normals[n]);
}
foreach (Vector3 v in dNormals.Keys){
Vector3 s = new Vector3();
foreach (Vector3 n in dNormals[v]){
s += n;
}
s /= dNormals[v].Count;
dNormals[v].Clear();
dNormals[v].Add(s);
}
for (int n=0;n<vertexes.Length;n++){
normals[n] = dNormals[ vertexes[n] ][0];
}
bind(vertexes, colors, normals);
}
public override void draw()
{
nDraw+= nTriangles >> 8;
if (nDraw > nTriangles){
nDraw = 0;
}
nDraw = nTriangles;
GL.BindVertexArray(this.vao);
GL.DrawArrays(PrimitiveType.Triangles, 0, nDraw * 3);
GL.BindVertexArray(0);
}
}
}