Having trouble generating a mesh in unity - c#

I have been trying to generate a mesh using the code below, and have been successful generating a mesh with width and length of one, but any more and I get an error in the console that says
"Failed setting triangles. Some indices are referencing out of bounds vertices. IndexCount: 24, VertexCount: 9 UnityEngine.Mesh:set_triangles (int[])"
I have done all the math of calculating the triangles on paper, and all of the values are within the length of the vertices array, going from 0 to 8. I don't have any clue what I am doing wrong, or why this error message is getting thrown, so any help would be greatly appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshGenerator : MonoBehaviour
{
Mesh mesh;
Vector3[] vertices;
int[] triangles;
public Mesh GenerateMesh(int mapWidth, int mapHeight)
{
mesh = new Mesh();
vertices = new Vector3[(mapHeight + 1) * (mapWidth + 1)];
triangles = new int[6 * (mapHeight * mapWidth)];
int index = 0;
for (int x = 0; x <= mapHeight; x++)
{
for (int y = 0; y <= mapWidth; y++)
{
vertices[index] = new Vector3(x, 0, y);
index += 1;
}
}
int z = 0;
for (int i = 0; i <= triangles.Length - 1; i += 6)
{
Debug.Log(i);
if (z == mapWidth)
{
triangles[i] = i + 1;
triangles[i + 1] = i + 2;
triangles[i + 2] = i + mapWidth + 3;
triangles[i + 3] = i + 1;
triangles[i + 4] = i + mapWidth + 3;
triangles[i + 5] = i + mapWidth + 2;
z = 1;
}
else
{
triangles[i] = i;
triangles[i + 1] = i + 1;
triangles[i + 2] = i + mapWidth + 2;
triangles[i + 3] = i;
triangles[i + 4] = i + mapWidth + 2;
triangles[i + 5] = i + mapWidth + 1;
z++;
}
}
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
return mesh;
}
}

I figured it out. The problem was I was using the index of the triangle array to calculate the index of the vertex array. Instead, I needed to use a separate variable (a) to calculate the vertex index. The new code is below.
int a = 0;
for (int i = 0; i < triangles.Length; i += 6)
{
Debug.Log(i);
if (z == mapWidth)
{
triangles[i] = a + 1;
triangles[i + 1] = a + 2;
triangles[i + 2] = a + mapWidth + 3;
triangles[i + 3] = a + 1;
triangles[i + 4] = a + mapWidth + 3;
triangles[i + 5] = a + mapWidth + 2;
z = 1;
a += 2;
}
else
{
triangles[i] = a;
triangles[i + 1] = a + 1;
triangles[i + 2] = a + mapWidth + 2;
triangles[i + 3] = a;
triangles[i + 4] = a + mapWidth + 2;
triangles[i + 5] = a + mapWidth + 1;
z++;
a++;
}
}

Related

Implementing Transvoxel algorithm, Gaps and Odd Mesh formations

