abstract compute pipeline barrier

feature/softbody-runtime-control
Benjamin Kraft 3 months ago
parent 1695940c6a
commit 296235288f
  1. 8
      imgui.ini
  2. 9
      include/application.hpp
  3. 3
      include/constraints.hpp
  4. 147
      src/application.cpp
  5. 12
      src/soft_body.cpp

@ -32,6 +32,14 @@ Collapsed=0
Pos=1617,2 Pos=1617,2
Size=302,1002 Size=302,1002
Collapsed=0 Collapsed=0
DockId=0x00000001,0
[Window][Performance 2]
Pos=1617,2
Size=302,1002
Collapsed=0
DockId=0x00000001,1
[Docking][Data] [Docking][Data]
DockNode ID=0x00000001 Pos=1617,2 Size=302,1002 Selected=0x60B79D0E

@ -91,12 +91,13 @@ private:
unique_ptr<ComputePipeline> normalPipeline; unique_ptr<ComputePipeline> normalPipeline;
void updateCameraBuffer(); void updateCameraBuffer();
void recordDrawCommands(VkCommandBuffer cmdBuffer); void recordDrawCommands(VkCommandBuffer commandBuffer);
void drawFrame(float dt); void drawFrame(float dt);
void recordGrabCommands(VkCommandBuffer cmdBuffer); void recordGrabCommands(VkCommandBuffer commandBuffer);
void recordPBDCommands(VkCommandBuffer cmdBuffer); void recordPBDCommands(VkCommandBuffer commandBuffer);
void recordNormalCommands(VkCommandBuffer cmdBuffer); void recordNormalCommands(VkCommandBuffer commandBuffer);
void computePipelineBarrier(VkCommandBuffer commandBuffer);
void update(); void update();

