forked from bartvdbraak/blender
Cycles: speed up mesh volume bounds construction.
Patch by Stefan, with minor tweaks by Brecht.
This commit is contained in:
parent
bcefb202a2
commit
b747524144
@ -87,23 +87,31 @@ const float3 quads_normals[6] = {
|
|||||||
make_float3(0.0f, 0.0f, 1.0f),
|
make_float3(0.0f, 0.0f, 1.0f),
|
||||||
};
|
};
|
||||||
|
|
||||||
static void create_quad(int3 corners[8], vector<int3> &vertices, vector<QuadData> &quads, int face_index)
|
static int add_vertex(int3 v, vector<int3> &vertices, int3 res, unordered_map<size_t, int> &used_verts)
|
||||||
{
|
{
|
||||||
size_t vertex_offset = vertices.size();
|
size_t vert_key = v.x + v.y * (res.x+1) + v.z * (res.x+1)*(res.y+1);
|
||||||
|
unordered_map<size_t, int>::iterator it = used_verts.find(vert_key);
|
||||||
|
|
||||||
|
if(it != used_verts.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vertex_offset = vertices.size();
|
||||||
|
used_verts[vert_key] = vertex_offset;
|
||||||
|
vertices.push_back(v);
|
||||||
|
return vertex_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void create_quad(int3 corners[8], vector<int3> &vertices, vector<QuadData> &quads, int3 res, unordered_map<size_t, int> &used_verts, int face_index)
|
||||||
|
{
|
||||||
QuadData quad;
|
QuadData quad;
|
||||||
quad.v0 = vertex_offset + 0;
|
quad.v0 = add_vertex(corners[quads_indices[face_index][0]], vertices, res, used_verts);
|
||||||
quad.v1 = vertex_offset + 1;
|
quad.v1 = add_vertex(corners[quads_indices[face_index][1]], vertices, res, used_verts);
|
||||||
quad.v2 = vertex_offset + 2;
|
quad.v2 = add_vertex(corners[quads_indices[face_index][2]], vertices, res, used_verts);
|
||||||
quad.v3 = vertex_offset + 3;
|
quad.v3 = add_vertex(corners[quads_indices[face_index][3]], vertices, res, used_verts);
|
||||||
quad.normal = quads_normals[face_index];
|
quad.normal = quads_normals[face_index];
|
||||||
|
|
||||||
quads.push_back(quad);
|
quads.push_back(quad);
|
||||||
|
|
||||||
vertices.push_back(corners[quads_indices[face_index][0]]);
|
|
||||||
vertices.push_back(corners[quads_indices[face_index][1]]);
|
|
||||||
vertices.push_back(corners[quads_indices[face_index][2]]);
|
|
||||||
vertices.push_back(corners[quads_indices[face_index][3]]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VolumeParams {
|
struct VolumeParams {
|
||||||
@ -159,9 +167,6 @@ private:
|
|||||||
void generate_vertices_and_quads(vector<int3> &vertices_is,
|
void generate_vertices_and_quads(vector<int3> &vertices_is,
|
||||||
vector<QuadData> &quads);
|
vector<QuadData> &quads);
|
||||||
|
|
||||||
void deduplicate_vertices(vector<int3> &vertices,
|
|
||||||
vector<QuadData> &quads);
|
|
||||||
|
|
||||||
void convert_object_space(const vector<int3> &vertices,
|
void convert_object_space(const vector<int3> &vertices,
|
||||||
vector<float3> &out_vertices);
|
vector<float3> &out_vertices);
|
||||||
|
|
||||||
@ -234,8 +239,6 @@ void VolumeMeshBuilder::create_mesh(vector<float3> &vertices,
|
|||||||
|
|
||||||
generate_vertices_and_quads(vertices_is, quads);
|
generate_vertices_and_quads(vertices_is, quads);
|
||||||
|
|
||||||
deduplicate_vertices(vertices_is, quads);
|
|
||||||
|
|
||||||
convert_object_space(vertices_is, vertices);
|
convert_object_space(vertices_is, vertices);
|
||||||
|
|
||||||
convert_quads_to_tris(quads, indices, face_normals);
|
convert_quads_to_tris(quads, indices, face_normals);
|
||||||
@ -245,10 +248,7 @@ void VolumeMeshBuilder::generate_vertices_and_quads(
|
|||||||
vector<ccl::int3> &vertices_is,
|
vector<ccl::int3> &vertices_is,
|
||||||
vector<QuadData> &quads)
|
vector<QuadData> &quads)
|
||||||
{
|
{
|
||||||
/* Overallocation, we could count the number of quads and vertices to create
|
unordered_map<size_t, int> used_verts;
|
||||||
* in a pre-pass if memory becomes an issue. */
|
|
||||||
vertices_is.reserve(number_of_nodes*8);
|
|
||||||
quads.reserve(number_of_nodes*6);
|
|
||||||
|
|
||||||
for(int z = 0; z < res.z; ++z) {
|
for(int z = 0; z < res.z; ++z) {
|
||||||
for(int y = 0; y < res.y; ++y) {
|
for(int y = 0; y < res.y; ++y) {
|
||||||
@ -283,77 +283,38 @@ void VolumeMeshBuilder::generate_vertices_and_quads(
|
|||||||
|
|
||||||
voxel_index = compute_voxel_index(res, x - 1, y, z);
|
voxel_index = compute_voxel_index(res, x - 1, y, z);
|
||||||
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
||||||
create_quad(corners, vertices_is, quads, QUAD_X_MIN);
|
create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel_index = compute_voxel_index(res, x + 1, y, z);
|
voxel_index = compute_voxel_index(res, x + 1, y, z);
|
||||||
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
||||||
create_quad(corners, vertices_is, quads, QUAD_X_MAX);
|
create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel_index = compute_voxel_index(res, x, y - 1, z);
|
voxel_index = compute_voxel_index(res, x, y - 1, z);
|
||||||
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
||||||
create_quad(corners, vertices_is, quads, QUAD_Y_MIN);
|
create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel_index = compute_voxel_index(res, x, y + 1, z);
|
voxel_index = compute_voxel_index(res, x, y + 1, z);
|
||||||
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
||||||
create_quad(corners, vertices_is, quads, QUAD_Y_MAX);
|
create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel_index = compute_voxel_index(res, x, y, z - 1);
|
voxel_index = compute_voxel_index(res, x, y, z - 1);
|
||||||
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
||||||
create_quad(corners, vertices_is, quads, QUAD_Z_MIN);
|
create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel_index = compute_voxel_index(res, x, y, z + 1);
|
voxel_index = compute_voxel_index(res, x, y, z + 1);
|
||||||
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
if(voxel_index == -1 || grid[voxel_index] == 0) {
|
||||||
create_quad(corners, vertices_is, quads, QUAD_Z_MAX);
|
create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MAX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VolumeMeshBuilder::deduplicate_vertices(vector<int3> &vertices,
|
|
||||||
vector<QuadData> &quads)
|
|
||||||
{
|
|
||||||
vector<int3> sorted_vertices = vertices;
|
|
||||||
std::sort(sorted_vertices.begin(), sorted_vertices.end());
|
|
||||||
vector<int3>::iterator it = std::unique(sorted_vertices.begin(), sorted_vertices.end());
|
|
||||||
sorted_vertices.resize(std::distance(sorted_vertices.begin(), it));
|
|
||||||
|
|
||||||
vector<QuadData> new_quads = quads;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < vertices.size(); ++i) {
|
|
||||||
for(size_t j = 0; j < sorted_vertices.size(); ++j) {
|
|
||||||
if(vertices[i] != sorted_vertices[j]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int k = 0; k < quads.size(); ++k) {
|
|
||||||
if(quads[k].v0 == i) {
|
|
||||||
new_quads[k].v0 = j;
|
|
||||||
}
|
|
||||||
else if(quads[k].v1 == i) {
|
|
||||||
new_quads[k].v1 = j;
|
|
||||||
}
|
|
||||||
else if(quads[k].v2 == i) {
|
|
||||||
new_quads[k].v2 = j;
|
|
||||||
}
|
|
||||||
else if(quads[k].v3 == i) {
|
|
||||||
new_quads[k].v3 = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vertices = sorted_vertices;
|
|
||||||
quads = new_quads;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices,
|
void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices,
|
||||||
vector<float3> &out_vertices)
|
vector<float3> &out_vertices)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user