I am trying to implement the Transvoxel algorithm for a game I am working on but I'm noticing some weird issues in the mesh generated:
Not sure why there are gaps and why the sphere has fins behind it.
For some reason, the mesh has gaps between chunks, and it has these strange fins extending out behind it. I haven't been able to figure out why this is happening but I have an inkling it may have to do with either the function that generates the density values for each Chunk (16x16x16 Block of cells):
private float SampleDensity(float3 _point)
{
var _worldPos = (_point / (m_WorldRadius - 1.0f) - 0.5f) * m_VolumeFieldSize;
var _halfS = m_VolumeFieldSize / 2;
var _maxD= Magnitude(new float3(_halfS, _halfS, _halfS));
var _fudge = 1f;
var _density = Magnitude(_worldPos) / (_maxD + _fudge) - 0.5f;
var _noise = CalculateNoise(_worldPos);
_density += _noise;
return _density;
}
public void Execute()
{
for (int _z = 0; _z < m_ChunkSize; _z++)
{
for (int _y = 0; _y < m_ChunkSize; _y++)
{
for (int _x = 0; _x < m_ChunkSize; _x++)
{
var _point = (new float3(_x, _y, _z) + (m_GPosition)); // Multiplying or dividing this value adjusts the final mesh's scale.
var _valueAtPoint = SampleDensity(_point);
m_Cells[_z * m_ChunkSize * m_ChunkSize + _y * m_ChunkSize + _x] = _valueAtPoint;
}
}
}
}
, or the mesh generating code itself:
for (int _z = 0; _z < _chunk.m_ChunkSize; _z++)
{
for (int _y = 0; _y < _chunk.m_ChunkSize; _y++)
{
for (int _x = 0; _x < _chunk.m_ChunkSize; _x++)
{
var _cubeConfiguration = 0;
for (int _i = 0; _i < 8; _i++)
{
_cornerPos = CornerIndex[_i];
_densityValues[_i] = _chunk.GetCell(_x + _cornerPos.x, _y + _cornerPos.y, _z + _cornerPos.z);
if (_densityValues[_i] < _chunk.m_World.m_ISOLevel) _cubeConfiguration |= (1 << _i);
}
var _caseCode = (byte) _cubeConfiguration;
if (_caseCode == 0) continue;
for (int _i = 0; _i < _cornerNormals.Length; _i++)
{
_cornerPos = CornerIndex[_i];
_cornerNormals[_i] = new Vector3(
_chunk.GetCell(_x + _cornerPos.x - 1, _y + _cornerPos.y, _z + _cornerPos.z) - _chunk.GetCell(_x + _cornerPos.x + 1, _y + _cornerPos.y, _z + _cornerPos.z),
_chunk.GetCell(_x + _cornerPos.x, _y + _cornerPos.y - 1, _z + _cornerPos.z) - _chunk.GetCell(_x + _cornerPos.x, _y + _cornerPos.y + 1, _z + _cornerPos.z),
_chunk.GetCell(_x + _cornerPos.x, _y + _cornerPos.y, _z + _cornerPos.z - 1) - _chunk.GetCell(_x + _cornerPos.x, _y + _cornerPos.y, _z + _cornerPos.z + 1)
);
}
var _cellClass = Transvoxel.regularCellClass[_caseCode];
Debug.Log($"Cell Class {_cellClass}");
var _vertexLocations = Transvoxel.RegularVertexData[_caseCode];
var _cellData = Transvoxel.RegularCellDatas[_cellClass];
var _vertexCount = _cellData.GetVertexCount();
var _triangleCount = _cellData.GetTriangleCount();
var _indexOffset = _cellData.vertexIndex;
for (int _i = 0; _i < _vertexCount; _i++)
{
ushort _edge = (ushort)(_vertexLocations[_i] & 255);
byte _v0 = (byte)((_edge >> 4) & 0x0F); //First Corner Index
byte _v1 = (byte)(_edge & 0x0F); //Second Corner Index
float _t = (_densityValues[_v1]) / (_densityValues[_v1] - _densityValues[_v0]);
Vector3 _p0 = new Vector3((_x + CornerIndex[_v0].x), (_y + CornerIndex[_v0].y), (_z + CornerIndex[_v0].z));
Vector3 _p1 = new Vector3((_x + CornerIndex[_v1].x), (_y + CornerIndex[_v1].y), (_z + CornerIndex[_v1].z));
var _position = (_p0 * _t) + ((1 - _t) * _p1);
var _n0 = CalculateNormal(_chunk, new Vector3Int((int) _p0.x, (int) _p0.y, (int) _p0.z));
var _n1 = CalculateNormal(_chunk, new Vector3Int((int) _p1.x, (int) _p1.y, (int) _p1.z));
var _normal = (_n0 + _t * (_n1 - _n0)).normalized;
m_Normals.Add(_normal);
m_Vertices.Add(_position);
m_UVs.Add(UvOffset[m_VCase]);
m_VCase = (byte)(m_VCase == 3 ? 0 : m_VCase + 1);
m_LocalVertexMapping[_i] = (ushort)(m_Vertices.Count - 1);
}
for (int _t = 0; _t < _triangleCount; _t++)
{
int _tm = _t * 3;
m_Triangles.Add(m_LocalVertexMapping[_indexOffset[_tm]]);
m_Triangles.Add(m_LocalVertexMapping[_indexOffset[_tm + 1]]);
m_Triangles.Add(m_LocalVertexMapping[_indexOffset[_tm + 2]]);
}
}
}
}
I am at a complete loss and would really appreciate some help as I've been racking my brains for close to 2 months on this, along with reading several papers on different MC Algorithms (Lengyel's included) for potential inspiration. Thank You.

2d array challenge access elements