@ -56,6 +56,9 @@ private:
uint32_t prePartitionTetrahedronCount; uint32_t prePartitionTetrahedronCount;
}; };
// The following classes are only for the graph coloring in pre-processing
struct Constraint { struct Constraint {
virtual ~Constraint() {} virtual ~Constraint() {}
virtual void writeData(ConstraintData& dataLists) const {}; virtual void writeData(ConstraintData& dataLists) const {};

@ -188,14 +188,14 @@ void Application::createMeshBuffers() {
auto body = std::make_unique<SoftBody>(&sphere, 1.f / 60); auto body = std::make_unique<SoftBody>(&sphere, 1.f / 60);
for (size_t i = 0; i < 5; i++){ for (size_t i = 0; i < 2; i++){
auto copy = std::make_unique<SoftBody>(*body.get()); auto copy = std::make_unique<SoftBody>(*body.get());
copy->applyVertexOffset({i * 2, 0, 0}); copy->applyVertexOffset({i * 2, 0, 0});
softBodies.push_back(std::move(copy)); softBodies.push_back(std::move(copy));
} }
body = std::make_unique<SoftBody>(&bunny, 1.f / 10); body = std::make_unique<SoftBody>(&bunny, 1.f / 10);
for (size_t i = 0; i < 5; i++){ for (size_t i = 0; i < 2; i++){
auto copy = std::make_unique<SoftBody>(*body.get()); auto copy = std::make_unique<SoftBody>(*body.get());
copy->applyVertexOffset({i * 2, 0, 2}); copy->applyVertexOffset({i * 2, 0, 2});
softBodies.push_back(std::move(copy)); softBodies.push_back(std::move(copy));
@ -481,17 +481,17 @@ void Application::drawFrame(float dt) {
} }
} }
void Application::recordDrawCommands(VkCommandBuffer cmdBuffer) { void Application::recordDrawCommands(VkCommandBuffer commandBuffer) {
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->handle); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->handle);
VkBuffer buffers[] = {vertexBuffers[currentDrawVertexBuffer]->handle}; VkBuffer buffers[] = {vertexBuffers[currentDrawVertexBuffer]->handle};
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(cmdBuffer, 0, 1, buffers, offsets); vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
vkCmdBindIndexBuffer(cmdBuffer, faceBuffer->handle, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(commandBuffer, faceBuffer->handle, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::WORLD], 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::WORLD], 0, nullptr);
for (const auto &softBody : softBodies){ for (const auto &softBody : softBodies){
vkCmdDrawIndexed(cmdBuffer, softBody->faces.size() * 3, 1, softBody->firstIndex, 0, 0); vkCmdDrawIndexed(commandBuffer, softBody->faces.size() * 3, 1, softBody->firstIndex, 0, 0);
} }
} }
@ -567,73 +567,58 @@ uint32_t Application::GetGroupCount(uint32_t threads, uint32_t blockSize) {
return (threads - 1) / blockSize + 1; return (threads - 1) / blockSize + 1;
} }
void Application::recordGrabCommands(VkCommandBuffer cmdBuffer) { void Application::recordGrabCommands(VkCommandBuffer commandBuffer) {
VkMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
// TODO maybe add buffermemorybarrier for camera uniform, because it can be changed from main drawing thread // TODO maybe add buffermemorybarrier for camera uniform, because it can be changed from main drawing thread
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->handle); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->handle);
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr);
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 1, 1, &descriptorPool->sets[DescriptorSet::WORLD], 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 1, 1, &descriptorPool->sets[DescriptorSet::WORLD], 0, nullptr);
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 2, 1, &descriptorPool->sets[DescriptorSet::SIMULATION], 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, grabPipeline->layout, 2, 1, &descriptorPool->sets[DescriptorSet::SIMULATION], 0, nullptr);
GrabPushData pushConstants {}; GrabPushData pushConstants {};
if (grabber->started()){ if (grabber->started()){
pushConstants.state = 0; pushConstants.state = 0;
pushConstants.screenPosition = grabber->previousCursorPosition; pushConstants.screenPosition = grabber->previousCursorPosition;
vkCmdPushConstants(cmdBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants); vkCmdPushConstants(commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants);
uint32_t faceInvocations = GetGroupCount(faceBuffer->size / sizeof(Face), BLOCK_SIZE_GRAB); uint32_t faceInvocations = GetGroupCount(faceBuffer->size / sizeof(Face), BLOCK_SIZE_GRAB);
vkCmdDispatch(cmdBuffer, faceInvocations, 1, 1); vkCmdDispatch(commandBuffer, faceInvocations, 1, 1);
computePipelineBarrier(commandBuffer);
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier,
0, nullptr, 0, nullptr);
pushConstants.state = 1; pushConstants.state = 1;
vkCmdPushConstants(cmdBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants); vkCmdPushConstants(commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants);
vkCmdDispatch(cmdBuffer, 1, 1, 1); vkCmdDispatch(commandBuffer, 1, 1, 1);
} }
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, computePipelineBarrier(commandBuffer);
0, nullptr, 0, nullptr);
glm::vec2 screenDelta; glm::vec2 screenDelta;
if (grabber->moved(screenDelta)){ if (grabber->moved(screenDelta)){
pushConstants.state = 2; pushConstants.state = 2;
pushConstants.screenDelta = screenDelta; pushConstants.screenDelta = screenDelta;
vkCmdPushConstants(cmdBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants); vkCmdPushConstants(commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants);
vkCmdDispatch(cmdBuffer, 1, 1, 1); vkCmdDispatch(commandBuffer, 1, 1, 1);
} }
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, computePipelineBarrier(commandBuffer);
0, nullptr, 0, nullptr);
if (grabber->stopped()){ if (grabber->stopped()){
pushConstants.state = 3; pushConstants.state = 3;
vkCmdPushConstants(cmdBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants); vkCmdPushConstants(commandBuffer, grabPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(GrabPushData), &pushConstants);
vkCmdDispatch(cmdBuffer, 1, 1, 1); vkCmdDispatch(commandBuffer, 1, 1, 1);
} }
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, computePipelineBarrier(commandBuffer);
0, nullptr, 0, nullptr);
} }
void Application::recordPBDCommands(VkCommandBuffer cmdBuffer) { void Application::recordPBDCommands(VkCommandBuffer commandBuffer) {
VkMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
uint32_t vertexGroupCount = GetGroupCount(vertexBuffers[1 - currentDrawVertexBuffer]->size / sizeof(Vertex), BLOCK_SIZE_PBD); uint32_t vertexGroupCount = GetGroupCount(vertexBuffers[1 - currentDrawVertexBuffer]->size / sizeof(Vertex), BLOCK_SIZE_PBD);
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->handle); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->handle);
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr);
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->layout, 1, 1, &descriptorPool->sets[DescriptorSet::SIMULATION], 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pbdPipeline->layout, 1, 1, &descriptorPool->sets[DescriptorSet::SIMULATION], 0, nullptr);
uint32_t state; uint32_t state;
@ -641,12 +626,12 @@ void Application::recordPBDCommands(VkCommandBuffer cmdBuffer) {
for (size_t i = 0; i < k; i++){ for (size_t i = 0; i < k; i++){
state = 0; state = 0;
vkCmdPushConstants(cmdBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state);
vkCmdDispatch(cmdBuffer, vertexGroupCount, 1, 1); vkCmdDispatch(commandBuffer, vertexGroupCount, 1, 1);
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr); computePipelineBarrier(commandBuffer);
state = 1; state = 1;
vkCmdPushConstants(cmdBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state);
for (uint32_t partition = 0; partition < constraintData.partitionCount; partition++){ for (uint32_t partition = 0; partition < constraintData.partitionCount; partition++){
auto edgePartition = constraintData.edgePartitions[partition]; auto edgePartition = constraintData.edgePartitions[partition];
@ -657,51 +642,67 @@ void Application::recordPBDCommands(VkCommandBuffer cmdBuffer) {
ConstraintData::Partition partitions[2] = {edgePartition, tetrahedronPartition}; ConstraintData::Partition partitions[2] = {edgePartition, tetrahedronPartition};
vkCmdPushConstants(cmdBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, vkCmdPushConstants(commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT,
offsetof(PBDPushData, edgePartition), offsetof(PBDPushData, edgePartition),
sizeof(partitions), partitions); sizeof(partitions), partitions);
uint32_t invocations = GetGroupCount(edgePartition.size + tetrahedronPartition.size, BLOCK_SIZE_PBD); uint32_t invocations = GetGroupCount(edgePartition.size + tetrahedronPartition.size, BLOCK_SIZE_PBD);
vkCmdDispatch(cmdBuffer, invocations, 1, 1); vkCmdDispatch(commandBuffer, invocations, 1, 1);
computePipelineBarrier(commandBuffer);
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr);
} }
state = 2; state = 2;
vkCmdPushConstants(cmdBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(commandBuffer, pbdPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state);
vkCmdDispatch(cmdBuffer, vertexGroupCount, 1, 1); vkCmdDispatch(commandBuffer, vertexGroupCount, 1, 1);
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr); computePipelineBarrier(commandBuffer);
} }
} }
void Application::recordNormalCommands(VkCommandBuffer cmdBuffer) { void Application::recordNormalCommands(VkCommandBuffer commandBuffer) {
VkMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
uint32_t vertexGroupCount = GetGroupCount(vertexBuffers[1 - currentDrawVertexBuffer]->size / sizeof(Vertex), BLOCK_SIZE_NORMAL); uint32_t vertexGroupCount = GetGroupCount(vertexBuffers[1 - currentDrawVertexBuffer]->size / sizeof(Vertex), BLOCK_SIZE_NORMAL);
uint32_t faceGroupCount = GetGroupCount(faceBuffer->size / sizeof(Face), BLOCK_SIZE_NORMAL); uint32_t faceGroupCount = GetGroupCount(faceBuffer->size / sizeof(Face), BLOCK_SIZE_NORMAL);
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, normalPipeline->handle); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, normalPipeline->handle);
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, normalPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, normalPipeline->layout, 0, 1, &descriptorPool->sets[DescriptorSet::MESH], 0, nullptr);
uint32_t state = 0; uint32_t state = 0;
vkCmdPushConstants(cmdBuffer, normalPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(commandBuffer, normalPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state);
vkCmdDispatch(cmdBuffer, vertexGroupCount, 1, 1); vkCmdDispatch(commandBuffer, vertexGroupCount, 1, 1);
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr); computePipelineBarrier(commandBuffer);
state = 1; state = 1;
vkCmdPushConstants(cmdBuffer, normalPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(commandBuffer, normalPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state);
vkCmdDispatch(cmdBuffer, faceGroupCount, 1, 1); vkCmdDispatch(commandBuffer, faceGroupCount, 1, 1);
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr); computePipelineBarrier(commandBuffer);
state = 2; state = 2;
vkCmdPushConstants(cmdBuffer, normalPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state); vkCmdPushConstants(commandBuffer, normalPipeline->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &state);
vkCmdDispatch(cmdBuffer, vertexGroupCount, 1, 1); vkCmdDispatch(commandBuffer, vertexGroupCount, 1, 1);
computePipelineBarrier(commandBuffer);
}
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; void Application::computePipelineBarrier(VkCommandBuffer commandBuffer) {
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr); VkMemoryBarrier memoryBarrier {};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
const Buffer& buffer = *vertexBuffers[1 - currentDrawVertexBuffer];
VkBufferMemoryBarrier bufferMemoryBarrier {};
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufferMemoryBarrier.buffer = buffer.handle;
bufferMemoryBarrier.size = buffer.size;
bufferMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
bufferMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkCmdPipelineBarrier(commandBuffer,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0,
1, &memoryBarrier,
1, &bufferMemoryBarrier,
0, nullptr);
} }
void Application::imGuiWindows() { void Application::imGuiWindows() {

@ -192,17 +192,17 @@ void SoftBody::splitConstraints() {
unordered_map<uint32_t, vector<const Constraint *>> pointToConstraints; unordered_map<uint32_t, vector<const Constraint *>> pointToConstraints;
vector<DistanceConstraint> lengthConstraints; vector<DistanceConstraint> distanceConstraints;
vector<VolumeConstraint> volumeConstraints; vector<VolumeConstraint> volumeConstraints;
lengthConstraints.reserve(constraintData.edges.size()); distanceConstraints.reserve(constraintData.edges.size());
volumeConstraints.reserve(constraintData.tetrahedra.size()); volumeConstraints.reserve(constraintData.tetrahedra.size());
for (const Edge &edge : constraintData.edges) for (const Edge &edge : constraintData.edges)
lengthConstraints.push_back(DistanceConstraint(edge)); distanceConstraints.push_back(DistanceConstraint(edge));
for (const Tetrahedron &tetrahedron : constraintData.tetrahedra) for (const Tetrahedron &tetrahedron : constraintData.tetrahedra)
volumeConstraints.push_back(VolumeConstraint(tetrahedron)); volumeConstraints.push_back(VolumeConstraint(tetrahedron));
for (const DistanceConstraint &distanceConstraint : lengthConstraints){ for (const DistanceConstraint &distanceConstraint : distanceConstraints){
pointToConstraints[distanceConstraint.a].push_back(&distanceConstraint); pointToConstraints[distanceConstraint.a].push_back(&distanceConstraint);
pointToConstraints[distanceConstraint.b].push_back(&distanceConstraint); pointToConstraints[distanceConstraint.b].push_back(&distanceConstraint);
} }
@ -225,8 +225,8 @@ void SoftBody::splitConstraints() {
graph[constraint].assign(neighbors.begin(), neighbors.end()); graph[constraint].assign(neighbors.begin(), neighbors.end());
}; };
#pragma omp parallel for default(none) shared(findAdjacent, lengthConstraints) #pragma omp parallel for default(none) shared(findAdjacent, distanceConstraints)
for (const DistanceConstraint &distanceConstraint : lengthConstraints){ for (const DistanceConstraint &distanceConstraint : distanceConstraints){
findAdjacent(&distanceConstraint, { findAdjacent(&distanceConstraint, {
distanceConstraint.a, distanceConstraint.a,
distanceConstraint.b distanceConstraint.b

Loading…
Cancel
Save