我一直在关注 this 文章,该文章创建了一个二十面体并将其细分为一个 icosphere 以用于我正在制作的游戏,我决定尝试从 C# 移植到 C。但是当我完成所有代码的移植后,我遇到了这个错误
Process returned -1073741795 (0xC000001D) execution time : 8.057 s Press any key to continue.
,在使用 print 语句和 gdb 帮助处理了几个小时后,我似乎无法修复该错误。这是我的代码的相关片段
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct Point3D
{
double x;
double y;
double z;
} point3D;
typedef struct Triangleindices
{
int v1;
int v2;
int v3;
} triangles;
typedef struct MeshGeometry3D
{
point3D *positions;
int *triangle_indices;
} mesh_geometry;
typedef struct IcosphereCreator
{
mesh_geometry geometry;
int index;
int *cache;
} icosphere;
int add_vertex(icosphere* creator, point3D p)
{
double length = sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
creator->geometry.positions[creator->index].x = p.x / length;
creator->geometry.positions[creator->index].y = p.y / length;
creator->geometry.positions[creator->index].z = p.z / length;
return creator->index++;
}
int get_middle_point(icosphere* creator, int p1, int p2)
{
bool first_is_smaller = p1 < p2;
int64_t smaller_index = first_is_smaller ? p1 : p2;
int64_t greater_index = first_is_smaller ? p2 : p1;
int64_t key = (smaller_index << 32) + greater_index;
if (creator->cache[key] != 0)
{
return creator->cache[key];
}
point3D point1 = creator->geometry.positions[p1];
point3D point2 = creator->geometry.positions[p2];
point3D middle;
middle.x = (point1.x + point2.x) / 2.0;
middle.y = (point1.y + point2.y) / 2.0;
middle.z = (point1.z + point2.z) / 2.0;
int i = add_vertex(creator, middle);
return i;
}
mesh_geometry create_icosphere(icosphere* creator, int subdivide)
{
int max_triangles = 20 * (1 << (2 * subdivide));
long long unsigned int array_size = max_triangles * sizeof(triangles);
creator->geometry = (mesh_geometry){0};
mesh_geometry result = (mesh_geometry){0};
creator->index = 0;
point3D p1 = {-1, (1.0 + sqrt(5.0)) / 2.0, 0};
point3D p2 = {1, (1.0 + sqrt(5.0)) / 2.0, 0};
point3D p3 = {-1, -(1.0 + sqrt(5.0)) / 2.0, 0};
point3D p4 = {1, -(1.0 + sqrt(5.0)) / 2.0, 0};
point3D p5 = {0, -1, (1.0 + sqrt(5.0)) / 2.0};
point3D p6 = {0, 1, (1.0 + sqrt(5.0)) / 2.0};
point3D p7 = {0, -1, -(1.0 + sqrt(5.0)) / 2.0};
point3D p8 = {0, 1, -(1.0 + sqrt(5.0)) / 2.0};
point3D p9 = {(1.0 + sqrt(5.0)) / 2.0, 0, -1};
point3D p10 = {(1.0 + sqrt(5.0)) / 2.0, 0, 1};
point3D p11 = {(1.0 + sqrt(5.0)) / 2.0, 0 -1};
point3D p12 = {(1.0 + sqrt(5.0)) / 2.0, 0, 1};
add_vertex(creator, p1);
add_vertex(creator, p2);
add_vertex(creator, p3);
add_vertex(creator, p4);
add_vertex(creator, p5);
add_vertex(creator, p6);
add_vertex(creator, p7);
add_vertex(creator, p8);
add_vertex(creator, p9);
add_vertex(creator, p10);
add_vertex(creator, p11);
add_vertex(creator, p12);
triangles faces[] =
{
{0, 11, 5},
{0, 5, 1},
{0, 1, 7},
{0, 7, 10},
{0, 10, 11},
{1, 5, 9},
{5, 11, 4},
{11, 10, 2},
{10, 7, 6},
{7, 1, 8},
{3, 9, 4},
{3, 4, 2},
{3, 2, 6},
{3, 6, 8},
{3, 8, 9},
{4, 9, 5},
{2, 4, 11},
{6, 2, 10},
{8, 6, 7},
{9, 8, 1}
};
for (int i = 0; i < subdivide; i++)
{
triangles new_faces[array_size];
int new_faces_index = 0;
for (int j = 0; j < 20; j++)
{
triangles tri = faces[j];
int a = get_middle_point(creator, tri.v1, tri.v2);
int b = get_middle_point(creator, tri.v2, tri.v3);
int c = get_middle_point(creator, tri.v3, tri.v1);
new_faces[new_faces_index++] = (triangles){tri.v1, a, c};
new_faces[new_faces_index++] = (triangles){tri.v2, b, a};
new_faces[new_faces_index++] = (triangles){tri.v3, c, b};
new_faces[new_faces_index++] = (triangles){a, b, c};
}
for (int j = 0; j < new_faces_index; j++)
{
faces[j] = new_faces[j];
}
for (int i = 0; i < 20; i++)
{
triangles tri = faces[i];
result.triangle_indices[i * 3] = tri.v1;
result.triangle_indices[i * 3 + 1] = tri.v2;
result.triangle_indices[i * 3 + 2] = tri.v3;
}
}
return result;
}
int main(void)
{
icosphere creator;
creator.index = -1;
int subdivision_level = 3;
creator.geometry = create_icosphere(&creator, subdivision_level);
for (int i = 0; i < creator.index; i++)
{
printf("Vertex %d: (%f, %f, %f)\n", i, creator.geometry.positions[i].x, creator.geometry.positions[i].y, creator.geometry.positions[i].z);
}
for (int i = 0; i < creator.index; i += 3)
{
printf("Triangle %d: %d, %d, %d\n", i / 3, creator.geometry.triangle_indices[i], creator.geometry.triangle_indices[i + 1], creator.geometry.triangle_indices[i + 2]);
}
int count = creator.geometry.triangle_indices;
return 0;
}
您应该注意到您链接的页面上的代码中广泛使用了 C# 中的
new
关键字。它为那些正在创建的东西分配内存。您的代码中没有 new
,因为 C 没有。您需要使用 malloc()
从 stdlib.h
分配内存。 (后来 free()
释放资源,因为 C 没有像 C# 那样的垃圾收集器。)
positions
、cache
和triangle_indices
是您从未在代码中设置的指针。这些指针需要设置为 malloc()
将返回的大小适当的内存块,以覆盖您将在这些指针上使用的所有索引值。