Attempting the hackerRank Q from https://www.hackerrank.com/challenges/2d-array
static void Main(String[] args)
{
int[][] arr = new int[6][];
for (int arr_i = 0; arr_i < 6; arr_i++)
{
string[] arr_temp = Console.ReadLine().Split(' ');
arr[arr_i] = Array.ConvertAll(arr_temp, Int32.Parse);
}
int[] sum = new int[6];
List<int> n = new List<int>();
for (int i = 0; i + 2 < arr.Length; i++)
{
for (int j = 0; j + 2 < arr.GetLength(0); j++)
{
sum[j] = arr[i][j] + arr[i][j + 1] + arr[i][j + 2] +
arr[i + 1][j + 1] +
arr[i + 2][j] + arr[i + 2][j + 1] + arr[i + 2][j + 2];
n.Add(sum[j]);
}
}
Console.WriteLine(n.Max());
}
}
}
If I run this program and enter the following as contents of 'arr'
111111
222222
333333
444444
555555
666666
Here I am trying to add 1 + 1 + 1
+ 2 +
3 + 3 + 3
using sum[j] = arr[i][j] + arr[i][j + 1] + arr[i][j + 2] +
arr[i + 1][j + 1] +
arr[i + 2][j] + arr[i + 2][j + 1] + arr[i + 2][j + 2];
but arr[i][j] returns 111111
how can I access 1? is this the right answer to the question on hackerrank?
Hope below code helps you
public class Solution {
private static final int _MAX = 6; // size of matrix
private static final int _OFFSET = 2; // hourglass width
private static int matrix[][] = new int[_MAX][_MAX];
private static int maxHourglass = -63; // initialize to lowest possible sum (-9 x 7)
/** Given a starting index for an hourglass, sets maxHourglass
* #param i row
* #param j column
**/
private static void hourglass(int i, int j){
int tmp = 0; // current hourglass sum
// sum top 3 and bottom 3 elements
for(int k = j; k <= j + _OFFSET; k++){
tmp += matrix[i][k];
tmp += matrix[i + _OFFSET][k];
}
// sum middle element
tmp += matrix[i + 1][j + 1];
if(maxHourglass < tmp){
maxHourglass = tmp;
}
}
public static void main(String[] args) {
// read inputs
Scanner scan = new Scanner(System.in);
for(int i=0; i < _MAX; i++){
for(int j=0; j < _MAX; j++){
matrix[i][j] = scan.nextInt();
}
}
scan.close();
// find maximum hourglass
for(int i=0; i < _MAX - _OFFSET; i++){
for(int j=0; j < _MAX - _OFFSET; j++){
hourglass(i, j);
}
}
// print maximum hourglass
System.out.println(maxHourglass);
}
}

Unexpected Diamond square Algorithm results

I'm currently trying to implement the Diamond Square algorithm and while the thing is somewhat working, I'm confused by the HeightMap.
Here it is :
As you can see the squares are clearly outlined by brighters values, while the losanges are outlined by darker values.
I really cant understand why. I know that the size of the map is really small but I don't think that's the expected result anyway, and I got the same behavior with larger sizes.
Here's my code :
public class TerrainBuilder
{
private Terrain Terrain = null;
private Random r = new Random();
private int espace;
public void Init(Terrain _terrain)
{
Terrain = _terrain;
espace = Terrain.SIZE - 1;
}
public void DiamondAlgoritm()
{
if (Terrain == null)
return;
//Initialization
Terrain.HeightMap[0, 0] = r.Next() % 255;
Terrain.HeightMap[0, Terrain.SIZE - 1] = r.Next() % 255;
Terrain.HeightMap[Terrain.SIZE - 1, 0] = r.Next() % 255;
Terrain.HeightMap[Terrain.SIZE - 1, Terrain.SIZE - 1] = r.Next() % 255;
//randominess
int decalage = 128;
while (espace > 1)
{
int demiSpace = espace / 2;
//diamond phase
for (int i = demiSpace; i < espace; i = i + espace)
{
for (int j = demiSpace; j < espace; j = j + espace)
{
var avg = Terrain.HeightMap[i + demiSpace, j + demiSpace] + Terrain.HeightMap[i + demiSpace, j - demiSpace] + Terrain.HeightMap[i - demiSpace, j + demiSpace] + Terrain.HeightMap[i - demiSpace, j - demiSpace];
avg /= 4;
Terrain.HeightMap[i, j] = Normalize(avg + r.Next() % decalage);
}
}
//carre phase
for (int i = 0; i < Terrain.SIZE; i += demiSpace)
{
int delay = 0;
if (i % espace == 0)
delay = demiSpace;
for (int j = delay; j < Terrain.SIZE; j += espace)
{
double somme = 0;
int n = 0;
if (i >= demiSpace)
somme = somme + Terrain.HeightMap[i - demiSpace, j];
n = n + 1;
if (i + demiSpace < Terrain.SIZE)
somme = somme + Terrain.HeightMap[i + demiSpace, j];
n = n + 1;
if (j >= demiSpace)
somme = somme + Terrain.HeightMap[i, j - demiSpace];
n = n + 1;
if (j + demiSpace < Terrain.SIZE)
somme = somme + Terrain.HeightMap[i, j + demiSpace];
n = n + 1;
Terrain.HeightMap[i, j] = Normalize(somme / n + r.Next() % decalage);
}
}
espace = demiSpace;
}
}
private double Normalize(double value)
{
return Math.Max(Math.Min(value, 255), 0);
}
}
I would like some help to understand this problem.
During the diamond phase, you don't iterate over the whole map. You only calculate the first square (equal to espace).
Change your loop termination conditions like this:
for (int i = demiSpace; i < Terrain.SIZE; i = i + espace)
{
for (int j = demiSpace; j < Terrain.SIZE; j = j + espace)
{
var avg = Terrain.HeightMap[i + demiSpace, j + demiSpace] +
Terrain.HeightMap[i + demiSpace, j - demiSpace] +
Terrain.HeightMap[i - demiSpace, j + demiSpace] +
Terrain.HeightMap[i - demiSpace, j - demiSpace];
avg /= 4;
Terrain.HeightMap[i, j] = Normalize(avg + r.Next() % decalage);
}
}
Also, you never adjust your randomness variable (decalage), which should get smaller as you reduce the size of espace.

