//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ #include #include #include #include #include #include #include #include #include #include #include namespace vtkm { namespace rendering { struct ScalarRenderer::InternalsType { bool ValidDataSet; vtkm::Int32 Width; vtkm::Int32 Height; vtkm::Float32 DefaultValue; vtkm::cont::DataSet DataSet; vtkm::rendering::raytracing::ScalarRenderer Tracer; vtkm::Bounds ShapeBounds; VTKM_CONT InternalsType() : ValidDataSet(false) , Width(1024) , Height(1024) , DefaultValue(vtkm::Nan32()) { } }; ScalarRenderer::ScalarRenderer() : Internals(new InternalsType) { } ScalarRenderer::~ScalarRenderer() {} void ScalarRenderer::SetWidth(const vtkm::Int32 width) { if (width < 1) { throw vtkm::cont::ErrorBadValue("ScalarRenderer: width must be greater than 0"); } Internals->Width = width; } void ScalarRenderer::SetDefaultValue(const vtkm::Float32 value) { Internals->DefaultValue = value; } void ScalarRenderer::SetHeight(const vtkm::Int32 height) { if (height < 1) { throw vtkm::cont::ErrorBadValue("ScalarRenderer: height must be greater than 0"); } Internals->Height = height; } void ScalarRenderer::SetInput(vtkm::cont::DataSet& dataSet) { this->Internals->DataSet = dataSet; this->Internals->ValidDataSet = true; raytracing::TriangleExtractor triExtractor; vtkm::cont::DynamicCellSet cellSet = this->Internals->DataSet.GetCellSet(); vtkm::cont::CoordinateSystem coords = this->Internals->DataSet.GetCoordinateSystem(); triExtractor.ExtractCells(cellSet); if (triExtractor.GetNumberOfTriangles() > 0) { auto triIntersector = std::make_shared(); triIntersector->SetData(coords, triExtractor.GetTriangles()); this->Internals->Tracer.SetShapeIntersector(triIntersector); this->Internals->ShapeBounds = triIntersector->GetShapeBounds(); } } ScalarRenderer::Result ScalarRenderer::Render(const vtkm::rendering::Camera& camera) { if (!Internals->ValidDataSet) { throw vtkm::cont::ErrorBadValue("ScalarRenderer: input never set"); } raytracing::Logger* logger = raytracing::Logger::GetInstance(); logger->OpenLogEntry("scalar_render"); vtkm::cont::Timer tot_timer; tot_timer.Start(); vtkm::cont::Timer timer; timer.Start(); // // Create rays // vtkm::rendering::raytracing::Camera cam; cam.SetParameters(camera, this->Internals->Width, this->Internals->Height); vtkm::rendering::raytracing::Ray rays; cam.CreateRays(rays, this->Internals->ShapeBounds); rays.Buffers.at(0).InitConst(0.f); // add fields const vtkm::Id numFields = this->Internals->DataSet.GetNumberOfFields(); std::map rangeMap; for (vtkm::Id i = 0; i < numFields; ++i) { vtkm::cont::Field field = this->Internals->DataSet.GetField(i); vtkm::cont::ArrayHandle ranges; ranges = field.GetRange(); vtkm::Id comps = ranges.GetNumberOfValues(); if (comps == 1) { rangeMap[field.GetName()] = ranges.ReadPortal().Get(0); this->Internals->Tracer.AddField(field); } } this->Internals->Tracer.Render(rays, Internals->DefaultValue); using ArrayF32 = vtkm::cont::ArrayHandle; std::vector res; std::vector names; const size_t numBuffers = rays.Buffers.size(); vtkm::Id expandSize = Internals->Width * Internals->Height; for (size_t i = 0; i < numBuffers; ++i) { const std::string name = rays.Buffers[i].GetName(); if (name == "default") continue; raytracing::ChannelBuffer buffer = rays.Buffers[i]; raytracing::ChannelBuffer expanded = buffer.ExpandBuffer(rays.PixelIdx, expandSize, Internals->DefaultValue); res.push_back(expanded.Buffer); names.push_back(name); } raytracing::ChannelBuffer depthChannel(1, rays.NumRays); depthChannel.Buffer = rays.Distance; raytracing::ChannelBuffer depthExpanded = depthChannel.ExpandBuffer(rays.PixelIdx, expandSize, Internals->DefaultValue); Result result; result.Width = Internals->Width; result.Height = Internals->Height; result.Scalars = res; result.ScalarNames = names; result.Ranges = rangeMap; result.Depths = depthExpanded.Buffer; vtkm::Float64 time = timer.GetElapsedTime(); logger->AddLogData("write_to_canvas", time); time = tot_timer.GetElapsedTime(); logger->CloseLogEntry(time); return result; } vtkm::cont::DataSet ScalarRenderer::Result::ToDataSet() { if (Scalars.size() == 0) { throw vtkm::cont::ErrorBadValue("ScalarRenderer: result empty"); } VTKM_ASSERT(Width > 0); VTKM_ASSERT(Height > 0); vtkm::cont::DataSet result; vtkm::Vec origin(0.f, 0.f, 0.f); vtkm::Vec spacing(1.f, 1.f, 1.f); vtkm::Id3 dims(Width + 1, Height + 1, 1); result.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coords", dims, origin, spacing)); vtkm::Id2 dims2(dims[0], dims[1]); vtkm::cont::CellSetStructured<2> resCellSet; resCellSet.SetPointDimensions(dims2); result.SetCellSet(resCellSet); const size_t fieldSize = Scalars.size(); for (size_t i = 0; i < fieldSize; ++i) { result.AddField( vtkm::cont::Field(ScalarNames[i], vtkm::cont::Field::Association::CELL_SET, Scalars[i])); } result.AddField(vtkm::cont::Field("depth", vtkm::cont::Field::Association::CELL_SET, Depths)); return result; } } } // vtkm::rendering