C#でコピーを作成せずに配列のサイズを変更する方法はありますか?私が特に探しているのは、配列のLengthプロパティを変更する方法です。配列の長さは固定されており、最大サイズ以下のサイズにリサイズされます(配列の再利用が可能です)。C#で配列が縮む
実際のユースケースはUnity3Dの手続きメッシュ生成です。これを行うビルトインの方法は、リスト(非常に遅い)を使用し、Vector3sの配列をmesh.verticesなどに割り当てることに限定されています。配列の割り当て方法は私が望むものですが、配列をmesh.verticesに割り当てるときにコピーする配列要素の数を指定する方法はありません(mesh.verticesは配列ではなく、割り当てられた配列をGPUにコピーします) 。
手順的に生成されたメッシュ内の頂点の数があらかじめ不明な場合、適切なサイズの配列を作成することは不可能であり、低速な配列のサイズ変更に頼る必要があります。
私はC#は通常、私は探している配列の種類の種類を許可していないが知っているが、半分まともな低レベルのhackish方法はまだそれを行うために尋ねる必要があります。
私が使用している方法は、最大数の頂点(生成された各メッシュに対して単純に再利用される)の配列を割り当て、それを塗りつぶしてから、適切なサイズの別の配列を割り当てて、新しい配列への配列要素の数(これはArray.Resizeよりも速く、リストを使用するものより確かに高速です)。
編集:要求されたとおり適切なコードで更新されました(十分に文書化されていない、注意してください)。
これは、各チャンク(テストコード)のマップジェネレータを呼び出し:
for (int z = 0; z < size; z++)
{
for (int x = 0; x < size; x++)
{
Vector3 position = new Vector3(x * 32, 0, z * 32);
GameObject a = Instantiate(baseObject);
a.transform.position = position;
map.GenMap(position, model); // procedural model generation
blockMesh.SetModel(model); // set the model to generate the mesh from
blockMesh.GenMesh(); // generate actual mesh
blockMesh.CopyMesh(a.GetComponent<MeshFilter>().mesh); // copy mesh data do the Unity mesh
}
}
簡単なテストマップ生成:
public void GenMap(Vector3 position, Model map)
{
map.Clear();
double par1 = 1000;
double par2 = 600;
double par3 = 500;
double par4 = 1.0/50.0;
double par5 = 1.0/25.0;
double par6 = 1.0/12.5;
double factor = (par1 + par2 + par3)/16;
if (factor != 0.0)
{
par1 /= factor;
par2 /= factor;
par3 /= factor;
}
Color32 color150 = map.palette[150];
for (int z = 0; z < map.realDepth; z++)
{
double zPos = position.z + z;
for (int x = 0; x < map.realWidth; x++)
{
double xPos = position.x + x;
int e = 16 + (int)
(
(noise.Noise(xPos * par4, zPos * par4) * par1) +
(noise.Noise(xPos * par5, zPos * par5) * par2) +
(noise.Noise(xPos * par6, zPos * par6) * par3)
);
for (int y = 0; y < map.realHeight; y++)
{
if (y <= e)
{
int a = (255 - (32 - y) * 9);
if (a < 1)
a = 1;
color150.a = (byte)(a | 1);
map.voxel[x][y][z] = color150;
}
}
}
}
}
これは実際のメッシュ生成コードである(モノ3.5に最適化しませんウェル)今、文書化:ずっと私はuのを偶然見つけグーグル後
using UnityEngine;
using System;
public class BlockMesh
{
public Vector3[] vertices = new Vector3[65532];
public Vector3[] normals = new Vector3[65532];
public Vector2[] uvs = new Vector2[65532];
public Color32[] colors = new Color32[65532];
public int[] triangles = new int[65532 * 6/4];
public int index = 0;
public Model model;
// set model and init arrays
public void SetModel(Model model)
{
this.model = model;
}
// copy mesh data to mesh
public void CopyMesh(Mesh mesh)
{
Vector3[] a = new Vector3[index * 4];
Array.Copy(vertices, a, index * 4);
mesh.vertices = a;
Array.Copy(normals, a, index * 4);
mesh.normals = a;
Color32[] b = new Color32[index * 4];
Array.Copy(colors, b, index * 4);
mesh.colors32 = b;
int[] c = new int[index * 6];
Array.Copy(triangles, c, index * 6);
mesh.triangles = c;
Vector2[] d = new Vector2[index * 4];
Array.Copy(uvs, d, index * 4);
mesh.uv = d;
}
// ambient occlusion uv constants
private const float pixelSize = 1.0f/4096.0f;
private const float tileSize = pixelSize * 256;
private const float adjust1 = pixelSize * 64;
private const float adjust2 = tileSize - 2 * adjust1;
// cube faces
private Vector3[] faceVertices1 = { new Vector3(0, 1, 0), new Vector3(0, 0, 0), new Vector3(0, 0, 0), new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(1, 0, 1) };
private Vector3[] faceVertices2 = { new Vector3(1, 1, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 1), new Vector3(0, 0, 0), new Vector3(1, 0, 0) };
private Vector3[] faceVertices3 = { new Vector3(0, 1, 1), new Vector3(0, 0, 1), new Vector3(0, 1, 0), new Vector3(0, 1, 1), new Vector3(0, 1, 1), new Vector3(1, 1, 1) };
private Vector3[] faceVertices4 = { new Vector3(1, 1, 1), new Vector3(1, 0, 1), new Vector3(1, 1, 0), new Vector3(1, 1, 1), new Vector3(0, 1, 0), new Vector3(1, 1, 0) };
private Vector3[] faceNormals = { Vector3.up, Vector3.down, Vector3.back, Vector3.forward, Vector3.left, Vector3.right };
private void AddFace(int side, Vector3 position, Color32 color, int aop)
{
// mesh array indices
int index4 = index * 4;
int index6 = index * 6;
// ambient occlusion uv cords
float x1 = tileSize * (aop & 15) + adjust1;
float y1 = tileSize * (aop >> 4) + adjust1;
float x2 = x1 + adjust2;
float y2 = y1 + adjust2;
// put face into mesh
vertices[index4 + 0] = position + faceVertices1[side];
vertices[index4 + 1] = position + faceVertices2[side];
vertices[index4 + 2] = position + faceVertices3[side];
vertices[index4 + 3] = position + faceVertices4[side];
uvs[index4 + 0].x = x1;
uvs[index4 + 0].y = y1;
uvs[index4 + 1].x = x2;
uvs[index4 + 1].y = y1;
uvs[index4 + 2].x = x1;
uvs[index4 + 2].y = y2;
uvs[index4 + 3].x = x2;
uvs[index4 + 3].y = y2;
normals[index4 + 0] = faceNormals[side];
normals[index4 + 1] = faceNormals[side];
normals[index4 + 2] = faceNormals[side];
normals[index4 + 3] = faceNormals[side];
colors[index4 + 0] = color;
colors[index4 + 1] = color;
colors[index4 + 2] = color;
colors[index4 + 3] = color;
int tri = 0x08790936 >> ((side & 1) << 4);
triangles[index6 + 0] = index4 + ((tri >> 10) & 3);
triangles[index6 + 1] = index4 + ((tri >> 08) & 3);
triangles[index6 + 2] = index4 + ((tri >> 06) & 3);
triangles[index6 + 3] = index4 + ((tri >> 04) & 3);
triangles[index6 + 4] = index4 + ((tri >> 02) & 3);
triangles[index6 + 5] = index4 + (tri & 3);
index += 1;
}
// build mesh
public void GenMesh()
{
index = 0;
for (int z = 1; z <= model.depth; z++)
{
for (int y = 1; y <= model.height; y++)
{
for (int x = 1; x <= model.width; x++)
{
Color32 voxelColor = model.voxel[x][y][z];
if (voxelColor.a == 0)
continue;
if (model.voxel[x][y + 1][z].a == 0) // top
{
AddFace(0, new Vector3(x, y, z), voxelColor,
(((model.voxel[x - 1][y + 1][z - 1].a) & 1) << 7) |
(((model.voxel[x + 0][y + 1][z - 1].a) & 1) << 6) |
(((model.voxel[x + 1][y + 1][z - 1].a) & 1) << 5) |
(((model.voxel[x - 1][y + 1][z + 0].a) & 1) << 4) |
(((model.voxel[x + 1][y + 1][z + 0].a) & 1) << 3) |
(((model.voxel[x - 1][y + 1][z + 1].a) & 1) << 2) |
(((model.voxel[x + 0][y + 1][z + 1].a) & 1) << 1) |
(((model.voxel[x + 1][y + 1][z + 1].a) & 1)));
}
if (model.voxel[x][y - 1][z].a == 0) // bottom
{
AddFace(1, new Vector3(x, y, z), voxelColor,
(((model.voxel[x - 1][y - 1][z - 1].a) & 1) << 7) |
(((model.voxel[x + 0][y - 1][z - 1].a) & 1) << 6) |
(((model.voxel[x + 1][y - 1][z - 1].a) & 1) << 5) |
(((model.voxel[x - 1][y - 1][z + 0].a) & 1) << 4) |
(((model.voxel[x + 1][y - 1][z + 0].a) & 1) << 3) |
(((model.voxel[x - 1][y - 1][z + 1].a) & 1) << 2) |
(((model.voxel[x + 0][y - 1][z + 1].a) & 1) << 1) |
(((model.voxel[x + 1][y - 1][z + 1].a) & 1)));
}
if (model.voxel[x][y][z - 1].a == 0) // back
{
AddFace(2, new Vector3(x, y, z), voxelColor,
(((model.voxel[x - 1][y - 1][z - 1].a) & 1) << 7) |
(((model.voxel[x + 0][y - 1][z - 1].a) & 1) << 6) |
(((model.voxel[x + 1][y - 1][z - 1].a) & 1) << 5) |
(((model.voxel[x - 1][y + 0][z - 1].a) & 1) << 4) |
(((model.voxel[x + 1][y + 0][z - 1].a) & 1) << 3) |
(((model.voxel[x - 1][y + 1][z - 1].a) & 1) << 2) |
(((model.voxel[x + 0][y + 1][z - 1].a) & 1) << 1) |
(((model.voxel[x + 1][y + 1][z - 1].a) & 1)));
}
if (model.voxel[x][y][z + 1].a == 0) // front
{
AddFace(3, new Vector3(x, y, z), voxelColor,
(((model.voxel[x - 1][y - 1][z + 1].a) & 1) << 7) |
(((model.voxel[x + 0][y - 1][z + 1].a) & 1) << 6) |
(((model.voxel[x + 1][y - 1][z + 1].a) & 1) << 5) |
(((model.voxel[x - 1][y + 0][z + 1].a) & 1) << 4) |
(((model.voxel[x + 1][y + 0][z + 1].a) & 1) << 3) |
(((model.voxel[x - 1][y + 1][z + 1].a) & 1) << 2) |
(((model.voxel[x + 0][y + 1][z + 1].a) & 1) << 1) |
(((model.voxel[x + 1][y + 1][z + 1].a) & 1)));
}
if (model.voxel[x - 1][y][z].a == 0) // left
{
AddFace(4, new Vector3(x, y, z), voxelColor,
(((model.voxel[x - 1][y - 1][z + 1].a) & 1) << 7) |
(((model.voxel[x - 1][y - 1][z + 0].a) & 1) << 6) |
(((model.voxel[x - 1][y - 1][z - 1].a) & 1) << 5) |
(((model.voxel[x - 1][y + 0][z + 1].a) & 1) << 4) |
(((model.voxel[x - 1][y + 0][z - 1].a) & 1) << 3) |
(((model.voxel[x - 1][y + 1][z + 1].a) & 1) << 2) |
(((model.voxel[x - 1][y + 1][z + 0].a) & 1) << 1) |
(((model.voxel[x - 1][y + 1][z - 1].a) & 1)));
}
if (model.voxel[x + 1][y][z].a == 0) // right
{
AddFace(5, new Vector3(x, y, z), voxelColor,
(((model.voxel[x + 1][y - 1][z + 1].a) & 1) << 7) |
(((model.voxel[x + 1][y - 1][z + 0].a) & 1) << 6) |
(((model.voxel[x + 1][y - 1][z - 1].a) & 1) << 5) |
(((model.voxel[x + 1][y + 0][z + 1].a) & 1) << 4) |
(((model.voxel[x + 1][y + 0][z - 1].a) & 1) << 3) |
(((model.voxel[x + 1][y + 1][z + 1].a) & 1) << 2) |
(((model.voxel[x + 1][y + 1][z + 0].a) & 1) << 1) |
(((model.voxel[x + 1][y + 1][z - 1].a) & 1)));
}
}
}
}
}
}
配列を含むReducableArrayクラスと、配列のサイズまでのint長を実装し、長さまでの配列の最初の部分のみを使用する方法はありますか? –
@YairHalberstadt yea、彼はそれを 'List'と呼ぶことができました! –
はい、しかし、リストが遅すぎると言いました@ScottChamberlain –