Flipping bitmap Function in C#

as a Practice I tried flipping a bitmap with unsafe code and pointers in C#
but the problem is I get the original bitmap as the result instead of flipped bitmap , it seems that the function does nothing at all , so I'm wondering what's wrong in my code !
please keep in mind that I want to flip pictureBox1.Image and set it as pictureBox2.Image
private bool Flip_H()
{
try
{
b = new Bitmap(pictureBox1.Image);
bmdata = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int offset = bmdata.Stride - b.Width * 3;
byte back_up;
int BGRwidth = b.Width * 3;
unsafe
{
byte* p = (byte*)bmdata.Scan0;
for (int y = 0; y < b.Height; y++)
{
for (int x = 0; x < BGRwidth / 2; x += 3)
{
back_up = p[x];
p[x] = p[BGRwidth - x - 3];
p[BGRwidth - x - 1] = back_up;
back_up = p[x + 1];
p[x + 1] = p[BGRwidth - x - 2];
p[BGRwidth - x - 2] = back_up;
back_up = p[x + 2];
p[x + 2] = p[BGRwidth - x - 1];
}
p += offset;
}
}
b.UnlockBits(bmdata);
pictureBox2.Image = b;
return true;
}
catch
{
return false;
}
}
I have already done this with GetPixel() and SetPixel() functions , but as you know they are too slow , so I'm trying to Improve my code with pointers !
the Problem was Offset Parameter ! thanks everyone who helped
Your problem is that you never advanced in the Y direction. You always change the pixels only on the first scanline and therefore the rest does not change. This happens because you do p += offset but you defined offset as:
int offset = bmdata.Stride - b.Width * 3;
You should instead define offset as:
int offset = bmdata.Stride;
Since you want to add the stride width, in bytes, to get to the next scan line.
Also there is a bug in your swapping code. You have:
back_up = p[x + 0];
p[x + 0] = p[BGRwidth - x - 3];
p[BGRwidth - x - 1] = back_up; // Error!
back_up = p[x + 1];
p[x + 1] = p[BGRwidth - x - 2];
p[BGRwidth - x - 2] = back_up;
back_up = p[x + 2];
p[x + 2] = p[BGRwidth - x - 1];
// Missing!
You should have:
back_up = p[x + 0];
p[x + 0] = p[BGRwidth - x - 3];
p[BGRwidth - x - 3] = back_up;
back_up = p[x + 1];
p[x + 1] = p[BGRwidth - x - 2];
p[BGRwidth - x - 2] = back_up;
back_up = p[x + 2];
p[x + 2] = p[BGRwidth - x - 1];
p[BGRwidth - x - 1] = back_up;

MS Charts C# DataSource from array or List

