mirror of https://gitee.com/openkylin/vtk9.git
393 lines
12 KiB
C++
393 lines
12 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkProjectedTetrahedraMapper.cxx
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm 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.
|
|
|
|
=========================================================================*/
|
|
|
|
/*
|
|
* Copyright 2003 Sandia Corporation.
|
|
* Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
|
|
* license for use of this work by or on behalf of the
|
|
* U.S. Government. Redistribution and use in source and binary forms, with
|
|
* or without modification, are permitted provided that this Notice and any
|
|
* statement of authorship are reproduced on all copies.
|
|
*/
|
|
|
|
#include "vtkProjectedTetrahedraMapper.h"
|
|
|
|
#include "vtkArrayDispatch.h"
|
|
#include "vtkCellArray.h"
|
|
#include "vtkCellCenterDepthSort.h"
|
|
#include "vtkCellData.h"
|
|
#include "vtkColorTransferFunction.h"
|
|
#include "vtkDoubleArray.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkGarbageCollector.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPiecewiseFunction.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkTimerLog.h"
|
|
#include "vtkUnsignedCharArray.h"
|
|
#include "vtkUnstructuredGrid.h"
|
|
#include "vtkVisibilitySort.h"
|
|
#include "vtkVolume.h"
|
|
#include "vtkVolumeProperty.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
//------------------------------------------------------------------------------
|
|
vtkCxxSetObjectMacro(vtkProjectedTetrahedraMapper, VisibilitySort, vtkVisibilitySort);
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Return nullptr if no override is supplied.
|
|
vtkAbstractObjectFactoryNewMacro(vtkProjectedTetrahedraMapper);
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
vtkProjectedTetrahedraMapper::vtkProjectedTetrahedraMapper()
|
|
{
|
|
this->VisibilitySort = vtkCellCenterDepthSort::New();
|
|
}
|
|
|
|
vtkProjectedTetrahedraMapper::~vtkProjectedTetrahedraMapper()
|
|
{
|
|
this->SetVisibilitySort(nullptr);
|
|
}
|
|
|
|
void vtkProjectedTetrahedraMapper::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
os << indent << "VisibilitySort: " << this->VisibilitySort << endl;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void vtkProjectedTetrahedraMapper::ReportReferences(vtkGarbageCollector* collector)
|
|
{
|
|
this->Superclass::ReportReferences(collector);
|
|
|
|
vtkGarbageCollectorReport(collector, this->VisibilitySort, "VisibilitySort");
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
namespace
|
|
{
|
|
struct TransformPointsWorker
|
|
{
|
|
const float* Proj;
|
|
const float* ModelView;
|
|
float* OutPoints;
|
|
|
|
TransformPointsWorker(const float* proj, const float* mv, float* out)
|
|
: Proj(proj)
|
|
, ModelView(mv)
|
|
, OutPoints(out)
|
|
{
|
|
}
|
|
|
|
template <class ArrayT>
|
|
void operator()(ArrayT* in_points)
|
|
{
|
|
float mat[16];
|
|
int row, col;
|
|
vtkIdType i;
|
|
vtkIdType num_points = in_points->GetNumberOfTuples();
|
|
typename ArrayT::ValueType in_p[3];
|
|
float* out_p;
|
|
|
|
// Combine two transforms into one transform.
|
|
for (col = 0; col < 4; col++)
|
|
{
|
|
for (row = 0; row < 4; row++)
|
|
{
|
|
mat[col * 4 + row] = (this->Proj[0 * 4 + row] * this->ModelView[col * 4 + 0] +
|
|
this->Proj[1 * 4 + row] * this->ModelView[col * 4 + 1] +
|
|
this->Proj[2 * 4 + row] * this->ModelView[col * 4 + 2] +
|
|
this->Proj[3 * 4 + row] * this->ModelView[col * 4 + 3]);
|
|
}
|
|
}
|
|
|
|
// Transform all points.
|
|
for (i = 0, out_p = this->OutPoints; i < num_points; i++, out_p += 3)
|
|
{
|
|
in_points->GetTypedTuple(i, in_p);
|
|
for (row = 0; row < 3; row++)
|
|
{
|
|
out_p[row] = (mat[0 * 4 + row] * in_p[0] + mat[1 * 4 + row] * in_p[1] +
|
|
mat[2 * 4 + row] * in_p[2] + mat[3 * 4 + row]);
|
|
}
|
|
}
|
|
|
|
// Check to see if we need to divide by w.
|
|
if ((mat[0 * 4 + 3] != 0) || (mat[1 * 4 + 3] != 0) || (mat[2 * 4 + 3] != 0) ||
|
|
(mat[3 * 4 + 3] != 1))
|
|
{
|
|
for (i = 0, out_p = this->OutPoints; i < num_points; i++, out_p += 3)
|
|
{
|
|
in_points->GetTypedTuple(i, in_p);
|
|
float w = (mat[0 * 4 + 3] * in_p[0] + mat[1 * 4 + 3] * in_p[1] + mat[2 * 4 + 3] * in_p[2] +
|
|
mat[3 * 4 + 3]);
|
|
if (w > 0.0)
|
|
{
|
|
out_p[0] /= w;
|
|
out_p[1] /= w;
|
|
out_p[2] /= w;
|
|
}
|
|
else
|
|
{
|
|
// A negative w probably means the point is behind the viewer. Things
|
|
// can get screwy if we try to inverse-project that. Instead, just
|
|
// set the position somewhere very far behind us.
|
|
out_p[2] = -VTK_FLOAT_MAX;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
} // end anon namespace
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkProjectedTetrahedraMapper::TransformPoints(vtkPoints* inPoints,
|
|
const float projection_mat[16], const float modelview_mat[16], vtkFloatArray* outPoints)
|
|
{
|
|
if (!inPoints)
|
|
{
|
|
return;
|
|
}
|
|
outPoints->SetNumberOfComponents(3);
|
|
outPoints->SetNumberOfTuples(inPoints->GetNumberOfPoints());
|
|
TransformPointsWorker worker(projection_mat, modelview_mat, outPoints->GetPointer(0));
|
|
vtkArrayDispatch::Dispatch::Execute(inPoints->GetData(), worker);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
namespace vtkProjectedTetrahedraMapperNamespace
|
|
{
|
|
template <typename ColorArrayT, typename ScalarArrayT>
|
|
void MapScalarsToColorsImpl(
|
|
ColorArrayT* colors, vtkVolumeProperty* property, ScalarArrayT* scalars);
|
|
template <typename ColorArrayT, typename ScalarArrayT>
|
|
void MapIndependentComponents(
|
|
ColorArrayT* colors, vtkVolumeProperty* property, ScalarArrayT* scalars);
|
|
template <typename ColorArrayT, typename ScalarArrayT>
|
|
void Map2DependentComponents(
|
|
ColorArrayT* colors, vtkVolumeProperty* property, ScalarArrayT* scalars);
|
|
template <typename ColorArrayT, typename ScalarArrayT>
|
|
void Map4DependentComponents(ColorArrayT* colors, ScalarArrayT* scalars);
|
|
|
|
struct Worker
|
|
{
|
|
vtkVolumeProperty* Property;
|
|
|
|
Worker(vtkVolumeProperty* property)
|
|
: Property(property)
|
|
{
|
|
}
|
|
|
|
template <typename ColorArrayT, typename ScalarArrayT>
|
|
void operator()(ColorArrayT* colors, ScalarArrayT* scalars)
|
|
{
|
|
MapScalarsToColorsImpl(colors, this->Property, scalars);
|
|
}
|
|
};
|
|
}
|
|
|
|
void vtkProjectedTetrahedraMapper::MapScalarsToColors(
|
|
vtkDataArray* colors, vtkVolumeProperty* property, vtkDataArray* scalars)
|
|
{
|
|
using namespace vtkProjectedTetrahedraMapperNamespace;
|
|
|
|
vtkDataArray* tmpColors;
|
|
int castColors;
|
|
|
|
if ((colors->GetDataType() == VTK_UNSIGNED_CHAR) &&
|
|
(((scalars->GetDataType() != VTK_UNSIGNED_CHAR) || (property->GetIndependentComponents())) ||
|
|
((!property->GetIndependentComponents()) && (scalars->GetNumberOfComponents() == 2))))
|
|
{
|
|
// Special case. Need to convert from range [0,1] to [0,255].
|
|
tmpColors = vtkDoubleArray::New();
|
|
castColors = 1;
|
|
}
|
|
else
|
|
{
|
|
tmpColors = colors;
|
|
castColors = 0;
|
|
}
|
|
|
|
vtkIdType numscalars = scalars->GetNumberOfTuples();
|
|
|
|
tmpColors->Initialize();
|
|
tmpColors->SetNumberOfComponents(4);
|
|
tmpColors->SetNumberOfTuples(numscalars);
|
|
|
|
Worker worker(property);
|
|
if (!vtkArrayDispatch::Dispatch2::Execute(tmpColors, scalars, worker))
|
|
{
|
|
vtkGenericWarningMacro("Dispatch failed for scalar array " << scalars->GetName());
|
|
}
|
|
|
|
if (castColors)
|
|
{
|
|
// Special case. Need to convert from range [0,1] to [0,255].
|
|
colors->Initialize();
|
|
colors->SetNumberOfComponents(4);
|
|
colors->SetNumberOfTuples(scalars->GetNumberOfTuples());
|
|
|
|
unsigned char* c = static_cast<vtkUnsignedCharArray*>(colors)->GetPointer(0);
|
|
|
|
for (vtkIdType i = 0; i < numscalars; i++, c += 4)
|
|
{
|
|
double* dc = tmpColors->GetTuple(i);
|
|
c[0] = static_cast<unsigned char>(dc[0] * 255.9999);
|
|
c[1] = static_cast<unsigned char>(dc[1] * 255.9999);
|
|
c[2] = static_cast<unsigned char>(dc[2] * 255.9999);
|
|
c[3] = static_cast<unsigned char>(dc[3] * 255.9999);
|
|
}
|
|
|
|
tmpColors->Delete();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
namespace vtkProjectedTetrahedraMapperNamespace
|
|
{
|
|
template <typename ColorArrayT, typename ScalarArrayT>
|
|
void MapScalarsToColorsImpl(ColorArrayT* colors, vtkVolumeProperty* property, ScalarArrayT* scalars)
|
|
{
|
|
if (property->GetIndependentComponents())
|
|
{
|
|
MapIndependentComponents(colors, property, scalars);
|
|
}
|
|
else
|
|
{
|
|
switch (scalars->GetNumberOfComponents())
|
|
{
|
|
case 2:
|
|
Map2DependentComponents(colors, property, scalars);
|
|
break;
|
|
case 4:
|
|
Map4DependentComponents(colors, scalars);
|
|
break;
|
|
default:
|
|
vtkGenericWarningMacro("Attempted to map scalar with " << scalars->GetNumberOfComponents()
|
|
<< " with dependent components");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename ColorArrayT, typename ScalarArrayT>
|
|
void MapIndependentComponents(
|
|
ColorArrayT* colors, vtkVolumeProperty* property, ScalarArrayT* scalars)
|
|
{
|
|
// I don't really know what to do if there is more than one component.
|
|
// How am I supposed to mix the resulting colors? Since I don't know
|
|
// what to do, and the whole thing seems kinda pointless anyway, I'm just
|
|
// going to punt and copy over the first scalar.
|
|
vtkIdType i;
|
|
vtkIdType num_scalars = scalars->GetNumberOfTuples();
|
|
|
|
typedef typename ScalarArrayT::ValueType ScalarType;
|
|
typedef typename ColorArrayT::ValueType ColorType;
|
|
ColorType c[4];
|
|
|
|
if (property->GetColorChannels() == 1)
|
|
{
|
|
vtkPiecewiseFunction* gray = property->GetGrayTransferFunction();
|
|
vtkPiecewiseFunction* alpha = property->GetScalarOpacity();
|
|
|
|
for (i = 0; i < num_scalars; i++)
|
|
{
|
|
ScalarType s = scalars->GetTypedComponent(i, 0);
|
|
c[0] = c[1] = c[2] = static_cast<ColorType>(gray->GetValue(s));
|
|
c[3] = static_cast<ColorType>(alpha->GetValue(s));
|
|
colors->SetTypedTuple(i, c);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vtkColorTransferFunction* rgb = property->GetRGBTransferFunction();
|
|
vtkPiecewiseFunction* alpha = property->GetScalarOpacity();
|
|
|
|
int vectorMode = rgb->GetVectorMode();
|
|
int vectorComponent = rgb->GetVectorComponent();
|
|
|
|
for (i = 0; i < num_scalars; i++)
|
|
{
|
|
ScalarType s = 0.0;
|
|
if (scalars->GetNumberOfComponents() == 1)
|
|
{
|
|
s = scalars->GetValue(i);
|
|
}
|
|
else if (vectorMode == vtkScalarsToColors::COMPONENT)
|
|
{
|
|
s = scalars->GetTypedComponent(i, vectorComponent);
|
|
}
|
|
else
|
|
{
|
|
ScalarType sum = 0.0;
|
|
for (int comp = 0; comp < scalars->GetNumberOfComponents(); ++comp)
|
|
{
|
|
ScalarType t = scalars->GetTypedComponent(i, comp);
|
|
sum += t * t;
|
|
}
|
|
s = sqrt(sum);
|
|
}
|
|
|
|
double trgb[3];
|
|
rgb->GetColor(s, trgb);
|
|
c[0] = static_cast<ColorType>(trgb[0]);
|
|
c[1] = static_cast<ColorType>(trgb[1]);
|
|
c[2] = static_cast<ColorType>(trgb[2]);
|
|
c[3] = static_cast<ColorType>(alpha->GetValue(s));
|
|
colors->SetTypedTuple(i, c);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename ColorArrayT, typename ScalarArrayT>
|
|
void Map2DependentComponents(
|
|
ColorArrayT* colors, vtkVolumeProperty* property, ScalarArrayT* scalars)
|
|
{
|
|
typedef typename ScalarArrayT::ValueType ScalarType;
|
|
vtkColorTransferFunction* rgb = property->GetRGBTransferFunction();
|
|
vtkPiecewiseFunction* alpha = property->GetScalarOpacity();
|
|
vtkIdType num_scalars = scalars->GetNumberOfTuples();
|
|
double rgbColor[4];
|
|
ScalarType scalar[2];
|
|
|
|
for (vtkIdType i = 0; i < num_scalars; i++)
|
|
{
|
|
scalars->GetTypedTuple(i, scalar);
|
|
rgb->GetColor(scalar[0], rgbColor);
|
|
rgbColor[3] = alpha->GetValue(scalar[1]);
|
|
colors->SetTuple(i, rgbColor);
|
|
}
|
|
}
|
|
|
|
template <typename ColorArrayT, typename ScalarArrayT>
|
|
void Map4DependentComponents(ColorArrayT* colors, ScalarArrayT* scalars)
|
|
{
|
|
double val[4];
|
|
vtkIdType num_scalars = scalars->GetNumberOfTuples();
|
|
for (vtkIdType i = 0; i < num_scalars; i++)
|
|
{
|
|
scalars->GetTuple(i, val);
|
|
colors->SetTuple(i, val);
|
|
}
|
|
}
|
|
|
|
}
|