I am trying to achieve drawing triangles from a list of Vector3 Elements.
Previously I have used a heightmap to create vertices and indices however this worked out well because it was a rectangle in a 2d array but not a list.
How would I go about (or modify) my existing code to deal with a list instead of a 2d array.
My existing code for Vertices:
public VertexPositionNormalTexture[] getVerticies(float[,] heightData)
{
VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[terrainLength * terrainWidth];
for (int y = 0; y < terrainLength; y++)
{
for (int x = 0; x < terrainWidth; x++)
{
// position the vertices so that the heightfield is centered
// around x=0,z=0
vertices[x + y * terrainWidth].Position.X = terrainScale * (x - ((terrainWidth - 1) / 2.0f));
vertices[x + y * terrainWidth].Position.Z = terrainScale * (y - ((terrainLength - 1) / 2.0f));
vertices[x + y * terrainWidth].Position.Y = (heightData[x, y] - 1);
vertices[x + y * terrainWidth].TextureCoordinate.X = (float)x / terrainScale;
vertices[x + y * terrainWidth].TextureCoordinate.Y = (float)y / terrainScale;
}
}
return vertices;
}
Here is the code for indices:
public int[] getIndicies()
{
int counter = 0;
int [] indices = new int[(terrainWidth - 1) * (terrainLength - 1) * 6];
for (int y = 0; y < terrainLength - 1; y++)
{
for (int x = 0; x < terrainWidth - 1; x++)
{
int lowerLeft = x + y * terrainWidth;
int lowerRight = (x + 1) + y * terrainWidth;
int topLeft = x + (y + 1) * terrainWidth;
int topRight = (x + 1) + (y + 1) * terrainWidth;
indices[counter++] = topLeft;
indices[counter++] = lowerRight;
indices[counter++] = lowerLeft;
indices[counter++] = topLeft;
indices[counter++] = topRight;
indices[counter++] = lowerRight;
}
}
return indices;
}
You'd be looking at List<List<float> or whichever type you're working with here.
Syntax might change slightly.
Related
I am trying to start work on learning strategy/base building games in unity. I started out by copying code from this video but my version only does a single line of squares.
It is the z dimension that does not continue and it does seem like it is a problem with the triangles/normals as the vertices seem to be in the right place via making the vertices a public variable and seeing them in unity's inspector. I think I'd have to write a widget to show the vertices to be sure as I'm no mathematician. I removed the actual creation of the object in unity for the sake of brevity as there is no math involved. Also the procedural object does seem to crumble to nothing at larger sizes, although that's not really an issue until the first one is fixed.
void BuildMesh()
{
int numTiles = size_x * size_z;
int numTris = numTiles * 2;
int vsize_x = size_x + 1;
int vsize_z = size_z + 1;
int numVerts = vsize_x * vsize_z;
//Generate Mesh Data
vertices = new Vector3[ numVerts ];
Vector3[] normals = new Vector3[ numVerts ];
Vector2[] uv = new Vector2[ numVerts ];
int[] triangles = new int[ numTris * 3];
int x, z;
for (z = 0; z < vsize_z; z++)
{
for (x = 0; x < vsize_x; x++)
{
vertices[z * vsize_x + x] = new Vector3(x * tileSize, 0, z * tileSize);
normals[ z * vsize_x + x] = Vector3.up;
uv[z * vsize_x + x] = new Vector2((float)x / vsize_x, (float)z / vsize_z);
}
}
for (z = 0; z < size_z; z++)
{
for (x = 0; x < size_x; x++)
{
int squareIndex = x * size_x + x;
int triOffset = squareIndex * 6;
triangles[triOffset + 0] = z * vsize_x + x + 0;
triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 0;
triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 3] = z * vsize_x + x + 0;
triangles[triOffset + 4] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 5] = z * vsize_x + x + 1;
}
}
The code from the video:
derHugo answered the question in the comments. Just posting this to mark it as answered. Thanks.
I'm using unity, c#, and I cannot figure out how I can generate a landscape with all different kinds of height colors. For instance, I want sand near the water and snow on mountain peaks. But I cannot manage to make this happen in code where the mesh is being generated.
Just to make clear, The mesh generates perfectly fine, but I cannot manage to change the colors of each separate triangle.
void CreateMesh()
{
planeMesh = new Mesh();
List<Vector3> vertices = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
List<int> indices = new List<int>();
List<Color> colors = new List<Color>();
for (int x = 0; x < gridSize + 1; x++)
{
for (int y = 0; y < gridSize + 1; y++)
{
float height = Mathf.PerlinNoise(y / (float)gridSize, x / (float)gridSize) * 15.0f;
vertices.Add(new Vector3(y, height, x));
if(height > 12)//mountain tops
{
uvs.Add(new Vector2(0, 1/3));//down to up, x first
colors.Add(Color.white);
}
else if(height > 3 && height < 13)//grassy fields
{
uvs.Add(new Vector2(1/3,2/3));
colors.Add(Color.green);
}
else if(height > 0 && height < 4)//sand
{
uvs.Add(new Vector2(2/3, 2/3));
colors.Add(Color.yellow);
}
}
}
//making the indices
for (int b = 0; b < gridSize; b++)
{
for (int c = 0; c < gridSize; c++)
{
indices.Add(b + ((gridSize + 1) * c));
indices.Add(b + gridSize + 1 + ((gridSize + 1) * c));
indices.Add(b + 1 + ((gridSize + 1) * c));
indices.Add(b + gridSize + 1 + ((gridSize + 1) * c));
indices.Add(b + gridSize + 2 + ((gridSize + 1) * c));
indices.Add(b + 1 + ((gridSize + 1) * c));
}
}
planeMesh.SetVertices(vertices);
planeMesh.SetIndices(indices.ToArray(), MeshTopology.Triangles, 0);
planeMesh.SetUVs(0, uvs);
planeMesh.RecalculateNormals();
planeMesh.colors = colors.ToArray();
GetComponent<MeshFilter>().mesh = planeMesh;
GetComponent<MeshFilter>().mesh.name = "Environment";
}
Could you guys help me with that?
Solved it! It seems the numbers I was using for the uvs were being rounded down to 0! I had to make them floats to use them properly.
I have a simple question. How can I shift a linear array in 3 dimensions?
It seems too work but in the X & Y axis i got an index problem.
The reson why I wanna do this is simple. I want to create a volumetric terrain with a chunk buffer, so i only have to recalulate values on the edges when the viewport is moving.
I have read an article about this system :
Essentially they provide a way to scroll a potentially infinite data
field through a fixed size multi-resolution cache.
So my pipline for the generation part would be:
When viewport moves get axis
Shift the axis
Generate some noise only for the new cells
Triangulate the new cells
Update all cell positions
Here are my other images:
http://forum.unity3d.com/threads/array-shifting-wrong-index-i-x-y-size-z-size-size.425448/#post-2751774
Nobody in the unity forums could answer my question...
public int size;
public float speed;
private byte[] volume;
private byte[] shifted;
public bool widthShift, heightShift, depthShift;
private int widthOffset = 0;
private int heightOffset = 0;
private int depthOffset = 0;
private float time = 0;
private int cube;
void Start()
{
volume = new byte[size * size * size];
shifted = new byte[size * size * size];
cube = size * size * size;
for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
for(int z = 0; z < size; z++)
volume[x + y * size + z * size * size] = (x == 0 || y == 0 || z == 0) ? (byte)1 : (byte)0;
}
void Update()
{
time += Time.fixedDeltaTime * speed;
if (time > 1)
{
time = 0;
widthOffset = (widthOffset >= size) ? 0 : widthOffset;
heightOffset = (heightOffset >= size) ? 0 : heightOffset;
depthOffset = (depthOffset >= size) ? 0 : depthOffset;
if (widthShift)
widthOffset++;
else
widthOffset = 0;
if (heightShift)
heightOffset++;
else
heightOffset = 0;
if (depthShift)
depthOffset++;
else
depthOffset = 0;
Shift(widthOffset, heightOffset, depthOffset);
}
}
void Shift(int xOff, int yOff, int zOff)
{
for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
for(int z = 0; z < size; z++)
{
int i = ((x + xOff) + (y + yOff) * size + (z + zOff) * size * size);
i = (i >= cube) ? (i - cube) : i;
shifted[x + y * size + z * size * size] = volume[i];
}
}
void OnDrawGizmos()
{
if(Application.isPlaying)
for(int x = 0; x < size; x++)
for(int y = 0; y < size; y++)
for(int z = 0; z < size; z++)
{
Gizmos.color = (shifted[x + y * size + z * size * size] == 1) ? new Color32(0, 255, 0, 255) : new Color32(255, 0, 0, 4);
Gizmos.DrawWireCube(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f), new Vector3(0.95f, 0.95f, 0.95f));
}
}
Give it a try:
void Shift(int xOff, int yOff, int zOff)
{
for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
for(int z = 0; z < size; z++)
{
int nx = (x + xOff) % size;
int ny = (y + yOff) % size;
int nz = (z + zOff) % size;
int i = (nx + ny * size + nz * size * size);
shifted[x + y * size + z * size * size] = volume[i];
}
}
I'm following this tutorial set: https://www.youtube.com/watch?v=owBt9SNKXCI&index=6&list=PLbghT7MmckI4qGA0Wm_TZS8LVrqS47I9R to dynamically build a tile map layout. It works to a point, but it generates a very strange layout with 128 x 128 sized tiles.
Clearly that strange partitioning shouldn't be happening, but I cannot seem to track down what's going on to cause it. Here is my version of the code, which is mostly identical to quill18creates's version sans a few small differences:
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class TileMap : MonoBehaviour {
public int size_x = 100;
public int size_z = 50;
public float tileSize = 1.0f;
public Texture2D terrainTiles;
int tileResolution = 128;
// Use this for initialization
void Start () {
BuildMesh();
}
Color[][] ChopUpTiles() {
int numTilesPerRow = terrainTiles.width / tileResolution;
int numRows = terrainTiles.height / tileResolution;
Color[][] tiles = new Color[numTilesPerRow*numRows][];
for(int y=0; y < numRows; y++) {
for(int x=0; x < numTilesPerRow; x++) {
tiles[y * numTilesPerRow + x] = terrainTiles.GetPixels( x*tileResolution , y*tileResolution, tileResolution, tileResolution );
}
}
return tiles;
}
void BuildTexture() {
//DTileMap map = new DTileMap(size_x, size_z);
int texWidth = size_x * tileResolution;
int texHeight = size_z * tileResolution;
Texture2D texture = new Texture2D(texWidth, texHeight);
Color[][] tiles = ChopUpTiles();
for(int y=0; y < size_z; y++) {
for(int x=0; x < size_x; x++) {
Color[] p = tiles[Mathf.RoundToInt(Random.Range(0, 5))];
texture.SetPixels(x * tileResolution, y * tileResolution, tileResolution, tileResolution, p);
}
}
//texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
texture.Apply();
MeshRenderer mesh_renderer = GetComponent<MeshRenderer>();
mesh_renderer.sharedMaterials[0].mainTexture = texture;
}
public void BuildMesh() {
int numTiles = size_x * size_z;
int numTris = numTiles * 2;
int vsize_x = size_x + 1;
int vsize_z = size_z + 1;
int numVerts = vsize_x * vsize_z;
// Generate the mesh data
Vector3[] vertices = new Vector3[ numVerts ];
Vector3[] normals = new Vector3[numVerts];
Vector2[] uv = new Vector2[numVerts];
int[] triangles = new int[ numTris * 3 ];
int x, z;
for(z=0; z < vsize_z; z++) {
for(x=0; x < vsize_x; x++) {
vertices[ z * vsize_x + x ] = new Vector3( x*tileSize, 0, -z*tileSize );
normals[ z * vsize_x + x ] = Vector3.up;
uv[ (z * vsize_x) + x ] = new Vector2( (float)x / size_x, (float)z / size_z );
}
}
Debug.Log ("Done Verts!");
for(z=0; z < size_z; z++) {
for(x=0; x < size_x; x++) {
int squareIndex = z * size_x + x;
int triOffset = squareIndex * 6;
triangles[triOffset + 0] = z * vsize_x + x + 0;
triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 0;
triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 3] = z * vsize_x + x + 0;
triangles[triOffset + 5] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 4] = z * vsize_x + x + 1;
}
}
// Create a new Mesh and populate with the data
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
// Assign our mesh to our filter/renderer/collider
MeshFilter mesh_filter = GetComponent<MeshFilter>();
MeshCollider mesh_collider = GetComponent<MeshCollider>();
mesh_filter.mesh = mesh;
mesh_collider.sharedMesh = mesh;
BuildTexture();
}
}
I don't get exactly what part is wrong in the image but I think it is that the same tiles are lumping together.
I tried your code and it works well for me. But I guess the following part could be causing the lumping together problem for you:
Color[] p = tiles[Mathf.RoundToInt(Random.Range(0, 5))];
Instead you should do:
Color[] p = tiles[Random.Range(0, 5)];
Because, the other way, Random is generating float numbers and maybe they are near the each other that rounding them to the integer gives same tile. Give it a try.
Also just reminding, make sure the width and the height of your texture is divisible by 128.
Well, it was definitely a size issue, but there was also an issue with positioning. Tiles have to start at the bottom-left corner for the coordinate system to find them.
I'm trying to give certain colors to image based on their movement (like vector direction) in Emgu Cv. I have managed to calculate the dense optical flow to my video stream. I have used this
OpticalFlow.Farneback(prev,NextFrame,velx,vely,0.5,1,1,2,5,1.1,Emgu.CV.CvEnum.OPTICALFLOW_FARNEBACK_FLAG.FARNEBACK_GAUSSIAN);
The variable vely and velx contains the velocity of vertical and horizontal directions.Does anyone know how to map colors to these. There are many algorithms that calculates the dense flow. HS also can be used, but I'm not sure what to use.
Any solution would be really appreciated.
EDIT:
Optical Flow Color Map in OpenCV
This is the same thing that i wanted, since I'm using Emgu cv I tried to convert this code to c# but I cannot understand how to pass the dense flow to function "colorflow".
public void colorflow(MCvMat imgColor)
{
MCvMat imgHsv = new MCvMat();
double max_s = 0;
double[] hsv_ptr = new double[3000];
IntPtr[] color_ptr = new IntPtr[3000];
int r = 0, g = 0, b = 0;
double angle = 0;
double h = 0, s = 0, v = 0;
double deltaX = 0, deltaY = 0;
int x = 0, y = 0;
for (y = 0; y < imgColor.rows; y++)
{
for (x = 0; x < imgColor.cols; x++)
{
PointF fxy = new PointF(y, x);
deltaX = fxy.X;
deltaY = fxy.Y;
angle = Math.Atan2(deltaX, deltaY);
if (angle < 0)
angle += 2 * Math.PI;
hsv_ptr[3 * x] = angle * 180 / Math.PI;
hsv_ptr[3 * x + 1] = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
hsv_ptr[3 * x + 2] = 0.9;
if (hsv_ptr[3 * x + 1] > max_s)
max_s = hsv_ptr[3 * x + 1];
}
}
for (y = 0; y < imgColor.rows; y++)
{
//hsv_ptr=imgHsv.ptr<float>(y);
//color_ptr=imgColor.ptr<unsigned char>(y);
for (x = 0; x < imgColor.cols; x++)
{
h = hsv_ptr[3 * x];
s = hsv_ptr[3 * x + 1] / max_s;
v = hsv_ptr[3 * x + 2];
//hsv2rgb(h,s,v,r,g,b);
Color c = ColorFromHSV(h, s, v);
color_ptr[3 * x] = (IntPtr)c.B;
color_ptr[3 * x + 1] = (IntPtr)c.G;
color_ptr[3 * x + 2] = (IntPtr)c.R;
}
}
drawLegendHSV(imgColor, 15, 25, 15);
}
I having trouble how to covert the two commented lines in the code. Can anyone Help me with this.?
Another thing that the Farneback algorithm gives two images velx and vely. It does not gives the flow( MCvMat). The colorFlow algorithms it takes the MCvMat type parameters.Did i done any wrong with the code. thanks