i want to fill the data of the charts from values i have in 2D array, one column will present the X-axis and the second is present the Y-axis.. i did it, but its not reading from the array, it gives me the default line when i run the application, i found a solution using List<>, i had an error, so if any one could help me in this, i will be thankful :D
this is the code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace ICS381Project
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int[,] AndFunction = { { 0, 0, 0 }, { 0, 1, 0 }, { 1, 0, 0 }, { 1, 1, 1 } }; // intialized the function
int[,] D_n = new int[4, 1]; // creating the D(n)
int[,] x_n = new int[4, 3]; // creating X(n) vectors X1 --> x4
int[,] W_n = { { 0, 0, 0 } }; // creating and intiallizing W(n) vectors W1 --> w4
int[,] W_n_1 = { { 0, 0, 0 } };
int[,] Delta_W_n = { { 0, 0, 0 } };
int wx = 0; //
int Y_n = 0; //
int d_y = 0; //
for (int i = 0; i < 4; i++)
{
D_n[i, 0] = AndFunction[i, 2];
}
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
if (j == 2)
x_n[i, j] = 1;
else
x_n[i, j] = AndFunction[i, j];
}
}
int step = 0;
int CheckIfNoLearning = 0;
int RowsPointer = 0;
while (CheckIfNoLearning < 4)
{
//Console.Write("step= " + step+1 + "\n");
wx = (x_n[RowsPointer, 0] * W_n[0, 0]) + (x_n[RowsPointer, 1] * W_n[0, 1]) + (x_n[RowsPointer, 2] * W_n[0, 2]);
//Console.Write("[ " + x_n[RowsPointer, 0] + ", " + x_n[RowsPointer, 1] + ", " + x_n[RowsPointer, 2] + "] \t");
//Console.Write("[ " + W_n[0, 0] + ", " + W_n[0, 1] + ", " + W_n[0, 2] + "] \t");
//Console.Write("" + wx + "\t");
if (wx < 0)
Y_n = 0;
else
Y_n = 1;
// Console.Write("" + Y_n + "\t");
d_y = D_n[RowsPointer, 0] - Y_n;
// Console.Write("" + d_y + "\t");
Delta_W_n[0, 0] = d_y * x_n[RowsPointer, 0];
Delta_W_n[0, 1] = d_y * x_n[RowsPointer, 1];
Delta_W_n[0, 2] = d_y * x_n[RowsPointer, 2];
// Console.Write("[ " + Delta_W_n[0, 0] + ", " + Delta_W_n[0, 1] + ", " + Delta_W_n[0, 2] + "] \t");
for (int i = 0; i < 3; i++)
{
W_n_1[0, i] = W_n[0, i] + Delta_W_n[0, i];
}
//Console.Write("[ " + W_n_1[0, 0] + ", " + W_n_1[0, 1] + ", " + W_n_1[0, 2] + "] \n");
if (W_n_1[0, 0] == W_n[0, 0] && W_n_1[0, 1] == W_n[0, 1] && W_n_1[0, 2] == W_n[0, 2] && CheckIfNoLearning == RowsPointer)
CheckIfNoLearning++;
else
CheckIfNoLearning = 0;
W_n[0, 0] = W_n_1[0, 0];
W_n[0, 1] = W_n_1[0, 1];
W_n[0, 2] = W_n_1[0, 2];
//Console.Write("W_n= [ " + W_n[0, 0] + ", " + W_n[0, 1] + ", " + W_n[0, 2] + "] \n");
RowsPointer = (RowsPointer + 1) % 4;
step++;
}
double[,] equation = {{-10,0},{-9,0},{-8,0},
{-7,0},{-6,0},{-5,0},
{-4,0},{-3,0},{-2,0},
{-1,0},{0,0},{1,0},
{2,0},{3,0},{4,0},
{5,0},{6,0},{7,0},
{8,0},{9,0},{10,0}};
List<XY> xy = new List<XY>();
for (int i = 0; i < 21; i++)
{
equation[i, 1] = (-1 * (W_n_1[0, 1] * equation[i, 0] + W_n_1[0, 2])) / W_n_1[0, 0];
xy.Add(new XY(equation[i,0], equation[i,1]));
}
chart1.DataSource = xy;
chart1.Series[0].XValueMember = "Y";
chart1.Series[0].YValueMembers = "X";
chart1.ChartAreas["ChartArea1"].AxisX.Interval = 1;
chart1.DataBind();
}
}
public class XY
{
private double X;
private double Y;
public double DayOfWeek
{
get { return X; }
set { X = value; }
}
public double Sales
{
get { return Y; }
set { Y = value; }
}
public XY(double X, double Y)
{
this.X = X;
this.Y = Y;
}
}
}
In your XY class, instead of the private fields:
private double X;
private double Y;
use public properties:
public double X { get; private set; }
public double Y { get; private set; }
DataBinding does not work on fields.

Categories

Resources