// 按照 Y 坐标计算出左右两条边纵坐标等于 Y 的顶点 void trapezoid_edge_interp(trapezoid_t *trap, float y) { float s1 = trap->left.v2.pos.y - trap->left.v1.pos.y; float s2 = trap->right.v2.pos.y - trap->right.v1.pos.y; float t1 = (y - trap->left.v1.pos.y) / s1; float t2 = (y - trap->right.v1.pos.y) / s2; vertex_interp(&trap->left.v, &trap->left.v1, &trap->left.v2, t1); vertex_interp(&trap->right.v, &trap->right.v1, &trap->right.v2, t2); }
int polygonise_grid (gridcell_t grid, double isolevel, triangle_t *triangles) { int i, trg_num, cube_idx; vertex_t vertlist[12]; /* Nejprve zjistime index pro urceni vrcholu, ktere tvori povrch. Tento index nam udava umisteni dat v table_edge */ cube_idx = 0; if (grid.val[0] < isolevel) cube_idx |= 1; if (grid.val[1] < isolevel) cube_idx |= 2; if (grid.val[2] < isolevel) cube_idx |= 4; if (grid.val[3] < isolevel) cube_idx |= 8; if (grid.val[4] < isolevel) cube_idx |= 16; if (grid.val[5] < isolevel) cube_idx |= 32; if (grid.val[6] < isolevel) cube_idx |= 64; if (grid.val[7] < isolevel) cube_idx |= 128; /* Krychle je mimo sledovany povrch */ if (!table_edge[cube_idx]) return 0; /* Zjistime jednotlive vrcholy kde se povrch proti s krychli */ if (table_edge[cube_idx] & 1) vertlist[0] = vertex_interp (isolevel, grid.p[0], grid.p[1], grid.val[0], grid.val[1]); if (table_edge[cube_idx] & 2) vertlist[1] = vertex_interp (isolevel, grid.p[1], grid.p[2], grid.val[1], grid.val[2]); if (table_edge[cube_idx] & 4) vertlist[2] = vertex_interp (isolevel, grid.p[2], grid.p[3], grid.val[2], grid.val[3]); if (table_edge[cube_idx] & 8) vertlist[3] = vertex_interp (isolevel, grid.p[3], grid.p[0], grid.val[3], grid.val[0]); if (table_edge[cube_idx] & 16) vertlist[4] = vertex_interp (isolevel, grid.p[4], grid.p[5], grid.val[4], grid.val[5]); if (table_edge[cube_idx] & 32) vertlist[5] = vertex_interp (isolevel, grid.p[5], grid.p[6], grid.val[5], grid.val[6]); if (table_edge[cube_idx] & 64) vertlist[6] = vertex_interp (isolevel, grid.p[6], grid.p[7], grid.val[6], grid.val[7]); if (table_edge[cube_idx] & 128) vertlist[7] = vertex_interp (isolevel, grid.p[7], grid.p[4], grid.val[7], grid.val[4]); if (table_edge[cube_idx] & 256) vertlist[8] = vertex_interp (isolevel, grid.p[0], grid.p[4], grid.val[0], grid.val[4]); if (table_edge[cube_idx] & 512) vertlist[9] = vertex_interp (isolevel, grid.p[1], grid.p[5], grid.val[1], grid.val[5]); if (table_edge[cube_idx] & 1024) vertlist[10] = vertex_interp (isolevel, grid.p[2], grid.p[6], grid.val[2], grid.val[6]); if (table_edge[cube_idx] & 2048) vertlist[11] = vertex_interp (isolevel, grid.p[3], grid.p[7], grid.val[3], grid.val[7]); /* vytvorime pole trojuhelniku, ktere se maji vykreslit */ trg_num = 0; for (i = 0; table_trg[cube_idx][i] != -1; i += 3) { triangles[trg_num].p[0] = vertlist[table_trg[cube_idx][i]]; triangles[trg_num].p[1] = vertlist[table_trg[cube_idx][i+1]]; triangles[trg_num].p[2] = vertlist[table_trg[cube_idx][i+2]]; trg_num ++; } return trg_num; // vrati pocet pouzitelnych trojuhelniku v poli (max. 5) }
void gen_marching_cubes(UVoxelMesh* vmesh, TArray<FGeneratedMeshTriangle>* tris) { int tri_index = 0; for (int z = -1; z < vmesh->get_sizez() - 1; ++z) { for (int y = -1; y < vmesh->get_sizey() - 1; ++y) { for (int x = -1; x < vmesh->get_sizex() - 1; ++x) { //if (x <= 0 || y <= 0 || z <= 0 || // x >= vmesh->get_sizex() - 1 || y >= vmesh->get_sizey() - 1 || z >= vmesh->get_sizez() - 1) continue; #define IS_NODE_AIR(x, y, z) (vmesh->get_node(x, y, z) != NULL && vmesh->get_node(x, y, z)->type == BLOCK_TYPE_AIR) bool corner0 = !IS_NODE_AIR(x + 1, y, z + 1); bool corner1 = !IS_NODE_AIR(x + 1, y + 1, z + 1); bool corner2 = !IS_NODE_AIR(x, y + 1, z + 1); bool corner3 = !IS_NODE_AIR(x, y, z + 1); bool corner4 = !IS_NODE_AIR(x + 1, y, z); bool corner5 = !IS_NODE_AIR(x + 1, y + 1, z); bool corner6 = !IS_NODE_AIR(x, y + 1, z); bool corner7 = !IS_NODE_AIR(x, y, z); FVector vert_list[12]; float iso_level = 1; int cube_index = 0; if (corner0) cube_index |= 1; if (corner1) cube_index |= 2; if (corner2) cube_index |= 4; if (corner3) cube_index |= 8; if (corner4) cube_index |= 16; if (corner5) cube_index |= 32; if (corner6) cube_index |= 64; if (corner7) cube_index |= 128; /* Cube is entirely in/out of the surface */ if (edge_table[cube_index] == 0) continue; /* Find the vertices where the surface intersects the cube */ if (edge_table[cube_index] & 1) vert_list[0] = vertex_interp(corner_points[0], corner_points[1], corner0, corner1); if (edge_table[cube_index] & 2) vert_list[1] = vertex_interp(corner_points[1], corner_points[2], corner1, corner2); if (edge_table[cube_index] & 4) vert_list[2] = vertex_interp(corner_points[2], corner_points[3], corner2, corner3); if (edge_table[cube_index] & 8) vert_list[3] = vertex_interp(corner_points[3], corner_points[0], corner3, corner0); if (edge_table[cube_index] & 16) vert_list[4] = vertex_interp(corner_points[4], corner_points[5], corner4, corner5); if (edge_table[cube_index] & 32) vert_list[5] = vertex_interp(corner_points[5], corner_points[6], corner5, corner6); if (edge_table[cube_index] & 64) vert_list[6] = vertex_interp(corner_points[6], corner_points[7], corner6, corner7); if (edge_table[cube_index] & 128) vert_list[7] = vertex_interp(corner_points[7], corner_points[4], corner7, corner4); if (edge_table[cube_index] & 256) vert_list[8] = vertex_interp(corner_points[0], corner_points[4], corner0, corner4); if (edge_table[cube_index] & 512) vert_list[9] = vertex_interp(corner_points[1], corner_points[5], corner1, corner5); if (edge_table[cube_index] & 1024) vert_list[10] = vertex_interp(corner_points[2], corner_points[6], corner2, corner6); if (edge_table[cube_index] & 2048) vert_list[11] = vertex_interp(corner_points[3], corner_points[7], corner3, corner7); FVector world_offset(x * 100.0f, y * 100.0f, z * 100.0f); for (int i = 0; tri_table[cube_index][i] != -1; i += 3) { // add new triangle if tri index goes over length if (tri_index >= tris->Num()) tris->Add(FGeneratedMeshTriangle()); //get triangle from tri index FGeneratedMeshTriangle& tri = (*tris)[tri_index]; const int NUM_TILESX = 3; const int NUM_TILESY = 1; const float TILE_SIZEX = 1.0f / NUM_TILESX; const float TILE_SIZEY = 1.0f / NUM_TILESY; float offsetx = 0, offsety = 0; FNode* node = vmesh->get_node(x <= 0 ? 1 : x, y <= 0 ? 1 : y, z <= 0 ? 1 : z); if (!node) continue; node->tri = &tri; ++tri_index; BlockType type = node->type; if (type == BLOCK_TYPE_GRID) offsetx = 0; else if (type == BLOCK_TYPE_SELECTED) offsetx = TILE_SIZEX; FVector v0 = vert_list[tri_table[cube_index][i]]; FVector v1 = vert_list[tri_table[cube_index][i + 1]]; FVector v2 = vert_list[tri_table[cube_index][i + 2]]; tri.v2.pos = (v0 * 100.0f) + world_offset; tri.v1.pos = (v1 * 100.0f) + world_offset; tri.v0.pos = (v2 * 100.0f) + world_offset; FVector2D uv(offsetx, offsety); tri.v2.uv = uv; tri.v1.uv = uv; tri.v0.uv = uv; tri.v2.colour = FColor(255, 0, 0); tri.v1.colour = FColor(255, 0, 0); tri.v0.colour = FColor(255, 0, 0); } } } } }
void AWorldSpawn::gen_chunk() { if (hex_asset) { for (int z = 0; z < SIZEZ; ++z) { for (int y = 0; y < SIZEY; ++y) { for (int x = 0; x < SIZEX; ++x) { Hex* hex = new Hex(); hex->x = x; hex->y = y; hex->z = z; hex_list.push_back(hex); gen_hex(x, y, z); } } } for (int z = -1; z < SIZEZ; ++z) { for (int y = -1; y < SIZEY; ++y) { for (int x = -1; x < SIZEX; ++x) { bool corner0 = (get_hex(x + 1, y, z + 1) != NULL && get_hex(x + 1, y, z + 1)->type != BLOCK_TYPE_AIR); bool corner1 = (get_hex(x + 1, y + 1, z + 1) != NULL && get_hex(x + 1, y + 1, z + 1)->type != BLOCK_TYPE_AIR); bool corner2 = (get_hex(x, y + 1, z + 1) != NULL && get_hex(x, y + 1, z + 1)->type != BLOCK_TYPE_AIR); bool corner3 = (get_hex(x, y, z + 1) != NULL && get_hex(x, y, z + 1)->type != BLOCK_TYPE_AIR); bool corner4 = (get_hex(x + 1, y, z) != NULL && get_hex(x + 1, y, z)->type != BLOCK_TYPE_AIR); bool corner5 = (get_hex(x + 1, y + 1, z) != NULL && get_hex(x + 1, y + 1, z)->type != BLOCK_TYPE_AIR); bool corner6 = (get_hex(x, y + 1, z) != NULL && get_hex(x, y + 1, z)->type != BLOCK_TYPE_AIR); bool corner7 = (get_hex(x, y, z) != NULL && get_hex(x, y, z)->type != BLOCK_TYPE_AIR); //UE_LOG(LogTemp, Warning, TEXT("(%d, %d, %d): %d, %d, %d, %d, %d, %d, %d, %d"), x, y, z, corner0, corner1, corner2, corner3, corner4, corner5, corner6, corner7); FVector vertlist[12]; //bool isolevel = corner0 && corner1 && corner2 && corner3 && corner4 && corner5 && corner6 && corner7; //isolevel = false; float isolevel = 1; int cubeindex = 0; if (corner0) cubeindex |= 1; if (corner1) cubeindex |= 2; if (corner2) cubeindex |= 4; if (corner3) cubeindex |= 8; if (corner4) cubeindex |= 16; if (corner5) cubeindex |= 32; if (corner6) cubeindex |= 64; if (corner7) cubeindex |= 128; //UE_LOG(LogTemp, Warning, TEXT("%d, %d"), cubeindex, isolevel); /* Cube is entirely in/out of the surface */ if (edgeTable[cubeindex] == 0) continue; /* Find the vertices where the surface intersects the cube */ if (edgeTable[cubeindex] & 1) vertlist[0] = vertex_interp(corner_points[0], corner_points[1], corner0, corner1); if (edgeTable[cubeindex] & 2) vertlist[1] = vertex_interp(corner_points[1], corner_points[2], corner1, corner2); if (edgeTable[cubeindex] & 4) vertlist[2] = vertex_interp(corner_points[2], corner_points[3], corner2, corner3); if (edgeTable[cubeindex] & 8) vertlist[3] = vertex_interp(corner_points[3], corner_points[0], corner3, corner0); if (edgeTable[cubeindex] & 16) vertlist[4] = vertex_interp(corner_points[4], corner_points[5], corner4, corner5); if (edgeTable[cubeindex] & 32) vertlist[5] = vertex_interp(corner_points[5], corner_points[6], corner5, corner6); if (edgeTable[cubeindex] & 64) vertlist[6] = vertex_interp(corner_points[6], corner_points[7], corner6, corner7); if (edgeTable[cubeindex] & 128) vertlist[7] = vertex_interp(corner_points[7], corner_points[4], corner7, corner4); if (edgeTable[cubeindex] & 256) vertlist[8] = vertex_interp(corner_points[0], corner_points[4], corner0, corner4); if (edgeTable[cubeindex] & 512) vertlist[9] = vertex_interp(corner_points[1], corner_points[5], corner1, corner5); if (edgeTable[cubeindex] & 1024) vertlist[10] = vertex_interp(corner_points[2], corner_points[6], corner2, corner6); if (edgeTable[cubeindex] & 2048) vertlist[11] = vertex_interp(corner_points[3], corner_points[7], corner3, corner7); /* Create the triangle */ int ntriang = 0; FGeneratedMeshTriangle tri; for (int i = 0; triTable[cubeindex][i] != -1; i += 3) { tri.set_vertex(vertlist[triTable[cubeindex][i]] * 100.0f, 2); tri.set_vertex(vertlist[triTable[cubeindex][i + 1]] * 100.0f, 1); tri.set_vertex(vertlist[triTable[cubeindex][i + 2]] * 100.0f, 0); tri.Vertex0.X += x * 100.0f; tri.Vertex1.X += x * 100.0f; tri.Vertex2.X += x * 100.0f; tri.Vertex0.Y += y * 100.0f; tri.Vertex1.Y += y * 100.0f; tri.Vertex2.Y += y * 100.0f; tri.Vertex0.Z += z * 100.0f; tri.Vertex1.Z += z * 100.0f; tri.Vertex2.Z += z * 100.0f; chunk_triangles.Add(tri); //UE_LOG(LogTemp, Warning, TEXT("--tri--")); //UE_LOG(LogTemp, Warning, TEXT("%f, %f, %f"), tri.Vertex0.X, tri.Vertex0.Y, tri.Vertex0.Z); //UE_LOG(LogTemp, Warning, TEXT("%f, %f, %f"), tri.Vertex1.X, tri.Vertex1.Y, tri.Vertex1.Z); //UE_LOG(LogTemp, Warning, TEXT("%f, %f, %f"), tri.Vertex2.X, tri.Vertex2.Y, tri.Vertex2.Z); ntriang++; } } } } custom_mesh = NewObject<UGeneratedMeshComponent>(this); custom_mesh->RegisterComponent(); custom_mesh->SetGeneratedMeshTriangles(chunk_triangles); custom_mesh->SetMaterial(0, water_mat_asset); UE_LOG(LogTemp, Warning, TEXT("spawned")); }else { UE_LOG(LogTemp, Warning, TEXT("Could not find hexagon asset")); } }