mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Initial commit of ResInsight version 0.4.8
This commit is contained in:
55
VisualizationModules/LibGeometry/CMakeLists.txt
Normal file
55
VisualizationModules/LibGeometry/CMakeLists.txt
Normal file
@@ -0,0 +1,55 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(LibGeometry)
|
||||
|
||||
|
||||
# Use our strict compile flags
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STRICT_CXX_FLAGS}")
|
||||
|
||||
|
||||
include_directories(../LibCore)
|
||||
|
||||
|
||||
set(CEE_HEADER_FILES
|
||||
cvfArrowGenerator.h
|
||||
cvfBoundingBox.h
|
||||
cvfBoxGenerator.h
|
||||
cvfEdgeKey.h
|
||||
cvfFrustum.h
|
||||
cvfGeometryBuilder.h
|
||||
cvfGeometryBuilderFaceList.h
|
||||
cvfGeometryBuilderTriangles.h
|
||||
cvfGeometryUtils.h
|
||||
cvfLibGeometry.h
|
||||
cvfMeshEdgeExtractor.h
|
||||
cvfOutlineEdgeExtractor.h
|
||||
cvfPatchGenerator.h
|
||||
cvfRay.h
|
||||
cvfTriangleMeshEdgeExtractor.h
|
||||
cvfTriangleVertexSplitter.h
|
||||
cvfVertexCompactor.h
|
||||
cvfVertexWelder.h
|
||||
)
|
||||
|
||||
set(CEE_SOURCE_FILES
|
||||
cvfArrowGenerator.cpp
|
||||
cvfBoundingBox.cpp
|
||||
cvfBoxGenerator.cpp
|
||||
cvfFrustum.cpp
|
||||
cvfEdgeKey.cpp
|
||||
cvfGeometryBuilder.cpp
|
||||
cvfGeometryBuilderFaceList.cpp
|
||||
cvfGeometryBuilderTriangles.cpp
|
||||
cvfGeometryUtils.cpp
|
||||
cvfMeshEdgeExtractor.cpp
|
||||
cvfOutlineEdgeExtractor.cpp
|
||||
cvfPatchGenerator.cpp
|
||||
cvfRay.cpp
|
||||
cvfTriangleMeshEdgeExtractor.cpp
|
||||
cvfTriangleVertexSplitter.cpp
|
||||
cvfVertexCompactor.cpp
|
||||
cvfVertexWelder.cpp
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} ${CEE_HEADER_FILES} ${CEE_SOURCE_FILES})
|
||||
|
||||
100
VisualizationModules/LibGeometry/cvfArrowGenerator.cpp
Normal file
100
VisualizationModules/LibGeometry/cvfArrowGenerator.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfArrowGenerator.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::ArrowGenerator
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Creates an arrow starting in origin and pointing in the direction of the +Z axis
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ArrowGenerator::ArrowGenerator()
|
||||
: m_shaftRelativeRadius(0.025f),
|
||||
m_headRelativeRadius(0.085f),
|
||||
m_headRelativeLength(0.25f),
|
||||
m_numSlices(20)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void ArrowGenerator::setShaftRelativeRadius(float shaftRelativeRadius)
|
||||
{
|
||||
m_shaftRelativeRadius = shaftRelativeRadius;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void ArrowGenerator::setHeadRelativeRadius(float headRelativeRadius)
|
||||
{
|
||||
m_headRelativeRadius = headRelativeRadius;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void ArrowGenerator::setHeadRelativeLength(float headRelativeLength)
|
||||
{
|
||||
m_headRelativeLength = headRelativeLength;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void ArrowGenerator::setNumSlices(uint numSlices)
|
||||
{
|
||||
m_numSlices = numSlices;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void ArrowGenerator::generate(GeometryBuilder* builder)
|
||||
{
|
||||
const uint numPolysZDir = 1;
|
||||
|
||||
GeometryUtils::createObliqueCylinder(m_shaftRelativeRadius, m_shaftRelativeRadius, 1.0f - m_headRelativeLength, 0, 0, m_numSlices, true, true, false, numPolysZDir, builder);
|
||||
|
||||
uint startIdx = builder->vertexCount();
|
||||
GeometryUtils::createCone(m_headRelativeRadius, m_headRelativeLength, m_numSlices, true, true, true, builder);
|
||||
uint endIdx = builder->vertexCount() - 1;
|
||||
|
||||
Mat4f mat = Mat4f::fromTranslation(Vec3f(0, 0, 1.0f - m_headRelativeLength));
|
||||
builder->transformVertexRange(startIdx, endIdx, mat);
|
||||
}
|
||||
|
||||
} // namespace cvf
|
||||
52
VisualizationModules/LibGeometry/cvfArrowGenerator.h
Normal file
52
VisualizationModules/LibGeometry/cvfArrowGenerator.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace cvf {
|
||||
|
||||
class GeometryBuilder;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Generates an arrow with base in origin and pointing in the +Z direction
|
||||
//
|
||||
//==================================================================================================
|
||||
class ArrowGenerator
|
||||
{
|
||||
public:
|
||||
ArrowGenerator();
|
||||
|
||||
void setShaftRelativeRadius(float shaftRelativeRadius);
|
||||
void setHeadRelativeRadius(float headRelativeRadius);
|
||||
void setHeadRelativeLength(float headRelativeLength);
|
||||
|
||||
void setNumSlices(uint numSlices);
|
||||
|
||||
void generate(GeometryBuilder* builder);
|
||||
|
||||
private:
|
||||
float m_shaftRelativeRadius;
|
||||
float m_headRelativeRadius;
|
||||
float m_headRelativeLength;
|
||||
|
||||
uint m_numSlices;
|
||||
};
|
||||
|
||||
}
|
||||
401
VisualizationModules/LibGeometry/cvfBoundingBox.cpp
Normal file
401
VisualizationModules/LibGeometry/cvfBoundingBox.cpp
Normal file
@@ -0,0 +1,401 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfBoundingBox.h"
|
||||
#include "cvfString.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::BoundingBox
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// The BoundingBox class implements an axis-aligned bounding box.
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
BoundingBox::BoundingBox()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
BoundingBox::BoundingBox(const Vec3d& min, const Vec3d& max)
|
||||
: m_min(min), m_max(max)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
BoundingBox::BoundingBox(const Vec3f& min, const Vec3f& max)
|
||||
: m_min(min), m_max(max)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
BoundingBox::BoundingBox(const BoundingBox& other)
|
||||
: m_min(other.m_min),
|
||||
m_max(other.m_max)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
BoundingBox& BoundingBox::operator=(const BoundingBox& rhs)
|
||||
{
|
||||
m_min = rhs.m_min;
|
||||
m_max = rhs.m_max;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Initialize bounding box
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBox::reset()
|
||||
{
|
||||
const double maxDouble = std::numeric_limits<double>::max();
|
||||
|
||||
m_max.set(-maxDouble, -maxDouble, -maxDouble);
|
||||
m_min.set( maxDouble, maxDouble, maxDouble);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns false if no input has been given
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool BoundingBox::isValid() const
|
||||
{
|
||||
if (m_min.x() <= m_max.x() &&
|
||||
m_min.y() <= m_max.y() &&
|
||||
m_min.z() <= m_max.z())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBox::add(const Vec3d& point)
|
||||
{
|
||||
if (point.x() < m_min.x()) m_min.x() = point.x();
|
||||
if (point.y() < m_min.y()) m_min.y() = point.y();
|
||||
if (point.z() < m_min.z()) m_min.z() = point.z();
|
||||
|
||||
if (point.x() > m_max.x()) m_max.x() = point.x();
|
||||
if (point.y() > m_max.y()) m_max.y() = point.y();
|
||||
if (point.z() > m_max.z()) m_max.z() = point.z();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBox::add(const Vec3f& point)
|
||||
{
|
||||
if (point.x() < m_min.x()) m_min.x() = point.x();
|
||||
if (point.y() < m_min.y()) m_min.y() = point.y();
|
||||
if (point.z() < m_min.z()) m_min.z() = point.z();
|
||||
|
||||
if (point.x() > m_max.x()) m_max.x() = point.x();
|
||||
if (point.y() > m_max.y()) m_max.y() = point.y();
|
||||
if (point.z() > m_max.z()) m_max.z() = point.z();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBox::add(const Vec3dArray& points)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < points.size(); i++)
|
||||
{
|
||||
add(points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBox::add(const Vec3fArray& points)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < points.size(); i++)
|
||||
{
|
||||
add(points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBox::add(const BoundingBox& bb)
|
||||
{
|
||||
if (bb.isValid())
|
||||
{
|
||||
add(bb.min());
|
||||
add(bb.max());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Computes center of the bounding box
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Vec3d BoundingBox::center() const
|
||||
{
|
||||
CVF_TIGHT_ASSERT(isValid());
|
||||
|
||||
return (m_min + m_max) / 2.0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Computes the total size of the bounding box
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Vec3d BoundingBox::extent() const
|
||||
{
|
||||
CVF_TIGHT_ASSERT(isValid());
|
||||
|
||||
return (m_max - m_min);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Compute radius as half the length of the box's diagonal
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double BoundingBox::radius() const
|
||||
{
|
||||
CVF_TIGHT_ASSERT(isValid());
|
||||
|
||||
return extent().length() / 2.0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const Vec3d& BoundingBox::min() const
|
||||
{
|
||||
CVF_TIGHT_ASSERT(isValid());
|
||||
|
||||
return m_min;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const Vec3d& BoundingBox::max() const
|
||||
{
|
||||
CVF_TIGHT_ASSERT(isValid());
|
||||
|
||||
return m_max;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Check if the bounding box contains the specified point
|
||||
///
|
||||
/// Note that a point on the box's surface is classified as being contained
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool BoundingBox::contains(const Vec3d& point) const
|
||||
{
|
||||
CVF_TIGHT_ASSERT(isValid());
|
||||
|
||||
if (point.x() >= m_min.x() && point.x() <= m_max.x() &&
|
||||
point.y() >= m_min.y() && point.y() <= m_max.y() &&
|
||||
point.z() >= m_min.z() && point.z() <= m_max.z())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool BoundingBox::intersects(const BoundingBox& box) const
|
||||
{
|
||||
CVF_TIGHT_ASSERT(isValid());
|
||||
CVF_TIGHT_ASSERT(box.isValid());
|
||||
|
||||
if (m_max.x() < box.m_min.x() || m_min.x() > box.m_max.x()) return false;
|
||||
if (m_max.y() < box.m_min.y() || m_min.y() > box.m_max.y()) return false;
|
||||
if (m_max.z() < box.m_min.z() || m_min.z() > box.m_max.z()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Get corner points of box
|
||||
///
|
||||
/// \param corners Array of Vec3d. Must be allocated 8 vectors long.
|
||||
///
|
||||
/// <PRE>
|
||||
/// 7---------6
|
||||
/// /| /| |z
|
||||
/// / | / | | / y
|
||||
/// 4---------5 | |/
|
||||
/// | 3------|--2 *---x
|
||||
/// | / | /
|
||||
/// |/ |/
|
||||
/// 0---------1 </PRE>
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBox::cornerVertices(Vec3d corners[8]) const
|
||||
{
|
||||
corners[0].set(m_min.x(), m_min.y(), m_min.z());
|
||||
corners[1].set(m_max.x(), m_min.y(), m_min.z());
|
||||
corners[2].set(m_max.x(), m_max.y(), m_min.z());
|
||||
corners[3].set(m_min.x(), m_max.y(), m_min.z());
|
||||
corners[4].set(m_min.x(), m_min.y(), m_max.z());
|
||||
corners[5].set(m_max.x(), m_min.y(), m_max.z());
|
||||
corners[6].set(m_max.x(), m_max.y(), m_max.z());
|
||||
corners[7].set(m_min.x(), m_max.y(), m_max.z());
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Expands the bounding box by the given amount in all three directions
|
||||
///
|
||||
/// If a bounding box is expanded by 2, the bounding box's size will increase by 2 in each direction
|
||||
/// \sa extent()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBox::expand(double amount)
|
||||
{
|
||||
double half = amount/2;
|
||||
m_min.x() -= half;
|
||||
m_min.y() -= half;
|
||||
m_min.z() -= half;
|
||||
m_max.x() += half;
|
||||
m_max.y() += half;
|
||||
m_max.z() += half;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Transform the min and max coordinate with the given transformation matrix
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBox::transform(const Mat4d& matrix)
|
||||
{
|
||||
// Check if box is invalid, and don't transform if so
|
||||
if (!isValid()) return;
|
||||
|
||||
BoundingBox newBox;
|
||||
newBox.reset();
|
||||
|
||||
Vec3d node;
|
||||
|
||||
node.set(m_min.x(), m_min.y(), m_min.z());
|
||||
node.transformPoint(matrix);
|
||||
newBox.add(node);
|
||||
|
||||
node.set(m_max.x(), m_min.y(), m_min.z());
|
||||
node.transformPoint(matrix);
|
||||
newBox.add(node);
|
||||
|
||||
node.set(m_max.x(), m_max.y(), m_min.z());
|
||||
node.transformPoint(matrix);
|
||||
newBox.add(node);
|
||||
|
||||
node.set(m_min.x(), m_max.y(), m_min.z());
|
||||
node.transformPoint(matrix);
|
||||
newBox.add(node);
|
||||
|
||||
node.set(m_min.x(), m_min.y(), m_max.z());
|
||||
node.transformPoint(matrix);
|
||||
newBox.add(node);
|
||||
|
||||
node.set(m_max.x(), m_min.y(), m_max.z());
|
||||
node.transformPoint(matrix);
|
||||
newBox.add(node);
|
||||
|
||||
node.set(m_max.x(), m_max.y(), m_max.z());
|
||||
node.transformPoint(matrix);
|
||||
newBox.add(node);
|
||||
|
||||
node.set(m_min.x(), m_max.y(), m_max.z());
|
||||
node.transformPoint(matrix);
|
||||
newBox.add(node);
|
||||
|
||||
*this = newBox;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns this BoundingBox transformed with the given transformation matrix
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const BoundingBox BoundingBox::getTransformed(const Mat4d& matrix) const
|
||||
{
|
||||
BoundingBox box(*this);
|
||||
box.transform(matrix);
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
String BoundingBox::toString() const
|
||||
{
|
||||
String str = "BoundingBox:";
|
||||
str += " min: x=" + String::number(m_min.x()) + " y=" + String::number(m_min.y()) + " z=" + String::number(m_min.z());
|
||||
str += " max: x=" + String::number(m_max.x()) + " y=" + String::number(m_max.y()) + " z=" + String::number(m_max.z());
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
77
VisualizationModules/LibGeometry/cvfBoundingBox.h
Normal file
77
VisualizationModules/LibGeometry/cvfBoundingBox.h
Normal file
@@ -0,0 +1,77 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfArray.h"
|
||||
#include "cvfMatrix4.h"
|
||||
#include "cvfString.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Axis aligned bounding box
|
||||
//
|
||||
//==================================================================================================
|
||||
class BoundingBox
|
||||
{
|
||||
public:
|
||||
BoundingBox();
|
||||
BoundingBox(const Vec3f& min, const Vec3f& max);
|
||||
BoundingBox(const Vec3d& min, const Vec3d& max);
|
||||
BoundingBox(const BoundingBox& other);
|
||||
|
||||
BoundingBox& operator=(const BoundingBox& rhs);
|
||||
|
||||
void reset();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
void add(const Vec3f& vertex);
|
||||
void add(const Vec3d& vertex);
|
||||
void add(const Vec3fArray& vertices);
|
||||
void add(const Vec3dArray& vertices);
|
||||
void add(const BoundingBox& bb);
|
||||
|
||||
const Vec3d& min() const;
|
||||
const Vec3d& max() const;
|
||||
|
||||
Vec3d center() const;
|
||||
Vec3d extent() const;
|
||||
double radius() const;
|
||||
|
||||
bool contains(const Vec3d& point) const;
|
||||
bool intersects(const BoundingBox& box) const;
|
||||
|
||||
void cornerVertices(Vec3d corners[8]) const;
|
||||
|
||||
void expand(double amount);
|
||||
void transform(const Mat4d& matrix);
|
||||
const BoundingBox getTransformed(const Mat4d& matrix) const;
|
||||
|
||||
String toString() const;
|
||||
|
||||
private:
|
||||
Vec3d m_min;
|
||||
Vec3d m_max;
|
||||
};
|
||||
|
||||
}
|
||||
173
VisualizationModules/LibGeometry/cvfBoxGenerator.cpp
Normal file
173
VisualizationModules/LibGeometry/cvfBoxGenerator.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfBoxGenerator.h"
|
||||
#include "cvfPatchGenerator.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::BoxGenerator
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Generates axis aligned box
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Default constructor
|
||||
///
|
||||
/// Will generate a box with one corner in (0,0,0) and the other corner in (1,1,1).
|
||||
/// Tesselation will be done using one quad for each of the box's six faces.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
BoxGenerator::BoxGenerator()
|
||||
: m_minCoord(0, 0, 0),
|
||||
m_maxCoord(1, 1, 1),
|
||||
m_subdivisions(1, 1, 1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoxGenerator::setMinMax(const Vec3d& minCoord, const Vec3d& maxCoord)
|
||||
{
|
||||
m_minCoord = minCoord;
|
||||
m_maxCoord = maxCoord;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoxGenerator::setOriginAndExtent(const Vec3d& origin, const Vec3d& extent)
|
||||
{
|
||||
m_minCoord = origin;
|
||||
m_maxCoord = origin + extent;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoxGenerator::setCenterAndExtent(const Vec3d& center, const Vec3d& extent)
|
||||
{
|
||||
m_minCoord = center - extent/2;
|
||||
m_maxCoord = center + extent/2;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoxGenerator::setSubdivisions(uint subdivX, uint subdivY, uint subdivZ)
|
||||
{
|
||||
CVF_ASSERT(subdivX > 0);
|
||||
CVF_ASSERT(subdivY > 0);
|
||||
CVF_ASSERT(subdivZ > 0);
|
||||
|
||||
m_subdivisions.set(subdivX, subdivY, subdivZ);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoxGenerator::generate(GeometryBuilder* builder)
|
||||
{
|
||||
uint cellCountX = m_subdivisions.x();
|
||||
uint cellCountY = m_subdivisions.y();
|
||||
uint cellCountZ = m_subdivisions.z();
|
||||
CVF_ASSERT(cellCountX > 0);
|
||||
CVF_ASSERT(cellCountY > 0);
|
||||
CVF_ASSERT(cellCountZ > 0);
|
||||
|
||||
if (cellCountX == 1 && cellCountY == 1 && cellCountZ == 1)
|
||||
{
|
||||
GeometryUtils::createBox(Vec3f(m_minCoord), Vec3f(m_maxCoord), builder);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Face ordering is
|
||||
//
|
||||
// *---------* Faces:
|
||||
// /| /| |z 0 bottom
|
||||
// / | / | | /y 1 top
|
||||
// *---------* | |/ 2 front
|
||||
// | 3------|--* *---x 3 right
|
||||
// | / | / 4 back
|
||||
// |/ |/ 5 left
|
||||
// *---------*
|
||||
|
||||
const Vec3d extent(m_maxCoord - m_minCoord);
|
||||
|
||||
PatchGenerator patchGen;
|
||||
|
||||
// Bottom
|
||||
patchGen.setOrigin(Vec3d(m_minCoord.x(), m_minCoord.y(), m_minCoord.z()));
|
||||
patchGen.setAxes(Vec3d::Y_AXIS, Vec3d::X_AXIS);
|
||||
patchGen.setExtent(extent.y(), extent.x());
|
||||
patchGen.setSubdivisions(cellCountY, cellCountX);
|
||||
patchGen.generate(builder);
|
||||
|
||||
// Top
|
||||
patchGen.setOrigin(Vec3d(m_minCoord.x(), m_minCoord.y(), m_maxCoord.z()));
|
||||
patchGen.setAxes(Vec3d::X_AXIS, Vec3d::Y_AXIS);
|
||||
patchGen.setExtent(extent.x(), extent.y());
|
||||
patchGen.setSubdivisions(cellCountX, cellCountY);
|
||||
patchGen.generate(builder);
|
||||
|
||||
// Front
|
||||
patchGen.setOrigin(Vec3d(m_minCoord.x(), m_minCoord.y(), m_minCoord.z()));
|
||||
patchGen.setAxes(Vec3d::X_AXIS, Vec3d::Z_AXIS);
|
||||
patchGen.setExtent(extent.x(), extent.z());
|
||||
patchGen.setSubdivisions(cellCountX, cellCountZ);
|
||||
patchGen.generate(builder);
|
||||
|
||||
// Right
|
||||
patchGen.setOrigin(Vec3d(m_maxCoord.x(), m_minCoord.y(), m_minCoord.z()));
|
||||
patchGen.setAxes(Vec3d::Y_AXIS, Vec3d::Z_AXIS);
|
||||
patchGen.setExtent(extent.y(), extent.z());
|
||||
patchGen.setSubdivisions(cellCountY, cellCountZ);
|
||||
patchGen.generate(builder);
|
||||
|
||||
// Back
|
||||
patchGen.setOrigin(Vec3d(m_maxCoord.x(), m_maxCoord.y(), m_minCoord.z()));
|
||||
patchGen.setAxes(-Vec3d::X_AXIS, Vec3d::Z_AXIS);
|
||||
patchGen.setExtent(extent.x(), extent.z());
|
||||
patchGen.setSubdivisions(cellCountX, cellCountZ);
|
||||
patchGen.generate(builder);
|
||||
|
||||
// Left
|
||||
patchGen.setOrigin(Vec3d(m_minCoord.x(), m_maxCoord.y(), m_minCoord.z()));
|
||||
patchGen.setAxes(-Vec3d::Y_AXIS, Vec3d::Z_AXIS);
|
||||
patchGen.setExtent(extent.y(), extent.z());
|
||||
patchGen.setSubdivisions(cellCountY, cellCountZ);
|
||||
patchGen.generate(builder);
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
54
VisualizationModules/LibGeometry/cvfBoxGenerator.h
Normal file
54
VisualizationModules/LibGeometry/cvfBoxGenerator.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfVector3.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
class GeometryBuilder;
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Generates an axis aligned box
|
||||
//
|
||||
//==================================================================================================
|
||||
class BoxGenerator
|
||||
{
|
||||
public:
|
||||
BoxGenerator();
|
||||
|
||||
void setMinMax(const Vec3d& minCoord, const Vec3d& maxCoord);
|
||||
void setOriginAndExtent(const Vec3d& origin, const Vec3d& extent);
|
||||
void setCenterAndExtent(const Vec3d& center, const Vec3d& extent);
|
||||
|
||||
void setSubdivisions(uint subdivX, uint subdivY, uint subdivZ);
|
||||
|
||||
void generate(GeometryBuilder* builder);
|
||||
|
||||
private:
|
||||
Vec3d m_minCoord;
|
||||
Vec3d m_maxCoord;
|
||||
Vec3ui m_subdivisions; // Number of cells/quads in each direction. Default (1, 1, 1)
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
112
VisualizationModules/LibGeometry/cvfEdgeKey.cpp
Normal file
112
VisualizationModules/LibGeometry/cvfEdgeKey.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfEdgeKey.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::EdgeKey
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
EdgeKey::EdgeKey(uint vertexIdx1, uint vertexIdx2)
|
||||
{
|
||||
if (vertexIdx1 <= vertexIdx2)
|
||||
{
|
||||
m_vertexIdx1 = vertexIdx1;
|
||||
m_vertexIdx2 = vertexIdx2;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vertexIdx1 = vertexIdx2;
|
||||
m_vertexIdx2 = vertexIdx1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool EdgeKey::operator==(const EdgeKey& rhs) const
|
||||
{
|
||||
if (m_vertexIdx1 == rhs.m_vertexIdx1 && m_vertexIdx2 == rhs.m_vertexIdx2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool EdgeKey::operator<(const EdgeKey& rhs) const
|
||||
{
|
||||
if (m_vertexIdx1 == rhs.m_vertexIdx1)
|
||||
{
|
||||
return (m_vertexIdx2 < rhs.m_vertexIdx2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (m_vertexIdx1 < rhs.m_vertexIdx1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int64 EdgeKey::toKeyVal() const
|
||||
{
|
||||
int64 edgeKey = m_vertexIdx1;
|
||||
edgeKey <<= 32;
|
||||
edgeKey += m_vertexIdx2;
|
||||
|
||||
return edgeKey;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
EdgeKey EdgeKey::fromkeyVal(int64 edgeKeyVal)
|
||||
{
|
||||
uint vertexIdx2 = static_cast<uint>(edgeKeyVal);
|
||||
|
||||
edgeKeyVal >>= 32;
|
||||
uint vertexIdx1 = static_cast<uint>(edgeKeyVal);
|
||||
|
||||
return EdgeKey(vertexIdx1, vertexIdx2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
53
VisualizationModules/LibGeometry/cvfEdgeKey.h
Normal file
53
VisualizationModules/LibGeometry/cvfEdgeKey.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class EdgeKey
|
||||
{
|
||||
public:
|
||||
EdgeKey(uint vertexIdx1, uint vertexIdx2);
|
||||
|
||||
bool operator==(const EdgeKey& rhs) const;
|
||||
bool operator<(const EdgeKey& rhs) const;
|
||||
|
||||
uint index1() const { return m_vertexIdx1; }
|
||||
uint index2() const { return m_vertexIdx2; }
|
||||
|
||||
int64 toKeyVal() const;
|
||||
|
||||
static EdgeKey fromkeyVal(int64 edgeKeyVal);
|
||||
|
||||
private:
|
||||
uint m_vertexIdx1; // The constructor ensures that index 1 is always the smallest
|
||||
uint m_vertexIdx2; // of the two indices
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
213
VisualizationModules/LibGeometry/cvfFrustum.cpp
Normal file
213
VisualizationModules/LibGeometry/cvfFrustum.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfBoundingBox.h"
|
||||
#include "cvfFrustum.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::Frustum
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Class defining a frustum
|
||||
///
|
||||
/// The frustum consists of 6 \link Plane Planes\endlink
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Default constructor
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Frustum::Frustum()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Copy constructor
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Frustum::Frustum(const Frustum& other)
|
||||
: Object()
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Destructor
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Frustum::~Frustum()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Assignment operator
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const Frustum& Frustum::operator=(const Frustum& rhs)
|
||||
{
|
||||
m_planes.clear();
|
||||
|
||||
std::map<int, Plane>::const_iterator it;
|
||||
for (it = rhs.m_planes.begin(); it != rhs.m_planes.end(); it++)
|
||||
{
|
||||
m_planes[it->first] = it->second;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Equality operator
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool Frustum::operator==(const Frustum& rhs) const
|
||||
{
|
||||
if (m_planes.size() != rhs.m_planes.size()) return false;
|
||||
|
||||
std::map<int, Plane>::const_iterator thisIt, rhsIt;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < m_planes.size(); i++)
|
||||
{
|
||||
int sideIdx = static_cast<int>(i);
|
||||
|
||||
thisIt = m_planes.find(sideIdx);
|
||||
rhsIt = rhs.m_planes.find(sideIdx);
|
||||
|
||||
if (thisIt->first != rhsIt->first) return false;
|
||||
if (thisIt->second != rhsIt->second) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Inequality operator
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool Frustum::operator!=(const Frustum& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Set one of the planes building up the frustum
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void Frustum::setPlane(Side side, const Plane& plane)
|
||||
{
|
||||
CVF_ASSERT(side < COUNT);
|
||||
CVF_ASSERT(plane.isValid());
|
||||
|
||||
m_planes[side] = plane;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Get one given Plane of the frustum.
|
||||
///
|
||||
/// \return The Plane queried or an invalid Plane if it does not exist.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Plane Frustum::plane(Side side) const
|
||||
{
|
||||
std::map<int, Plane>::const_iterator it = m_planes.find(side);
|
||||
|
||||
return (it != m_planes.end()) ? it->second : Plane();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Transforms all planes in the frustum with the given matrix
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void Frustum::transform(const Mat4d& matrix)
|
||||
{
|
||||
std::map<int, Plane>::iterator it;
|
||||
for (it = m_planes.begin(); it != m_planes.end(); it++)
|
||||
{
|
||||
it->second.transform(matrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test point to see if it's outside the frustum or not
|
||||
///
|
||||
/// \return true if outside or exactly on the boundary. false if inside.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool Frustum::isOutside(const Vec3d& point) const
|
||||
{
|
||||
CVF_ASSERT(m_planes.size() == 6);
|
||||
|
||||
std::map<int, Plane>::const_iterator it;
|
||||
for (it = m_planes.begin(); it != m_planes.end(); it++)
|
||||
{
|
||||
if (it->second.distanceSquared(point) < 0.0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test bounding box to see if it's outside the frustum or not
|
||||
///
|
||||
/// \return true if outside or exactly on the boundary. false if inside.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool Frustum::isOutside(const BoundingBox& bbox) const
|
||||
{
|
||||
CVF_ASSERT(m_planes.size() == 6);
|
||||
|
||||
const Vec3d& boxMin = bbox.min();
|
||||
const Vec3d& boxMax = bbox.max();
|
||||
|
||||
Vec3d point;
|
||||
Vec3d planeNormal;
|
||||
|
||||
std::map<int, Plane>::const_iterator it;
|
||||
for (it = m_planes.begin(); it != m_planes.end(); it++)
|
||||
{
|
||||
planeNormal = it->second.normal();
|
||||
|
||||
point.x() = (planeNormal.x() <= 0.0) ? boxMin.x() : boxMax.x();
|
||||
point.y() = (planeNormal.y() <= 0.0) ? boxMin.y() : boxMax.y();
|
||||
point.z() = (planeNormal.z() <= 0.0) ? boxMin.z() : boxMax.z();
|
||||
|
||||
if (it->second.distanceSquared(point) < 0.0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
73
VisualizationModules/LibGeometry/cvfFrustum.h
Normal file
73
VisualizationModules/LibGeometry/cvfFrustum.h
Normal file
@@ -0,0 +1,73 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfObject.h"
|
||||
#include "cvfPlane.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace cvf {
|
||||
|
||||
class BoundingBox;
|
||||
|
||||
|
||||
//=================================================================================================
|
||||
//
|
||||
// Frustum class
|
||||
//
|
||||
//=================================================================================================
|
||||
class Frustum : public Object
|
||||
{
|
||||
public:
|
||||
/// Sides of the frustum
|
||||
enum Side
|
||||
{
|
||||
BOTTOM = 0, // Index based -> Must start with zero
|
||||
TOP,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
FRONT,
|
||||
BACK,
|
||||
COUNT ///< Number of sides
|
||||
};
|
||||
|
||||
public:
|
||||
Frustum();
|
||||
Frustum(const Frustum& other);
|
||||
~Frustum();
|
||||
|
||||
const Frustum& operator=(const Frustum& other);
|
||||
bool operator==(const Frustum& other) const;
|
||||
bool operator!=(const Frustum& other) const;
|
||||
|
||||
void setPlane(Side side, const Plane& plane);
|
||||
Plane plane(Side side) const;
|
||||
|
||||
void transform(const Mat4d& matrix);
|
||||
|
||||
bool isOutside(const Vec3d& point) const;
|
||||
bool isOutside(const BoundingBox& bbox) const;
|
||||
|
||||
private:
|
||||
std::map<int, Plane> m_planes;
|
||||
};
|
||||
|
||||
}
|
||||
347
VisualizationModules/LibGeometry/cvfGeometryBuilder.cpp
Normal file
347
VisualizationModules/LibGeometry/cvfGeometryBuilder.cpp
Normal file
@@ -0,0 +1,347 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfGeometryBuilder.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::GeometryBuilder
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Abstract base class for building geometry using the Builder pattern.
|
||||
/// \sa GeometryUtils
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::setTotalVertexCountHint(size_t totalVertexCountHint)
|
||||
{
|
||||
CVF_UNUSED(totalVertexCountHint);
|
||||
// Nothing here, may be used in derived classes
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// \fn virtual int GeometryBuilder::addVertices(const Vec3fArray& vertices) = 0;
|
||||
///
|
||||
/// Add vertex coordinates
|
||||
///
|
||||
/// \return The resulting index of the first vertex in the \a vertices array.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// \fn virtual int GeometryBuilder::addTriangle(int i0, int i1, int i2) = 0;
|
||||
///
|
||||
/// Add a single triangle by specifying the indices into the vertex array.
|
||||
///
|
||||
/// \sa addTriangles()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Add multiple triangles
|
||||
///
|
||||
/// \remarks There must be at least 3 entries in the \a indices array, and the total number of
|
||||
/// entries must be a multiple of 3.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addTriangles(const UIntArray& indices)
|
||||
{
|
||||
size_t numIndices = indices.size();
|
||||
CVF_ASSERT(numIndices >= 3);
|
||||
CVF_ASSERT(numIndices % 3 == 0);
|
||||
|
||||
size_t numTriangles = numIndices/3;
|
||||
CVF_ASSERT(numTriangles >= 1);
|
||||
CVF_ASSERT(3*numTriangles == numIndices);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numTriangles; i++)
|
||||
{
|
||||
addTriangle(indices[3*i], indices[3*i + 1], indices[3*i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addTriangles(const IntArray& indices)
|
||||
{
|
||||
size_t numIndices = indices.size();
|
||||
CVF_ASSERT(numIndices >= 3);
|
||||
CVF_ASSERT(numIndices % 3 == 0);
|
||||
|
||||
size_t numTriangles = numIndices/3;
|
||||
CVF_ASSERT(numTriangles >= 1);
|
||||
CVF_ASSERT(3*numTriangles == numIndices);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numTriangles; i++)
|
||||
{
|
||||
CVF_ASSERT(indices[3*i] >= 0 && indices[3*i + 1] && indices[3*i + 2]);
|
||||
addTriangle(static_cast<uint>(indices[3*i]), static_cast<uint>(indices[3*i + 1]), static_cast<uint>(indices[3*i + 2]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Add a triangle fan
|
||||
///
|
||||
/// Vertex ordering for triangle fans:
|
||||
/// <PRE>
|
||||
/// v4 *-------* v3 Resulting triangles:
|
||||
/// \ / \ t1: v0, v1, v2
|
||||
/// \ / \ t2: v0, v2, v3
|
||||
/// \ / \ t3: v0, v3, v4
|
||||
/// v0 *-------* v2
|
||||
/// \ /
|
||||
/// \ /
|
||||
/// \ /
|
||||
/// * v1 </PRE>
|
||||
///
|
||||
/// \remarks The number of entries in the \a indices array must be at least 3.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addTriangleFan(const UIntArray& indices)
|
||||
{
|
||||
size_t numIndices = indices.size();
|
||||
CVF_ASSERT(numIndices >= 3);
|
||||
|
||||
size_t numTriangles = numIndices - 2;
|
||||
CVF_ASSERT(numTriangles >= 1);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numTriangles; i++)
|
||||
{
|
||||
addTriangle(indices[0], indices[i + 1], indices[i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Add a triangle strip
|
||||
///
|
||||
/// Vertex ordering for triangle strips:
|
||||
/// <PRE>
|
||||
/// v0 v2 v4 Resulting triangles:
|
||||
/// *-------*-------* t1: v0, v1, v2
|
||||
/// \ / \ / \ t2: v2, v1, v3
|
||||
/// \ / \ / \ t3: v2, v3, v4
|
||||
/// \ / \ / \ t4: v4, v3, v5
|
||||
/// *-------*-------*
|
||||
/// v1 v3 v5 </PRE>
|
||||
///
|
||||
/// \remarks The number of entries in the \a indices array must be at least 3.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addTriangleStrip(const UIntArray& indices)
|
||||
{
|
||||
size_t numIndices = indices.size();
|
||||
CVF_ASSERT(numIndices >= 3);
|
||||
|
||||
size_t numTriangles = numIndices - 2;
|
||||
CVF_ASSERT(numTriangles >= 1);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numTriangles; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
addTriangle(indices[i], indices[i + 1], indices[i + 2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
addTriangle(indices[i + 1], indices[i], indices[i + 2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addTriangleByVertices(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2)
|
||||
{
|
||||
Vec3fArray verts;
|
||||
verts.resize(3);
|
||||
verts[0] = v0;
|
||||
verts[1] = v1;
|
||||
verts[2] = v2;
|
||||
|
||||
uint firstVertexIdx = addVertices(verts);
|
||||
|
||||
addTriangle(firstVertexIdx, firstVertexIdx + 1, firstVertexIdx + 2);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Add a single quad by specifying the indices into the vertex array
|
||||
///
|
||||
/// The default implementation will split the quad into two triangles (i0,i1,i2 and i0,i2,i3) and
|
||||
/// add them using addTriangle().
|
||||
///
|
||||
/// \sa addTriangle(), addQuads()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addQuad(uint i0, uint i1, uint i2, uint i3)
|
||||
{
|
||||
addTriangle(i0, i1, i2);
|
||||
addTriangle(i0, i2, i3);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Add multiple quads
|
||||
///
|
||||
/// The default implementation utilizes addQuad() to add each quad separately.
|
||||
///
|
||||
/// \remarks There must be at least 4 entries in the \a indices array, and the total number of
|
||||
/// entries must be a multiple of 4.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addQuads(const UIntArray& indices)
|
||||
{
|
||||
size_t numIndices = indices.size();
|
||||
CVF_ASSERT(numIndices >= 4);
|
||||
CVF_ASSERT(numIndices % 4 == 0);
|
||||
|
||||
size_t numQuads = numIndices/4;
|
||||
CVF_ASSERT(numQuads >= 1);
|
||||
CVF_ASSERT(4*numQuads == numIndices);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numQuads; i++)
|
||||
{
|
||||
addQuad(indices[4*i], indices[4*i + 1], indices[4*i + 2], indices[4*i + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addQuads(const IntArray& indices)
|
||||
{
|
||||
size_t numIndices = indices.size();
|
||||
CVF_ASSERT(numIndices >= 4);
|
||||
CVF_ASSERT(numIndices % 4 == 0);
|
||||
|
||||
size_t numQuads = numIndices/4;
|
||||
CVF_ASSERT(numQuads >= 1);
|
||||
CVF_ASSERT(4*numQuads == numIndices);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numQuads; i++)
|
||||
{
|
||||
CVF_ASSERT(indices[4*i] >= 0 && indices[4*i + 1] && indices[4*i + 2] && indices[4*i + 3]);
|
||||
addQuad(static_cast<uint>(indices[4*i]), static_cast<uint>(indices[4*i + 1]), static_cast<uint>(indices[4*i + 2]), static_cast<uint>(indices[4*i + 3]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Add a quad strip
|
||||
///
|
||||
/// Vertex ordering for quad strips:
|
||||
/// <PRE>
|
||||
/// v0 v2 v4 v6 Resulting quads:
|
||||
/// *-----*-----*-----* q1: v0, v1, v3, v2
|
||||
/// | | | | q2: v2, v3, v5, v4
|
||||
/// | | | | q3: v4, v5, v7, v6
|
||||
/// | | | |
|
||||
/// *-----*-----*-----*
|
||||
/// v1 v3 v5 v7 </PRE>
|
||||
///
|
||||
/// \remarks There must be at least 4 entries in the \a indices array, and the total number of
|
||||
/// entries must be a multiple of 2.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addQuadStrip(const UIntArray& indices)
|
||||
{
|
||||
size_t numIndices = indices.size();
|
||||
CVF_ASSERT(numIndices >= 4);
|
||||
CVF_ASSERT(numIndices % 2 == 0);
|
||||
|
||||
size_t numQuads = (numIndices - 2)/2;
|
||||
CVF_ASSERT(numQuads >= 1);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numQuads; i++)
|
||||
{
|
||||
addQuad(indices[2*i], indices[2*i + 1], indices[2*i + 3], indices[2*i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addQuadByVertices(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, const Vec3f& v3)
|
||||
{
|
||||
Vec3fArray verts;
|
||||
verts.resize(4);
|
||||
verts[0] = v0;
|
||||
verts[1] = v1;
|
||||
verts[2] = v2;
|
||||
verts[3] = v3;
|
||||
|
||||
uint firstVertexIdx = addVertices(verts);
|
||||
|
||||
addQuad(firstVertexIdx, firstVertexIdx + 1, firstVertexIdx + 2, firstVertexIdx + 3);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Add one face
|
||||
///
|
||||
/// The type of primitive added will be determined from the number of indices passed in \a indices
|
||||
///
|
||||
/// \remarks Currently, points and lines are not supported. Faces with more than 4 indices will
|
||||
/// be triangulated using fanning
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilder::addFace(const UIntArray& indices)
|
||||
{
|
||||
size_t numIndices = indices.size();
|
||||
CVF_ASSERT(numIndices >= 3);
|
||||
|
||||
if (numIndices == 3)
|
||||
{
|
||||
addTriangle(indices[0], indices[1], indices[2]);
|
||||
}
|
||||
else if (numIndices == 4)
|
||||
{
|
||||
addQuad(indices[0], indices[1], indices[2], indices[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t numTriangles = numIndices - 2;
|
||||
size_t i;
|
||||
for (i = 0; i < numTriangles; i++)
|
||||
{
|
||||
addTriangle(indices[0], indices[i + 1], indices[i + 2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
61
VisualizationModules/LibGeometry/cvfGeometryBuilder.h
Normal file
61
VisualizationModules/LibGeometry/cvfGeometryBuilder.h
Normal file
@@ -0,0 +1,61 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfObject.h"
|
||||
#include "cvfArray.h"
|
||||
#include "cvfMatrix4.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Abstract base class for building geometry using the Builder pattern
|
||||
//
|
||||
//==================================================================================================
|
||||
class GeometryBuilder : public Object
|
||||
{
|
||||
public:
|
||||
virtual void setTotalVertexCountHint(size_t totalVertexCountHint);
|
||||
|
||||
virtual uint addVertices(const Vec3fArray& vertices) = 0;
|
||||
virtual uint vertexCount() const = 0;
|
||||
virtual void transformVertexRange(uint startIdx, uint endIdx, const Mat4f& mat) = 0;
|
||||
|
||||
virtual void addTriangle(uint i0, uint i1, uint i2) = 0;
|
||||
virtual void addTriangles(const UIntArray& indices);
|
||||
virtual void addTriangles(const IntArray& indices);
|
||||
virtual void addTriangleFan(const UIntArray& indices);
|
||||
virtual void addTriangleStrip(const UIntArray& indices);
|
||||
virtual void addTriangleByVertices(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2);
|
||||
|
||||
virtual void addQuad(uint i0, uint i1, uint i2, uint i3);
|
||||
virtual void addQuads(const UIntArray& indices);
|
||||
virtual void addQuads(const IntArray& indices);
|
||||
virtual void addQuadStrip(const UIntArray& indices);
|
||||
virtual void addQuadByVertices(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, const Vec3f& v3);
|
||||
|
||||
virtual void addFace(const UIntArray& indices);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
145
VisualizationModules/LibGeometry/cvfGeometryBuilderFaceList.cpp
Normal file
145
VisualizationModules/LibGeometry/cvfGeometryBuilderFaceList.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfGeometryBuilderFaceList.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::GeometryBuilderFaceList
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Builds geometry represented as a face list.
|
||||
///
|
||||
/// A face list is an array of integers. The first integer is the number of connectivity indices for
|
||||
/// the first face, followed by an integer for each vertex int the face, which are indices into
|
||||
/// the vertex array. For example, if the face list contains (3 0 1 2), then a triangle is formed
|
||||
/// from the first three points in the vertex array. The next entry in the face list starts another
|
||||
/// face, and so on.
|
||||
///
|
||||
/// A face list representing a geometry with two triangles, one quad and finally one line would
|
||||
/// look something like this:
|
||||
/// \code
|
||||
/// 3, 0, 1, 2,
|
||||
/// 3, 0, 2, 3,
|
||||
/// 4, 4, 5, 6, 7,
|
||||
/// 2, 8, 9
|
||||
/// \endcode
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
GeometryBuilderFaceList::GeometryBuilderFaceList()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint GeometryBuilderFaceList::addVertices(const Vec3fArray& vertices)
|
||||
{
|
||||
uint numExistingVerts = static_cast<uint>(m_vertices.size());
|
||||
uint numNewVerts = static_cast<uint>(vertices.size());
|
||||
|
||||
uint i;
|
||||
for (i = 0; i < numNewVerts; i++)
|
||||
{
|
||||
m_vertices.push_back(vertices[i]);
|
||||
}
|
||||
|
||||
return numExistingVerts;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint GeometryBuilderFaceList::vertexCount() const
|
||||
{
|
||||
return static_cast<uint>(m_vertices.size());
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilderFaceList::transformVertexRange(uint startIdx, uint endIdx, const Mat4f& mat)
|
||||
{
|
||||
uint i;
|
||||
for (i = startIdx; i <= endIdx; i++)
|
||||
{
|
||||
m_vertices[i].transformPoint(mat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilderFaceList::addTriangle(uint i0, uint i1, uint i2)
|
||||
{
|
||||
m_faceList.push_back(3);
|
||||
m_faceList.push_back(i0);
|
||||
m_faceList.push_back(i1);
|
||||
m_faceList.push_back(i2);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilderFaceList::addQuad(uint i0, uint i1, uint i2, uint i3)
|
||||
{
|
||||
m_faceList.push_back(4);
|
||||
m_faceList.push_back(i0);
|
||||
m_faceList.push_back(i1);
|
||||
m_faceList.push_back(i2);
|
||||
m_faceList.push_back(i3);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<Vec3fArray> GeometryBuilderFaceList::vertices() const
|
||||
{
|
||||
ref<Vec3fArray> verts = new Vec3fArray(m_vertices);
|
||||
return verts;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UIntArray> GeometryBuilderFaceList::faceList() const
|
||||
{
|
||||
ref<UIntArray> fList = new UIntArray(m_faceList);
|
||||
return fList;
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfGeometryBuilder.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Concrete geometry builder class for building geometry to a face lists
|
||||
//
|
||||
//==================================================================================================
|
||||
class GeometryBuilderFaceList : public GeometryBuilder
|
||||
{
|
||||
public:
|
||||
GeometryBuilderFaceList();
|
||||
|
||||
virtual uint addVertices(const Vec3fArray& vertices);
|
||||
virtual uint vertexCount() const;
|
||||
virtual void transformVertexRange(uint startIdx, uint endIdx, const Mat4f& mat);
|
||||
|
||||
virtual void addTriangle(uint i0, uint i1, uint i2);
|
||||
virtual void addQuad(uint i0, uint i1, uint i2, uint i3);
|
||||
|
||||
ref<Vec3fArray> vertices() const;
|
||||
ref<UIntArray> faceList() const;
|
||||
|
||||
private:
|
||||
std::vector<Vec3f> m_vertices;
|
||||
std::vector<uint> m_faceList;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
133
VisualizationModules/LibGeometry/cvfGeometryBuilderTriangles.cpp
Normal file
133
VisualizationModules/LibGeometry/cvfGeometryBuilderTriangles.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfGeometryBuilderTriangles.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::GeometryBuilderTriangles
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Builds geometry represented as triangles.
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
GeometryBuilderTriangles::GeometryBuilderTriangles()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint GeometryBuilderTriangles::addVertices(const Vec3fArray& vertices)
|
||||
{
|
||||
uint numExistingVerts = static_cast<uint>(m_vertices.size());
|
||||
uint numNewVerts = static_cast<uint>(vertices.size());
|
||||
|
||||
uint i;
|
||||
for (i = 0; i < numNewVerts; i++)
|
||||
{
|
||||
m_vertices.push_back(vertices[i]);
|
||||
}
|
||||
|
||||
return numExistingVerts;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint GeometryBuilderTriangles::vertexCount() const
|
||||
{
|
||||
return static_cast<uint>(m_vertices.size());
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilderTriangles::transformVertexRange(uint startIdx, uint endIdx, const Mat4f& mat)
|
||||
{
|
||||
uint i;
|
||||
for (i = startIdx; i <= endIdx; i++)
|
||||
{
|
||||
m_vertices[i].transformPoint(mat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryBuilderTriangles::addTriangle(uint i0, uint i1, uint i2)
|
||||
{
|
||||
m_triangles.push_back(i0);
|
||||
m_triangles.push_back(i1);
|
||||
m_triangles.push_back(i2);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<Vec3fArray> GeometryBuilderTriangles::vertices() const
|
||||
{
|
||||
ref<Vec3fArray> verts = new Vec3fArray(m_vertices);
|
||||
return verts;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UIntArray> GeometryBuilderTriangles::triangles() const
|
||||
{
|
||||
ref<UIntArray> tris = new UIntArray(m_triangles);
|
||||
return tris;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UShortArray> GeometryBuilderTriangles::trianglesUShort() const
|
||||
{
|
||||
ref<UShortArray> tris = new UShortArray;
|
||||
|
||||
tris->resize(m_triangles.size());
|
||||
size_t i;
|
||||
for (i = 0; i < m_triangles.size(); i++)
|
||||
{
|
||||
tris->set(i, static_cast<ushort>(m_triangles[i]));
|
||||
}
|
||||
|
||||
return tris;
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
@@ -0,0 +1,52 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfGeometryBuilder.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Concrete geometry builder class for building geometry to only triangles
|
||||
//
|
||||
//==================================================================================================
|
||||
class GeometryBuilderTriangles : public GeometryBuilder
|
||||
{
|
||||
public:
|
||||
GeometryBuilderTriangles();
|
||||
|
||||
virtual uint addVertices(const Vec3fArray& vertices);
|
||||
virtual uint vertexCount() const;
|
||||
virtual void transformVertexRange(uint startIdx, uint endIdx, const Mat4f& mat);
|
||||
|
||||
virtual void addTriangle(uint i0, uint i1, uint i2);
|
||||
|
||||
ref<Vec3fArray> vertices() const;
|
||||
ref<UIntArray> triangles() const;
|
||||
ref<UShortArray> trianglesUShort() const;
|
||||
|
||||
private:
|
||||
std::vector<Vec3f> m_vertices;
|
||||
std::vector<uint> m_triangles;
|
||||
};
|
||||
|
||||
}
|
||||
881
VisualizationModules/LibGeometry/cvfGeometryUtils.cpp
Normal file
881
VisualizationModules/LibGeometry/cvfGeometryUtils.cpp
Normal file
@@ -0,0 +1,881 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfGeometryBuilder.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
#include "cvfMatrix4.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::GeometryUtils
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Static helper class for creating geometries from primitive shapes.
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Create a 2D patch
|
||||
///
|
||||
/// \param origin The start point of the patch
|
||||
/// \param uUnit Direction vector u. First point 'to the right of' origin is origin + uUnit.
|
||||
/// \param vUnit Direction vector v. Coordinates of first point 'above' origin is origin + vunit.
|
||||
/// \param uCellCount The number of cells/quads to generate along the uUnit dimension.
|
||||
/// \param vCellCount The number of cells/quads to generate along the vUnit dimension.
|
||||
/// \param builder Geometry builder to use when creating geometry
|
||||
///
|
||||
/// The figure below illustrates how the patch is constructed from the specified parameters.
|
||||
///
|
||||
/// <PRE>
|
||||
/// v8-----v9----v10----v11 Parameters: Resulting vertices:
|
||||
/// | | | | origin = (10,20,0) v0 = (10,20,0)
|
||||
/// origin | | | | uUnit = (2,0,0) v1 = (12,20,0)
|
||||
/// + vunit v4-----v5-----v6-----v7 |y vUnit = (0,1,0) v2 = (14,20,0)
|
||||
/// | | | | | uCellCount = 3 v3 = (16,20,0)
|
||||
/// | | | | | vCellCount = 2 v4 = (10,21,0)
|
||||
/// v0-----v1-----v2-----v3 *----x v5 = (12,21,0)
|
||||
/// origin origin :
|
||||
/// + uUnit </PRE>
|
||||
///
|
||||
/// The following quad connectivities will be produced:\n
|
||||
/// <TT> (v4,v0,v1,v5) (v5,v1,v2,v6) (v6,v2,v3,v5) ... (v10,v6,v7,v11)</TT>
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::createPatch(const Vec3f& origin, const Vec3f& uUnit, const Vec3f& vUnit, uint uCellCount, uint vCellCount, GeometryBuilder* builder)
|
||||
{
|
||||
CVF_ASSERT(uCellCount > 0);
|
||||
CVF_ASSERT(vCellCount > 0);
|
||||
|
||||
uint numVertices = (uCellCount + 1)*(vCellCount + 1);
|
||||
uint numQuads = uCellCount*vCellCount;
|
||||
|
||||
Vec3fArray vertices;
|
||||
vertices.reserve(numVertices);
|
||||
|
||||
uint u, v;
|
||||
for (v = 0; v <= vCellCount; v++)
|
||||
{
|
||||
for (u = 0; u <= uCellCount; u++)
|
||||
{
|
||||
vertices.add(origin + static_cast<float>(u)*uUnit + static_cast<float>(v)*vUnit);
|
||||
}
|
||||
}
|
||||
|
||||
uint baseNodeIdx = builder->addVertices(vertices);
|
||||
|
||||
UIntArray conn;
|
||||
conn.reserve(4*numQuads);
|
||||
|
||||
for (v = 0; v < vCellCount; v++)
|
||||
{
|
||||
for (u = 0; u < uCellCount; u++)
|
||||
{
|
||||
conn.add(baseNodeIdx + u + (v + 1)*(uCellCount + 1));
|
||||
conn.add(baseNodeIdx + u + v*(uCellCount + 1));
|
||||
conn.add(baseNodeIdx + u + 1 + v*(uCellCount + 1));
|
||||
conn.add(baseNodeIdx + u + 1 + (v + 1)*(uCellCount + 1));
|
||||
}
|
||||
}
|
||||
|
||||
builder->addQuads(conn);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Create a 3D solid box spanning diagonally from min to max
|
||||
///
|
||||
/// \param min The coordinate that represent one corner of the box.
|
||||
/// \param max The coordinate that lie diagonal from max on the opposite face of the box
|
||||
/// \param builder Geometry builder to use when creating geometry
|
||||
///
|
||||
/// This method creates a box with no shared vertices resulting in sharp corners during shading.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::createBox(const Vec3f& min, const Vec3f& max, GeometryBuilder* builder)
|
||||
{
|
||||
// The ordering of the faces is consistent with GLviewAPI's hexahedron element.
|
||||
// Note that the vertex ordering within a face is not consistent
|
||||
//
|
||||
// 7---------6 Faces:
|
||||
// /| /| |z 0 bottom 0, 3, 2, 1
|
||||
// / | / | | /y 1 top 4, 5, 6, 7
|
||||
// 4---------5 | |/ 2 front 4, 0, 1, 5
|
||||
// | 3------|--2 *---x 3 right 5, 1, 2, 6
|
||||
// | / | / 4 back 6, 2, 3, 7
|
||||
// |/ |/ 5 left 7, 3, 0, 4
|
||||
// 0---------1
|
||||
|
||||
Vec3f v0(min.x(), min.y(), min.z());
|
||||
Vec3f v1(max.x(), min.y(), min.z());
|
||||
Vec3f v2(max.x(), max.y(), min.z());
|
||||
Vec3f v3(min.x(), max.y(), min.z());
|
||||
|
||||
Vec3f v4(min.x(), min.y(), max.z());
|
||||
Vec3f v5(max.x(), min.y(), max.z());
|
||||
Vec3f v6(max.x(), max.y(), max.z());
|
||||
Vec3f v7(min.x(), max.y(), max.z());
|
||||
|
||||
builder->addQuadByVertices(v0, v3, v2, v1);
|
||||
builder->addQuadByVertices(v4, v5, v6, v7);
|
||||
builder->addQuadByVertices(v4, v0, v1, v5);
|
||||
builder->addQuadByVertices(v5, v1, v2, v6);
|
||||
builder->addQuadByVertices(v6, v2, v3, v7);
|
||||
builder->addQuadByVertices(v7, v3, v0, v4);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Create a 3D solid box at the specified position and with the given total extents
|
||||
///
|
||||
/// \param centerPos Position of center of box
|
||||
/// \param extentX Total extent of box along x-axis
|
||||
/// \param extentY Total extent of box along y-axis
|
||||
/// \param extentZ Total extent of box along z-axis
|
||||
/// \param builder Geometry builder to use when creating geometry
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::createBox(const Vec3f& centerPos, float extentX, float extentY, float extentZ, GeometryBuilder* builder)
|
||||
{
|
||||
Vec3f halfExtent(extentX/2, extentY/2, extentZ/2);
|
||||
Vec3f min(centerPos - halfExtent);
|
||||
Vec3f max(centerPos + halfExtent);
|
||||
|
||||
createBox(min, max, builder);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Create a disc centered at origin with its normal along positive z-axis
|
||||
///
|
||||
/// \param radius Outer radius of the disc
|
||||
/// \param numSlices The number of subdivisions around the z-axis. Must be >= 4
|
||||
/// \param builder Geometry builder to use when creating geometry
|
||||
///
|
||||
/// Creates a disc on the z = 0 plane, centered at origin and with its surface normal pointing
|
||||
/// along the positive z-axis.
|
||||
///
|
||||
/// The disk is subdivided around the z axis into numSlices (as in pizza slices).
|
||||
///
|
||||
/// The sourceNodes that will be produced by this method:
|
||||
/// <PRE>
|
||||
/// 1
|
||||
/// /-----\ 8
|
||||
/// 2/\ | /\ |y
|
||||
/// / \ | / \ |
|
||||
/// | \|/ | |
|
||||
/// 3|----0----|7 |
|
||||
/// | /|\ | *-----x
|
||||
/// \ / | \ / /
|
||||
/// 4\/ | \/6 /z
|
||||
/// \-----/
|
||||
/// 5 </PRE>
|
||||
///
|
||||
/// The following triangle connectivities will be produced:\n
|
||||
/// <TT> (0,1,2) (0,2,3) (0,3,4) ... (0,8,1)</TT>
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::createDisc(double radius, uint numSlices, GeometryBuilder* builder)
|
||||
{
|
||||
CVF_ASSERT(numSlices >= 4);
|
||||
CVF_ASSERT(builder);
|
||||
|
||||
|
||||
double da = 2*PI_D/numSlices;
|
||||
|
||||
Vec3fArray verts;
|
||||
verts.reserve(numSlices + 1);
|
||||
|
||||
// Center of disc
|
||||
verts.add(Vec3f::ZERO);
|
||||
|
||||
|
||||
Vec3f point = Vec3f::ZERO;
|
||||
|
||||
uint i;
|
||||
for (i = 0; i < numSlices; i++)
|
||||
{
|
||||
// Precompute this one (A = i*da;)
|
||||
double sinA = Math::sin(i*da);
|
||||
double cosA = Math::cos(i*da);
|
||||
|
||||
point.x() = static_cast<float>(-sinA*radius);
|
||||
point.y() = static_cast<float>( cosA*radius);
|
||||
|
||||
verts.add(point);
|
||||
}
|
||||
|
||||
uint baseNodeIdx = builder->addVertices(verts);
|
||||
|
||||
|
||||
// Vec3fArray myArray;
|
||||
// myArray.resize(10);
|
||||
// generatePointsOnCircle(radius, numSlices, &myArray);
|
||||
|
||||
|
||||
uint conn[3] = { baseNodeIdx, 0, 0};
|
||||
|
||||
for (i = numSlices; i > 0; i--)
|
||||
{
|
||||
conn[1] = baseNodeIdx + i + 1;
|
||||
conn[2] = baseNodeIdx + i + 0;
|
||||
|
||||
if (i == numSlices) conn[1] = baseNodeIdx + 1;
|
||||
|
||||
builder->addTriangle(conn[0], conn[1], conn[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// void GeometryUtils::generatePointsOnCircle(double radius, int numPoints, Vec3fArray* generatedPoints)
|
||||
// {
|
||||
// CVF_ASSERT(generatedPoints);
|
||||
// generatedPoints->reserve(generatedPoints->size() + numPoints);
|
||||
//
|
||||
// double da = 2*PI_D/numPoints;
|
||||
//
|
||||
// Vec3f point = Vec3f::ZERO;
|
||||
//
|
||||
// int i;
|
||||
// for (i = 0; i < numPoints; i++)
|
||||
// {
|
||||
// // Precompute this one (A = i*da;)
|
||||
// double sinA = sin(i*da);
|
||||
// double cosA = cos(i*da);
|
||||
//
|
||||
// point.x() = static_cast<float>(-sinA*radius);
|
||||
// point.y() = static_cast<float>( cosA*radius);
|
||||
//
|
||||
// generatedPoints->add(point);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
|
||||
// void GeometryUtils::createDiscUsingFan(double radius, int numSlices, GeometryBuilder* geometryBuilder)
|
||||
// {
|
||||
// CVF_ASSERT(numSlices >= 4);
|
||||
// CVF_ASSERT(geometryBuilder);
|
||||
//
|
||||
//
|
||||
// double da = 2*PI_D/numSlices;
|
||||
//
|
||||
// Vec3fArray verts;
|
||||
// verts.preAllocBuffer(numSlices + 1);
|
||||
//
|
||||
// // Center of disc
|
||||
// verts.addToPreAlloc(Vec3f::ZERO);
|
||||
//
|
||||
//
|
||||
// Vec3f point = Vec3f::ZERO;
|
||||
//
|
||||
// int i;
|
||||
// for (i = 0; i < numSlices; i++)
|
||||
// {
|
||||
// // Precompute this one (A = i*da;)
|
||||
// double sinA = sin(i*da);
|
||||
// double cosA = cos(i*da);
|
||||
//
|
||||
// point.x() = static_cast<float>(-sinA*radius);
|
||||
// point.y() = static_cast<float>( cosA*radius);
|
||||
//
|
||||
// verts.addToPreAlloc(point);
|
||||
// }
|
||||
//
|
||||
// int baseNodeIdx = geometryBuilder->addVertices(verts);
|
||||
//
|
||||
//
|
||||
// IntArray conns;
|
||||
// conns.resize(numSlices + 2);
|
||||
//
|
||||
// for (i = 0; i < numSlices + 1; i++)
|
||||
// {
|
||||
// conns[i] = baseNodeIdx + i;
|
||||
// }
|
||||
//
|
||||
// conns[numSlices + 1] = baseNodeIdx + 1;
|
||||
//
|
||||
// geometryBuilder->addTriangleFan(conns);
|
||||
// }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Create a sphere with center in origin
|
||||
///
|
||||
/// \param radius Radius of sphere
|
||||
/// \param numSlices The number of subdivisions around the z-axis (similar to lines of longitude).
|
||||
/// \param numStacks The number of subdivisions along the z-axis (similar to lines of latitude).
|
||||
/// \param builder Geometry builder to use when creating geometry
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::createSphere(double radius, uint numSlices, uint numStacks, GeometryBuilder* builder)
|
||||
{
|
||||
// Code is strongly inspired by mesa.
|
||||
|
||||
// From GLviewAPI:
|
||||
// float nsign = bNormalsOutwards ? 1.0f : -1.0f;
|
||||
// Could be added as a param if needed (e.g. dome)
|
||||
const double nsign = 1.0;
|
||||
|
||||
double rho = PI_D/numStacks;
|
||||
double theta = 2.0*PI_D/static_cast<double>(numSlices);
|
||||
|
||||
// Array to receive the node coordinates
|
||||
Vec3fArray vertices;
|
||||
uint vertexCount = 1 + 2*numSlices + (numStacks - 2)*numSlices;
|
||||
vertices.reserve(vertexCount);
|
||||
|
||||
// Create the +Z end as triangles
|
||||
Vec3d vTop(0.0, 0.0, nsign*radius);
|
||||
vertices.add(Vec3f(vTop));
|
||||
|
||||
ref<UIntArray> triangleFan = new UIntArray;
|
||||
triangleFan->reserve(numSlices + 2);
|
||||
triangleFan->add(0);
|
||||
|
||||
uint j;
|
||||
for (j = 0; j < numSlices; j++)
|
||||
{
|
||||
double localTheta = j * theta;
|
||||
|
||||
Vec3d v;
|
||||
v.x() = -Math::sin(localTheta) * Math::sin(rho);
|
||||
v.y() = Math::cos(localTheta) * Math::sin(rho);
|
||||
v.z() = nsign * Math::cos(rho);
|
||||
|
||||
v *= radius;
|
||||
vertices.add(Vec3f(v));
|
||||
|
||||
triangleFan->add(j + 1);
|
||||
}
|
||||
|
||||
// Close top fan
|
||||
triangleFan->add(1);
|
||||
builder->addTriangleFan(*triangleFan);
|
||||
|
||||
// Intermediate stacks as quad-strips
|
||||
// First and last stacks are handled separately
|
||||
|
||||
ref<UIntArray> quadStrip = new UIntArray;
|
||||
quadStrip->reserve(numSlices*2 + 2);
|
||||
|
||||
uint i;
|
||||
for (i = 1; i < numStacks - 1; i++)
|
||||
{
|
||||
double localRho = i * rho;
|
||||
|
||||
quadStrip->setSizeZero();
|
||||
|
||||
for (j = 0; j < numSlices; j++)
|
||||
{
|
||||
double localTheta = j * theta;
|
||||
|
||||
Vec3d v;
|
||||
v.x() = -Math::sin(localTheta) * Math::sin(localRho + rho);
|
||||
v.y() = Math::cos(localTheta) * Math::sin(localRho + rho);
|
||||
v.z() = nsign * Math::cos(localRho + rho);
|
||||
|
||||
v *= radius;
|
||||
vertices.add(Vec3f(v));
|
||||
|
||||
uint iC1 = (i*numSlices) + 1 + j;
|
||||
uint iC0 = iC1 - numSlices;
|
||||
quadStrip->add(iC0);
|
||||
quadStrip->add(iC1);
|
||||
}
|
||||
|
||||
// Close quad-strip
|
||||
uint iStartC1 = (i*numSlices) + 1;
|
||||
uint iStartC0 = iStartC1 - numSlices;
|
||||
quadStrip->add(iStartC0);
|
||||
quadStrip->add(iStartC1);
|
||||
|
||||
builder->addQuadStrip(*quadStrip);
|
||||
}
|
||||
|
||||
// Create -Z end as triangles
|
||||
Vec3d vBot( 0.0, 0.0, -radius*nsign );
|
||||
vertices.add(Vec3f(vBot));
|
||||
|
||||
uint endNodeIndex = static_cast<uint>(vertices.size()) - 1;
|
||||
|
||||
triangleFan->setSizeZero();
|
||||
triangleFan->add(endNodeIndex);
|
||||
|
||||
for (j = 0; j < numSlices; j++)
|
||||
{
|
||||
triangleFan->add(endNodeIndex - j - 1);
|
||||
}
|
||||
|
||||
// Close bottom fan
|
||||
triangleFan->add(endNodeIndex - 1);
|
||||
builder->addTriangleFan(*triangleFan);
|
||||
|
||||
builder->addVertices(vertices);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Create a (possibly oblique) cylinder oriented along the z-axis
|
||||
///
|
||||
/// \param bottomRadius Bottom radius of cylinder
|
||||
/// \param topRadius Top radius of cylinder
|
||||
/// \param height Height of cylinder
|
||||
/// \param topOffsetX Offset top disc relative to bottom in X direction
|
||||
/// \param topOffsetY Offset top disc relative to bottom in Y direction
|
||||
/// \param numSlices Number of slices
|
||||
/// \param normalsOutwards true to generate polygons with outward facing normals.
|
||||
/// \param closedBot true to close the bottom of the cylinder with a disc
|
||||
/// \param closedTop true to close the top of the cylinder with a disc
|
||||
/// \param numPolysZDir Number of (subdivisions) polygons along the Z axis.
|
||||
/// \param builder Geometry builder to use when creating geometry
|
||||
///
|
||||
/// An oblique cylinder is a cylinder with bases that are not aligned one directly above the other
|
||||
/// The base of the cylinder is placed at z = 0, and the top at z = height.
|
||||
/// Cylinder is subdivided around the z-axis into slices.
|
||||
/// Use the cone functions instead of setting one of the radius params to 0
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::createObliqueCylinder(float bottomRadius, float topRadius, float height, float topOffsetX, float topOffsetY, uint numSlices, bool normalsOutwards, bool closedBot, bool closedTop, uint numPolysZDir, GeometryBuilder* builder)
|
||||
{
|
||||
// Create cylinder...
|
||||
Vec3f centBot(0, 0, 0);
|
||||
Vec3f centTop(topOffsetX, topOffsetY, height);
|
||||
|
||||
// Create vertices
|
||||
uint zPoly;
|
||||
for (zPoly = 0; zPoly <= numPolysZDir; zPoly++)
|
||||
{
|
||||
float fT = static_cast<float>((1.0/numPolysZDir)*(zPoly));
|
||||
float radius = bottomRadius + fT*(topRadius - bottomRadius);
|
||||
Vec3f center(fT*topOffsetX, fT*topOffsetY, fT*height);
|
||||
|
||||
Vec3fArray verts;
|
||||
verts.reserve(numSlices);
|
||||
Vec3f point = Vec3f::ZERO;
|
||||
|
||||
double da = 2*PI_D/numSlices;
|
||||
uint i;
|
||||
for (i = 0; i < numSlices; i++)
|
||||
{
|
||||
// Precompute this one (A = i*da;)
|
||||
double sinA = Math::sin(i*da);
|
||||
double cosA = Math::cos(i*da);
|
||||
|
||||
point.x() = static_cast<float>(-sinA*radius);
|
||||
point.y() = static_cast<float>( cosA*radius);
|
||||
point.z() = 0;
|
||||
|
||||
point += center;
|
||||
|
||||
verts.add(point);
|
||||
}
|
||||
|
||||
uint baseNodeIdx = builder->addVertices(verts);
|
||||
|
||||
// First time we only create the sourceNodes
|
||||
if (zPoly != 0)
|
||||
{
|
||||
uint offset = baseNodeIdx - numSlices;
|
||||
uint piConn[4] = { 0, 0, 0, 0 };
|
||||
|
||||
// Normals facing outwards
|
||||
if (normalsOutwards)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < numSlices; i++)
|
||||
{
|
||||
piConn[0] = offset + i;
|
||||
piConn[1] = offset + i + 1;
|
||||
piConn[2] = offset + i + numSlices + 1;
|
||||
piConn[3] = offset + i + numSlices;
|
||||
|
||||
if (i == numSlices - 1)
|
||||
{
|
||||
piConn[1] = offset;
|
||||
piConn[2] = offset + numSlices;
|
||||
}
|
||||
|
||||
builder->addQuad(piConn[0], piConn[1], piConn[2], piConn[3]);
|
||||
}
|
||||
}
|
||||
|
||||
// Normals facing inwards
|
||||
else
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < numSlices; i++)
|
||||
{
|
||||
piConn[0] = offset + i + 1;
|
||||
piConn[1] = offset + i;
|
||||
piConn[2] = offset + i + numSlices;
|
||||
piConn[3] = offset + i + numSlices + 1;
|
||||
|
||||
if (i == numSlices - 1)
|
||||
{
|
||||
piConn[0] = offset;
|
||||
piConn[3] = offset + numSlices;
|
||||
}
|
||||
|
||||
builder->addQuad(piConn[0], piConn[1], piConn[2], piConn[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (closedBot)
|
||||
{
|
||||
createDisc(bottomRadius, numSlices, builder);
|
||||
}
|
||||
|
||||
if (closedTop)
|
||||
{
|
||||
uint startIdx = builder->vertexCount();
|
||||
createDisc(topRadius, numSlices, builder);
|
||||
uint endIdx = builder->vertexCount() - 1;
|
||||
|
||||
// Translate the top disc sourceNodes, also flip it to get the normals the right way
|
||||
Mat4f mat = Mat4f::fromRotation(Vec3f(1.0f, 0.0f, 0.0f), Math::toRadians(180.0f));
|
||||
mat.translatePreMultiply(Vec3f(topOffsetX, topOffsetY, height));
|
||||
|
||||
builder->transformVertexRange(startIdx, endIdx, mat);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Create a cone oriented along the z-axis
|
||||
///
|
||||
/// \param bottomRadius Bottom radius of cone
|
||||
/// \param height Height of cone
|
||||
/// \param numSlices Number of slices
|
||||
/// \param normalsOutwards true to generate polygons with outward facing normals.
|
||||
/// \param closedBot true to close the bottom of the cone with a disc
|
||||
/// \param singleTopNode Specify if a single top node should be used, or if each side triangle
|
||||
/// should have its own top node.
|
||||
/// \param builder Geometry builder to use when creating geometry
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::createCone(float bottomRadius, float height, uint numSlices, bool normalsOutwards, bool closedBot, bool singleTopNode, GeometryBuilder* builder)
|
||||
{
|
||||
Vec3fArray verts;
|
||||
|
||||
if (singleTopNode)
|
||||
{
|
||||
verts.reserve(numSlices + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
verts.reserve(numSlices*2);
|
||||
}
|
||||
|
||||
Vec3f point = Vec3f::ZERO;
|
||||
|
||||
double da = 2*PI_D/numSlices;
|
||||
uint i;
|
||||
for (i = 0; i < numSlices; i++)
|
||||
{
|
||||
// Precompute this one (A = i*da;)
|
||||
double sinA = Math::sin(i*da);
|
||||
double cosA = Math::cos(i*da);
|
||||
|
||||
point.x() = static_cast<float>(-sinA*bottomRadius);
|
||||
point.y() = static_cast<float>( cosA*bottomRadius);
|
||||
|
||||
verts.add(point);
|
||||
}
|
||||
|
||||
if (singleTopNode)
|
||||
{
|
||||
verts.add(Vec3f(0, 0, height));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unique sourceNodes at apex of cone
|
||||
Vec3f topNode(0, 0, height);
|
||||
|
||||
uint i;
|
||||
for (i = 0; i < numSlices; i++)
|
||||
{
|
||||
verts.add(topNode);
|
||||
}
|
||||
}
|
||||
|
||||
uint baseNodeIdx = builder->addVertices(verts);
|
||||
|
||||
uint piConn[3] = { 0, 0, 0 };
|
||||
|
||||
// Normals facing outwards
|
||||
if (normalsOutwards)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < numSlices; i++)
|
||||
{
|
||||
piConn[0] = baseNodeIdx + i;
|
||||
piConn[1] = baseNodeIdx + i + 1;
|
||||
piConn[2] = singleTopNode ? baseNodeIdx + numSlices : baseNodeIdx + i + numSlices;
|
||||
|
||||
if (i == numSlices - 1)
|
||||
{
|
||||
piConn[1] = baseNodeIdx;
|
||||
}
|
||||
|
||||
if (normalsOutwards)
|
||||
{
|
||||
builder->addTriangle(piConn[0], piConn[1], piConn[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder->addTriangle(piConn[1], piConn[0], piConn[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (closedBot)
|
||||
{
|
||||
createDisc(bottomRadius, numSlices, builder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::tesselatePatchAsQuads(uint pointCountU, uint pointCountV, uint indexOffset, bool windingCCW, UIntArray* indices)
|
||||
{
|
||||
CVF_ASSERT(pointCountU >= 2);
|
||||
CVF_ASSERT(pointCountV >= 2);
|
||||
|
||||
uint uCellCount = pointCountU - 1;
|
||||
uint vCellCount = pointCountV - 1;
|
||||
|
||||
uint numQuads = uCellCount*vCellCount;
|
||||
indices->reserve(indices->size() + 4*numQuads);
|
||||
|
||||
uint u, v;
|
||||
for (v = 0; v < vCellCount; v++)
|
||||
{
|
||||
for (u = 0; u < uCellCount; u++)
|
||||
{
|
||||
if (windingCCW)
|
||||
{
|
||||
indices->add(indexOffset + u + (v+1)*pointCountU);
|
||||
indices->add(indexOffset + u + v*pointCountU);
|
||||
indices->add(indexOffset + u+1 + v*pointCountU);
|
||||
indices->add(indexOffset + u+1 + (v+1)*pointCountU);
|
||||
}
|
||||
else
|
||||
{
|
||||
indices->add(indexOffset + u + v*pointCountU);
|
||||
indices->add(indexOffset + u + (v+1)*pointCountU);
|
||||
indices->add(indexOffset + u+1 + (v+1)*pointCountU);
|
||||
indices->add(indexOffset + u+1 + v*pointCountU);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::tesselatePatchAsTriangles(uint pointCountU, uint pointCountV, uint indexOffset, bool windingCCW, UIntArray* indices)
|
||||
{
|
||||
CVF_ASSERT(pointCountU >= 2);
|
||||
CVF_ASSERT(pointCountV >= 2);
|
||||
|
||||
uint uCellCount = pointCountU - 1;
|
||||
uint vCellCount = pointCountV - 1;
|
||||
|
||||
uint numTris = 2*uCellCount*vCellCount;
|
||||
indices->reserve(indices->size() + 3*numTris);
|
||||
|
||||
uint u, v;
|
||||
for (v = 0; v < vCellCount; v++)
|
||||
{
|
||||
for (u = 0; u < uCellCount; u++)
|
||||
{
|
||||
if (windingCCW)
|
||||
{
|
||||
indices->add(indexOffset + u + (v+1)*pointCountU);
|
||||
indices->add(indexOffset + u + v*pointCountU);
|
||||
indices->add(indexOffset + u+1 + v*pointCountU);
|
||||
|
||||
indices->add(indexOffset + u + (v+1)*pointCountU);
|
||||
indices->add(indexOffset + u+1 + v*pointCountU);
|
||||
indices->add(indexOffset + u+1 + (v+1)*pointCountU);
|
||||
}
|
||||
else
|
||||
{
|
||||
indices->add(indexOffset + u + v*pointCountU);
|
||||
indices->add(indexOffset + u + (v+1)*pointCountU);
|
||||
indices->add(indexOffset + u+1 + (v+1)*pointCountU);
|
||||
|
||||
indices->add(indexOffset + u + v*pointCountU);
|
||||
indices->add(indexOffset + u+1 + (v+1)*pointCountU);
|
||||
indices->add(indexOffset + u+1 + v*pointCountU);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Check if the specified quad is convex
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool GeometryUtils::isConvexQuad(const Vec3f& a, const Vec3f& b, const Vec3f& c, const Vec3f& d)
|
||||
{
|
||||
// From "Real Time Collision Detection", p60
|
||||
// Quad is nonconvex if dot(cross(bd, ba), cross(bd, bc)) >= 0
|
||||
const Vec3f bda = (d - b) ^ (a - b);
|
||||
const Vec3f bdc = (d - b) ^ (c - b);
|
||||
if (bda*bdc >= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Quad is now convex if dot(cross(ac, ad), cross(ac, ab)) < 0
|
||||
const Vec3f acd = (c - a) ^ (d - a);
|
||||
const Vec3f acb = (c - a) ^ (b - a);
|
||||
if (acd*acb < 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Compute surface normal for a quad
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Vec3f GeometryUtils::quadNormal(const Vec3f& a, const Vec3f& b, const Vec3f& c, const Vec3f& d)
|
||||
{
|
||||
// From "Real Time Collision Detection", p. 495
|
||||
Vec3f normal = (c - a) ^ (d - b);
|
||||
normal.normalize();
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Compute polygon normal using Newell's method
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Vec3f GeometryUtils::polygonNormal(const Vec3fValueArray& vertices, const uint* indices, uint indexCount)
|
||||
{
|
||||
// From "Real Time Collision Detection", p. 495
|
||||
// Compute normal as being proportional to projected areas of polygon onto the yz, xz, and xy planes.
|
||||
Vec3f normal(0, 0, 0);
|
||||
|
||||
uint n;
|
||||
for (n = 0; n < indexCount; n++)
|
||||
{
|
||||
uint i = indices[(n > 0) ? n - 1 : indexCount - 1];
|
||||
uint j = indices[n];
|
||||
|
||||
normal.x() += (vertices.val(i).y() - vertices.val(j).y()) * (vertices.val(i).z() + vertices.val(j).z()); // projection on yz
|
||||
normal.y() += (vertices.val(i).z() - vertices.val(j).z()) * (vertices.val(i).x() + vertices.val(j).x()); // projection on xz
|
||||
normal.z() += (vertices.val(i).x() - vertices.val(j).x()) * (vertices.val(i).y() + vertices.val(j).y()); // projection on xy
|
||||
}
|
||||
|
||||
normal.normalize();
|
||||
return normal;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Compact an array of vertex indices by removing 'unused' indices
|
||||
///
|
||||
/// \param[in] vertexIndices The original vertex indices
|
||||
/// \param[out] newVertexIndices New compacted vertex indices
|
||||
/// \param[out] newToOldMapping For each 'new' vertex, will contain its original index
|
||||
/// \param[in] maxVertexCount The maximum resulting vertex count after removing unused vertices
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::removeUnusedVertices(const UIntValueArray& vertexIndices, UIntArray* newVertexIndices, UIntArray* newToOldMapping, uint maxVertexCount)
|
||||
{
|
||||
if (vertexIndices.size() == 0 || maxVertexCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<uint, uint> oldToNewVertexIndexMap;
|
||||
std::map<uint, uint>::const_iterator it;
|
||||
|
||||
CVF_ASSERT(newVertexIndices);
|
||||
CVF_ASSERT(newToOldMapping);
|
||||
newVertexIndices->reserve(vertexIndices.size());
|
||||
newToOldMapping->reserve(maxVertexCount);
|
||||
|
||||
size_t i;
|
||||
uint newVertexIndex = 0;
|
||||
for (i = 0; i < vertexIndices.size(); i++)
|
||||
{
|
||||
uint vertexIdx = vertexIndices.val(i);
|
||||
|
||||
uint currentIndex = UNDEFINED_UINT;
|
||||
|
||||
it = oldToNewVertexIndexMap.find(vertexIdx);
|
||||
if (it == oldToNewVertexIndexMap.end())
|
||||
{
|
||||
currentIndex = newVertexIndex++;
|
||||
oldToNewVertexIndexMap[vertexIdx] = currentIndex;
|
||||
newToOldMapping->add(vertexIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentIndex = it->second;
|
||||
}
|
||||
|
||||
CVF_ASSERT(currentIndex != UNDEFINED_UINT);
|
||||
newVertexIndices->add(currentIndex);
|
||||
}
|
||||
|
||||
newToOldMapping->squeeze();
|
||||
}
|
||||
|
||||
bool GeometryUtils::project(const Mat4d& projectionMultViewMatrix, const Vec2ui& viewportPosition, const Vec2ui& viewportSize, const Vec3d& point, Vec3d* out)
|
||||
{
|
||||
CVF_ASSERT(out);
|
||||
|
||||
Vec4d v = projectionMultViewMatrix * Vec4d(point, 1.0);
|
||||
|
||||
if (v.w() == 0.0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
v.x() /= v.w();
|
||||
v.y() /= v.w();
|
||||
v.z() /= v.w();
|
||||
|
||||
// map to range 0-1
|
||||
out->x() = v.x()*0.5 + 0.5;
|
||||
out->y() = v.y()*0.5 + 0.5;
|
||||
out->z() = v.z()*0.5 + 0.5;
|
||||
|
||||
// map to viewport
|
||||
out->x() = out->x() * viewportSize.x() + viewportPosition.x();
|
||||
out->y() = out->y() * viewportSize.y() + viewportPosition.y();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace cvf
|
||||
63
VisualizationModules/LibGeometry/cvfGeometryUtils.h
Normal file
63
VisualizationModules/LibGeometry/cvfGeometryUtils.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfVector3.h"
|
||||
#include "cvfGeometryBuilder.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Static helper class for building geometry
|
||||
//
|
||||
//==================================================================================================
|
||||
class GeometryUtils
|
||||
{
|
||||
public:
|
||||
static void createPatch(const Vec3f& origin, const Vec3f& uUnit, const Vec3f& vUnit, uint uCellCount, uint vCellCount, GeometryBuilder* builder);
|
||||
|
||||
static void createBox(const Vec3f& min, const Vec3f& max, GeometryBuilder* builder);
|
||||
static void createBox(const Vec3f& centerPos, float extentX, float extentY, float extentZ, GeometryBuilder* builder);
|
||||
|
||||
static void createDisc(double radius, uint numSlices, GeometryBuilder* builder);
|
||||
|
||||
static void createSphere(double radius, uint numSlices, uint numStacks, GeometryBuilder* builder);
|
||||
|
||||
// These two should be refactored out into separate generator classes
|
||||
static void createObliqueCylinder(float bottomRadius, float topRadius, float height, float topOffsetX, float topOffsetY, uint numSlices, bool normalsOutwards, bool closedBot, bool closedTop, uint numPolysZDir, GeometryBuilder* builder);
|
||||
static void createCone(float bottomRadius, float height, uint numSlices, bool normalsOutwards, bool closedBot, bool singleTopNode, GeometryBuilder* builder);
|
||||
|
||||
//static void generatePointsOnCircle(double radius, int numPoints, Vec3fArray* generatedPoints);
|
||||
|
||||
static void tesselatePatchAsQuads(uint pointCountU, uint pointCountV, uint indexOffset, bool windingCCW, UIntArray* indices);
|
||||
static void tesselatePatchAsTriangles(uint pointCountU, uint pointCountV, uint indexOffset, bool windingCCW, UIntArray* indices);
|
||||
|
||||
static bool isConvexQuad(const Vec3f& a, const Vec3f& b, const Vec3f& c, const Vec3f& d);
|
||||
static Vec3f quadNormal(const Vec3f& a, const Vec3f& b, const Vec3f& c, const Vec3f& d);
|
||||
static Vec3f polygonNormal(const Vec3fValueArray& vertices, const uint* indices, uint indexCount);
|
||||
|
||||
static void removeUnusedVertices(const UIntValueArray& vertexIndices, UIntArray* newVertexIndices, UIntArray* newToOldMapping, uint maxVertexCount);
|
||||
|
||||
static bool project(const Mat4d& projectionMultViewMatrix, const Vec2ui& viewportPosition, const Vec2ui& viewportSize, const Vec3d& point, Vec3d* out);
|
||||
};
|
||||
|
||||
}
|
||||
41
VisualizationModules/LibGeometry/cvfLibGeometry.h
Normal file
41
VisualizationModules/LibGeometry/cvfLibGeometry.h
Normal file
@@ -0,0 +1,41 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
|
||||
// Doxygen module definition
|
||||
/// \ingroup CeeVizFramework
|
||||
/// @{
|
||||
/// \defgroup Geometry Geometry module
|
||||
/// @}
|
||||
|
||||
#include "cvfArrowGenerator.h"
|
||||
#include "cvfBoundingBox.h"
|
||||
#include "cvfBoxGenerator.h"
|
||||
#include "cvfFrustum.h"
|
||||
#include "cvfEdgeKey.h"
|
||||
#include "cvfGeometryBuilder.h"
|
||||
#include "cvfGeometryBuilderFaceList.h"
|
||||
#include "cvfGeometryBuilderTriangles.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
#include "cvfMeshEdgeExtractor.h"
|
||||
#include "cvfOutlineEdgeExtractor.h"
|
||||
#include "cvfPatchGenerator.h"
|
||||
#include "cvfRay.h"
|
||||
#include "cvfVertexWelder.h"
|
||||
|
||||
151
VisualizationModules/LibGeometry/cvfMeshEdgeExtractor.cpp
Normal file
151
VisualizationModules/LibGeometry/cvfMeshEdgeExtractor.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfMeshEdgeExtractor.h"
|
||||
#include "cvfEdgeKey.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::MeshEdgeExtractor
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
MeshEdgeExtractor::MeshEdgeExtractor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void MeshEdgeExtractor::addPrimitives(uint verticesPerPrimitive, const uint* indices, size_t indexCount)
|
||||
{
|
||||
CVF_ASSERT(verticesPerPrimitive > 0);
|
||||
CVF_ASSERT(indices);
|
||||
CVF_ASSERT(indexCount > 0);
|
||||
|
||||
// Points will never become edges
|
||||
if (verticesPerPrimitive < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t numPrimitives = indexCount/verticesPerPrimitive;
|
||||
|
||||
size_t ip;
|
||||
for (ip = 0; ip < numPrimitives; ip++)
|
||||
{
|
||||
size_t firstIdxInPrimitive = ip*verticesPerPrimitive;
|
||||
|
||||
uint i;
|
||||
for (i = 0; i < verticesPerPrimitive; i++)
|
||||
{
|
||||
uint vertexIdx1 = indices[firstIdxInPrimitive + i];
|
||||
uint vertexIdx2 = (i < verticesPerPrimitive - 1) ? indices[firstIdxInPrimitive + i + 1] : indices[firstIdxInPrimitive];
|
||||
|
||||
// Don't add collapsed edges
|
||||
if (vertexIdx1 != vertexIdx2)
|
||||
{
|
||||
int64 edgeKeyVal = EdgeKey(vertexIdx1, vertexIdx2).toKeyVal();
|
||||
m_edgeSet.insert(edgeKeyVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void MeshEdgeExtractor::addPrimitives(uint verticesPerPrimitive, const UIntArray& indices)
|
||||
{
|
||||
CVF_ASSERT(verticesPerPrimitive > 0);
|
||||
|
||||
size_t indexCount = indices.size();
|
||||
size_t numPrimitives = indexCount/verticesPerPrimitive;
|
||||
if (numPrimitives > 0)
|
||||
{
|
||||
const uint* indexPtr = indices.ptr();
|
||||
addPrimitives(verticesPerPrimitive, indexPtr, indexCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void MeshEdgeExtractor::addFaceList(const UIntArray& faceList)
|
||||
{
|
||||
size_t numFaceListEntries = faceList.size();
|
||||
|
||||
size_t i = 0;
|
||||
while (i < numFaceListEntries)
|
||||
{
|
||||
uint numVerticesInFace = faceList[i++];
|
||||
CVF_ASSERT(numVerticesInFace > 0);
|
||||
CVF_ASSERT(i + numVerticesInFace <= numFaceListEntries);
|
||||
|
||||
const uint* indexPtr = &faceList[i];
|
||||
addPrimitives(numVerticesInFace, indexPtr, numVerticesInFace);
|
||||
|
||||
i += numVerticesInFace;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UIntArray> MeshEdgeExtractor::lineIndices() const
|
||||
{
|
||||
ref<UIntArray> indices = new UIntArray;
|
||||
|
||||
size_t numEdges = m_edgeSet.size();
|
||||
if (numEdges == 0)
|
||||
{
|
||||
return indices;
|
||||
}
|
||||
|
||||
indices->reserve(2*numEdges);
|
||||
|
||||
std::set<cvf::int64>::const_iterator it;
|
||||
for (it = m_edgeSet.begin(); it != m_edgeSet.end(); ++it)
|
||||
{
|
||||
EdgeKey ek = EdgeKey::fromkeyVal(*it);
|
||||
indices->add(ek.index1());
|
||||
indices->add(ek.index2());
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
51
VisualizationModules/LibGeometry/cvfMeshEdgeExtractor.h
Normal file
51
VisualizationModules/LibGeometry/cvfMeshEdgeExtractor.h
Normal file
@@ -0,0 +1,51 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfArray.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class MeshEdgeExtractor
|
||||
{
|
||||
public:
|
||||
MeshEdgeExtractor();
|
||||
|
||||
void addPrimitives(uint verticesPerPrimitive, const uint* indices, size_t indexCount);
|
||||
void addPrimitives(uint verticesPerPrimitive, const UIntArray& indices);
|
||||
void addFaceList(const UIntArray& faceList);
|
||||
|
||||
ref<UIntArray> lineIndices() const;
|
||||
|
||||
private:
|
||||
std::set<cvf::int64> m_edgeSet;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
269
VisualizationModules/LibGeometry/cvfOutlineEdgeExtractor.cpp
Normal file
269
VisualizationModules/LibGeometry/cvfOutlineEdgeExtractor.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfOutlineEdgeExtractor.h"
|
||||
#include "cvfEdgeKey.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::OutlineEdgeExtractor
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
static const size_t OEE_OUTLINE_EDGE = cvf::UNDEFINED_SIZE_T; // This is an outline edge
|
||||
static const size_t OEE_NON_OUTLINE_EDGE = cvf::UNDEFINED_SIZE_T - 1; // Marked as an interior edge
|
||||
static const size_t OEE_MULTIREF_EDGE = cvf::UNDEFINED_SIZE_T - 2; // An edge with more than two faces connected to it.
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Constructor
|
||||
///
|
||||
/// creaseAngle is specified in radians
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
OutlineEdgeExtractor::OutlineEdgeExtractor(double creaseAngle, const Vec3fValueArray& vertexArray)
|
||||
: m_creaseAngle(creaseAngle),
|
||||
m_vertexArray(vertexArray)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void OutlineEdgeExtractor::addPrimitives(uint verticesPerPrimitive, const uint* indices, size_t indexCount)
|
||||
{
|
||||
CVF_ASSERT(verticesPerPrimitive > 0);
|
||||
CVF_ASSERT(indices);
|
||||
CVF_ASSERT(indexCount > 0);
|
||||
|
||||
// Points will never become edges
|
||||
if (verticesPerPrimitive < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t numPrimitives = indexCount/verticesPerPrimitive;
|
||||
|
||||
size_t ip;
|
||||
for (ip = 0; ip < numPrimitives; ip++)
|
||||
{
|
||||
size_t myFaceIndex = m_faceNormals.size();
|
||||
size_t firstIdxInPrimitive = ip*verticesPerPrimitive;
|
||||
|
||||
// Normal computation accepts points and lines, but in that case returns a zero vector
|
||||
Vec3f faceNormal = computeFaceNormal(&indices[firstIdxInPrimitive], verticesPerPrimitive);
|
||||
m_faceNormals.push_back(faceNormal);
|
||||
|
||||
uint i;
|
||||
for (i = 0; i < verticesPerPrimitive; i++)
|
||||
{
|
||||
const uint vertexIdx1 = indices[firstIdxInPrimitive + i];
|
||||
const uint vertexIdx2 = (i < verticesPerPrimitive - 1) ? indices[firstIdxInPrimitive + i + 1] : indices[firstIdxInPrimitive];
|
||||
|
||||
// Never add collapsed edges
|
||||
if (vertexIdx1 == vertexIdx2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int64 edgeKeyVal = EdgeKey(vertexIdx1, vertexIdx2).toKeyVal();
|
||||
std::map<int64, size_t>::iterator it = m_edgeToFaceIndexMap.find(edgeKeyVal);
|
||||
if (it == m_edgeToFaceIndexMap.end())
|
||||
{
|
||||
// Not found, so add and register face index
|
||||
m_edgeToFaceIndexMap[edgeKeyVal] = myFaceIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t otherFaceIdx = it->second;
|
||||
if (otherFaceIdx < OEE_MULTIREF_EDGE)
|
||||
{
|
||||
// An edge is already there, check angle
|
||||
if (isFaceAngleAboveThreshold(myFaceIndex, otherFaceIdx))
|
||||
{
|
||||
m_edgeToFaceIndexMap[edgeKeyVal] = OEE_OUTLINE_EDGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_edgeToFaceIndexMap[edgeKeyVal] = OEE_NON_OUTLINE_EDGE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Three or more faces share an edge
|
||||
m_edgeToFaceIndexMap[edgeKeyVal] = OEE_MULTIREF_EDGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void OutlineEdgeExtractor::addPrimitives(uint verticesPerPrimitive, const UIntArray& indices)
|
||||
{
|
||||
CVF_ASSERT(verticesPerPrimitive > 0);
|
||||
|
||||
size_t indexCount = indices.size();
|
||||
size_t numPrimitives = indexCount/verticesPerPrimitive;
|
||||
if (numPrimitives > 0)
|
||||
{
|
||||
const uint* indexPtr = indices.ptr();
|
||||
addPrimitives(verticesPerPrimitive, indexPtr, indexCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void OutlineEdgeExtractor::addFaceList(const UIntArray& faceList)
|
||||
{
|
||||
size_t numFaceListEntries = faceList.size();
|
||||
|
||||
size_t i = 0;
|
||||
while (i < numFaceListEntries)
|
||||
{
|
||||
uint numVerticesInFace = faceList[i++];
|
||||
CVF_ASSERT(numVerticesInFace > 0);
|
||||
CVF_ASSERT(i + numVerticesInFace <= numFaceListEntries);
|
||||
|
||||
const uint* indexPtr = &faceList[i];
|
||||
addPrimitives(numVerticesInFace, indexPtr, numVerticesInFace);
|
||||
|
||||
i += numVerticesInFace;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UIntArray> OutlineEdgeExtractor::lineIndices() const
|
||||
{
|
||||
ref<UIntArray> indices = new UIntArray;
|
||||
|
||||
size_t numEdges = m_edgeToFaceIndexMap.size();
|
||||
if (numEdges == 0)
|
||||
{
|
||||
return indices;
|
||||
}
|
||||
|
||||
indices->reserve(2*numEdges);
|
||||
|
||||
std::map<int64, size_t>::const_iterator it;
|
||||
for (it = m_edgeToFaceIndexMap.begin(); it != m_edgeToFaceIndexMap.end(); ++it)
|
||||
{
|
||||
size_t otherFaceIdx = it->second;
|
||||
if (otherFaceIdx != OEE_NON_OUTLINE_EDGE)
|
||||
{
|
||||
EdgeKey ek = EdgeKey::fromkeyVal(it->first);
|
||||
indices->add(ek.index1());
|
||||
indices->add(ek.index2());
|
||||
}
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns the worker array with one normal per face (primitive)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<Vec3f>& OutlineEdgeExtractor::faceNormals()
|
||||
{
|
||||
return m_faceNormals;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Vec3f OutlineEdgeExtractor::computeFaceNormal(const uint* faceVertexIndices, uint numVerticesInFace) const
|
||||
{
|
||||
// Init to zero so that points and lines return a zero normal
|
||||
Vec3f normal(Vec3f::ZERO);
|
||||
|
||||
if (numVerticesInFace == 3)
|
||||
{
|
||||
const Vec3f& v0 = m_vertexArray.val(faceVertexIndices[0]);
|
||||
Vec3f v1 = m_vertexArray.val(faceVertexIndices[1]) - v0;
|
||||
Vec3f v2 = m_vertexArray.val(faceVertexIndices[2]) - v0;
|
||||
|
||||
normal = v1 ^ v2;
|
||||
normal.normalize();
|
||||
}
|
||||
else if (numVerticesInFace == 4)
|
||||
{
|
||||
// Quad surface normal,
|
||||
// From "Real Time Collision Detection" p 495
|
||||
const Vec3f& A = m_vertexArray.val(faceVertexIndices[0]);
|
||||
const Vec3f& B = m_vertexArray.val(faceVertexIndices[1]);
|
||||
const Vec3f& C = m_vertexArray.val(faceVertexIndices[2]);
|
||||
const Vec3f& D = m_vertexArray.val(faceVertexIndices[3]);
|
||||
normal = GeometryUtils::quadNormal(A, B, C, D);
|
||||
}
|
||||
else if (numVerticesInFace > 4)
|
||||
{
|
||||
normal = GeometryUtils::polygonNormal(m_vertexArray, faceVertexIndices, numVerticesInFace);
|
||||
}
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool OutlineEdgeExtractor::isFaceAngleAboveThreshold(size_t faceIdx1, size_t faceIdx2) const
|
||||
{
|
||||
const Vec3f& n1 = m_faceNormals[faceIdx1];
|
||||
const Vec3f& n2 = m_faceNormals[faceIdx2];
|
||||
|
||||
// If either vector is 0, the face is probably a line
|
||||
// Therefore just return true to flag this as an outline edge
|
||||
if (n1.isZero() || n2.isZero())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
double angle = Math::acos(n1*n2);
|
||||
if (Math::abs(angle) > m_creaseAngle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
62
VisualizationModules/LibGeometry/cvfOutlineEdgeExtractor.h
Normal file
62
VisualizationModules/LibGeometry/cvfOutlineEdgeExtractor.h
Normal file
@@ -0,0 +1,62 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfArray.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class OutlineEdgeExtractor
|
||||
{
|
||||
public:
|
||||
OutlineEdgeExtractor(double creaseAngle, const Vec3fValueArray& vertexArray);
|
||||
|
||||
public:
|
||||
void addPrimitives(uint verticesPerPrimitive, const uint* indices, size_t indexCount);
|
||||
void addPrimitives(uint verticesPerPrimitive, const UIntArray& indices);
|
||||
void addFaceList(const UIntArray& faceList);
|
||||
|
||||
ref<UIntArray> lineIndices() const;
|
||||
const std::vector<Vec3f>& faceNormals(); // Surface normals for the faces, normalized
|
||||
|
||||
private:
|
||||
Vec3f computeFaceNormal(const uint* faceVertexIndices, uint numVerticesInFace) const;
|
||||
bool isFaceAngleAboveThreshold(size_t faceIdx1, size_t faceIdx2) const;
|
||||
|
||||
private:
|
||||
double m_creaseAngle; // Threshold crease angle in radians
|
||||
const Vec3fValueArray& m_vertexArray;
|
||||
std::map<int64, size_t> m_edgeToFaceIndexMap;
|
||||
std::vector<Vec3f> m_faceNormals; // Surface normals for the faces, normalized
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
162
VisualizationModules/LibGeometry/cvfPatchGenerator.cpp
Normal file
162
VisualizationModules/LibGeometry/cvfPatchGenerator.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfPatchGenerator.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::PatchGenerator
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Generates 2D patches
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
PatchGenerator::PatchGenerator()
|
||||
: m_origin(0, 0, 0),
|
||||
m_axisU(Vec3d::X_AXIS),
|
||||
m_axisV(Vec3d::Y_AXIS),
|
||||
m_extentU(1),
|
||||
m_extentV(1),
|
||||
m_cellCountU(1),
|
||||
m_cellCountV(1),
|
||||
m_useQuads(true),
|
||||
m_windingCCW(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PatchGenerator::setOrigin(const Vec3d& origin)
|
||||
{
|
||||
m_origin = origin;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Set the axes
|
||||
///
|
||||
/// The specified axes will be normalized
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PatchGenerator::setAxes(const Vec3d& axisU, const Vec3d& axisV)
|
||||
{
|
||||
m_axisU = axisU.getNormalized();
|
||||
m_axisV = axisV.getNormalized();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PatchGenerator::setExtent(double extentU, double extentV)
|
||||
{
|
||||
m_extentU = extentU;
|
||||
m_extentV = extentV;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PatchGenerator::setSubdivisions(uint subdivU, uint subdivV)
|
||||
{
|
||||
CVF_ASSERT(subdivU > 0 && subdivV > 0);
|
||||
m_cellCountU = subdivU;
|
||||
m_cellCountV = subdivV;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PatchGenerator::setQuads(bool useQuads)
|
||||
{
|
||||
m_useQuads = useQuads;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PatchGenerator::setWindingCCW(bool windingCCW)
|
||||
{
|
||||
m_windingCCW = windingCCW;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void PatchGenerator::generate(GeometryBuilder* builder)
|
||||
{
|
||||
CVF_ASSERT(m_cellCountU > 0);
|
||||
CVF_ASSERT(m_cellCountV > 0);
|
||||
|
||||
size_t numVertices = (m_cellCountU + 1)*(m_cellCountV + 1);
|
||||
|
||||
Vec3fArray vertices;
|
||||
vertices.reserve(numVertices);
|
||||
|
||||
const Vec3d unitU = (m_extentU*m_axisU)/m_cellCountU;
|
||||
const Vec3d unitV = (m_extentV*m_axisV)/m_cellCountV;
|
||||
|
||||
uint v;
|
||||
for (v = 0; v <= m_cellCountV; v++)
|
||||
{
|
||||
Vec3d rowOrigo(m_origin + unitV*v);
|
||||
|
||||
uint u;
|
||||
for (u = 0; u <= m_cellCountU; u++)
|
||||
{
|
||||
vertices.add(Vec3f(rowOrigo + unitU*u));
|
||||
}
|
||||
}
|
||||
|
||||
uint baseNodeIdx = builder->addVertices(vertices);
|
||||
|
||||
if (m_useQuads)
|
||||
{
|
||||
UIntArray conn;
|
||||
GeometryUtils::tesselatePatchAsQuads(m_cellCountU + 1, m_cellCountV + 1, baseNodeIdx, m_windingCCW, &conn);
|
||||
builder->addQuads(conn);
|
||||
}
|
||||
else
|
||||
{
|
||||
UIntArray conn;
|
||||
GeometryUtils::tesselatePatchAsTriangles(m_cellCountU + 1, m_cellCountV + 1, baseNodeIdx, m_windingCCW, &conn);
|
||||
builder->addTriangles(conn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
63
VisualizationModules/LibGeometry/cvfPatchGenerator.h
Normal file
63
VisualizationModules/LibGeometry/cvfPatchGenerator.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfVector3.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
class GeometryBuilder;
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Generates 2D patches
|
||||
//
|
||||
//==================================================================================================
|
||||
class PatchGenerator
|
||||
{
|
||||
public:
|
||||
PatchGenerator();
|
||||
|
||||
void setOrigin(const Vec3d& origin);
|
||||
void setAxes(const Vec3d& axisU, const Vec3d& axisV);
|
||||
void setExtent(double extentU, double extentV);
|
||||
void setSubdivisions(uint subdivU, uint subdivV);
|
||||
|
||||
void setQuads(bool useQuads);
|
||||
void setWindingCCW(bool windingCCW);
|
||||
|
||||
void generate(GeometryBuilder* builder);
|
||||
|
||||
private:
|
||||
Vec3d m_origin; // Origin. Default (0, 0, 0)
|
||||
Vec3d m_axisU; // First axis of patch. Default is global X-axis
|
||||
Vec3d m_axisV; // Second axis of patch. Default is global Y-axis
|
||||
double m_extentU; // Extent along U axis
|
||||
double m_extentV; // Extent along V axis
|
||||
uint m_cellCountU; // Number of cells/quads in each direction. Default 1
|
||||
uint m_cellCountV; // :
|
||||
|
||||
bool m_useQuads; // If true, quads will be generated, otherwise triangles. Default is quads
|
||||
bool m_windingCCW; // Winding of the generated quads. Controls which side of the patch will be front facing.
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
378
VisualizationModules/LibGeometry/cvfRay.cpp
Normal file
378
VisualizationModules/LibGeometry/cvfRay.cpp
Normal file
@@ -0,0 +1,378 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfRay.h"
|
||||
#include "cvfBoundingBox.h"
|
||||
#include "cvfPlane.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::Ray
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// A ray that can be used for intersection testing.
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Ray::Ray()
|
||||
{
|
||||
m_origin = Vec3d::ZERO;
|
||||
m_direction = -Vec3d::Z_AXIS;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Ray::Ray(const Ray& other) : Object()
|
||||
{
|
||||
m_origin = other.origin();
|
||||
m_direction = other.direction();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Ray::~Ray()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Sets the origin (starting point) of the ray
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void Ray::setOrigin(const Vec3d& orig)
|
||||
{
|
||||
m_origin = orig;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const Vec3d& Ray::origin() const
|
||||
{
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Sets the direction of the ray
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void Ray::setDirection(const Vec3d& dir)
|
||||
{
|
||||
m_direction = dir;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const Vec3d& Ray::direction() const
|
||||
{
|
||||
return m_direction;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Transforms the origin and direction with the given transformation matrix
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void Ray::transform(const Mat4d& matrix)
|
||||
{
|
||||
m_origin.transformPoint(matrix);
|
||||
m_direction.transformVector(matrix);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns this ray transformed with the given transformation matrix
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const Ray Ray::getTransformed(const Mat4d& matrix) const
|
||||
{
|
||||
Ray ray(*this);
|
||||
ray.transform(matrix);
|
||||
|
||||
return ray;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns true if the ray intersects the triangle.
|
||||
///
|
||||
/// intersectionPoint (if not NULL) will be set to the ray intersection point on the triangle.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool Ray::triangleIntersect(const Vec3d& v1, const Vec3d& v2, const Vec3d& v3, Vec3d* intersectionPoint) const
|
||||
{
|
||||
Vec3d v12 = v2 - v1;
|
||||
Vec3d v13 = v3 - v1;
|
||||
|
||||
Vec3d n = (v12 ^ v13).getNormalized();
|
||||
|
||||
double det = n * direction();
|
||||
|
||||
if (det == 0.0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double t = n * ((v1 - origin()) / det);
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vec3d fp = origin() + direction()*t;
|
||||
Vec3d pts[] = { v1, v2, v3, v1 };
|
||||
|
||||
int i;
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
Vec3d bi_norm = -((pts[i+1]-pts[i]) ^ n).getNormalized();
|
||||
|
||||
if (((fp-pts[i]) * bi_norm) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (intersectionPoint)
|
||||
{
|
||||
*intersectionPoint = fp;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns true if the ray intersects the quad.
|
||||
///
|
||||
/// intersectionPoint (if not NULL) will be set to the ray intersection point on the quad.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool Ray::quadIntersect(const Vec3d& v1, const Vec3d& v2, const Vec3d& v3, const Vec3d& v4, Vec3d* intersectionPoint) const
|
||||
{
|
||||
Vec3d v12 = v2 - v1;
|
||||
Vec3d v13 = v3 - v1;
|
||||
|
||||
Vec3d n = (v12 ^ v13).getNormalized();
|
||||
|
||||
double det = n * direction();
|
||||
|
||||
if (det == 0.0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double t = n * ((v1 - origin()) / det);
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vec3d fp = origin() + direction()*t;
|
||||
Vec3d pts[] = { v1, v2, v3, v4, v1 };
|
||||
|
||||
int i;
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
Vec3d bi_norm = -((pts[i+1]-pts[i]) ^ n).getNormalized();
|
||||
|
||||
if (((fp-pts[i]) * bi_norm) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (intersectionPoint)
|
||||
{
|
||||
*intersectionPoint = fp;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns true if the ray intersects the bounding box.
|
||||
///
|
||||
/// intersectionPoint (if not NULL) will be set to the ray intersection point on the bounding box.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool Ray::boxIntersect(const BoundingBox& box, Vec3d* intersectionPoint) const
|
||||
{
|
||||
if (!box.isValid()) return false;
|
||||
|
||||
const int RIGHT = 0;
|
||||
const int LEFT = 1;
|
||||
const int MIDDLE = 2;
|
||||
|
||||
|
||||
// Find candidate planes; this loop can be avoided if rays cast all from the eye(assume perpsective view)
|
||||
bool inside = true;
|
||||
char quadrant[3];
|
||||
double candidatePlane[3];
|
||||
|
||||
Vec3d min = box.min();
|
||||
Vec3d max = box.max();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if(m_origin[i] < min[i])
|
||||
{
|
||||
quadrant[i] = LEFT;
|
||||
candidatePlane[i] = min[i];
|
||||
inside = false;
|
||||
}
|
||||
else if (m_origin[i] > max[i])
|
||||
{
|
||||
quadrant[i] = RIGHT;
|
||||
candidatePlane[i] = max[i];
|
||||
inside = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
quadrant[i] = MIDDLE;
|
||||
}
|
||||
}
|
||||
|
||||
// Ray origin inside bounding box
|
||||
if (inside)
|
||||
{
|
||||
// Return intersection point
|
||||
if (intersectionPoint) *intersectionPoint = m_origin;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calculate T distances to candidate planes
|
||||
double maxT[3];
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (quadrant[i] != MIDDLE && m_direction[i] !=0.0f)
|
||||
{
|
||||
maxT[i] = (candidatePlane[i] - m_origin[i]) / m_direction[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxT[i] = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Get largest of the maxT's for final choice of intersection
|
||||
int whichPlane = 0;
|
||||
for (i = 1; i < 3; i++)
|
||||
{
|
||||
if (maxT[whichPlane] < maxT[i]) whichPlane = i;
|
||||
}
|
||||
|
||||
// Check final candidate actually inside box
|
||||
if (maxT[whichPlane] < 0.0f) return false;
|
||||
|
||||
Vec3d hitPoint;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (whichPlane != i)
|
||||
{
|
||||
hitPoint[i] = m_origin[i] + maxT[whichPlane] * m_direction[i];
|
||||
|
||||
if (hitPoint[i] < min[i] || hitPoint[i] > max[i]) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
hitPoint[i] = candidatePlane[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (intersectionPoint)
|
||||
{
|
||||
*intersectionPoint = hitPoint;
|
||||
}
|
||||
|
||||
// Ray hits box
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns true if the ray intersects the ray
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool Ray::planeIntersect(const Plane& plane, Vec3d* intersectionPoint) const
|
||||
{
|
||||
Vec3d pn = plane.normal();
|
||||
double D = plane.D();
|
||||
|
||||
double vd = pn*m_direction;
|
||||
|
||||
// If vd > 0, the plane normal is pointing 'away' from the ray
|
||||
// We want the plane normal facing the ray so flip direction of the plane
|
||||
if (vd > 0)
|
||||
{
|
||||
pn *= -1;
|
||||
D *= -1;
|
||||
vd *= -1;
|
||||
}
|
||||
|
||||
// No intersection ray and plane normal are parallel
|
||||
if (Math::abs(vd) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
double v0 = -(pn*m_origin + D);
|
||||
double t = v0/vd;
|
||||
if (t >= 0)
|
||||
{
|
||||
if (intersectionPoint)
|
||||
{
|
||||
*intersectionPoint = m_origin + t*m_direction;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
String Ray::toString() const
|
||||
{
|
||||
String str = "Ray: ";
|
||||
str += " origin: x=" + String::number(m_origin.x()) + " y=" + String::number(m_origin.y()) + " z=" + String::number(m_origin.z());
|
||||
str += " direction: x=" + String::number(m_direction.x()) + " y=" + String::number(m_direction.y()) + " z=" + String::number(m_direction.z());
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
65
VisualizationModules/LibGeometry/cvfRay.h
Normal file
65
VisualizationModules/LibGeometry/cvfRay.h
Normal file
@@ -0,0 +1,65 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfObject.h"
|
||||
#include "cvfVector3.h"
|
||||
#include "cvfMatrix4.h"
|
||||
#include "cvfString.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
class BoundingBox;
|
||||
class Plane;
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Ray
|
||||
//
|
||||
//==================================================================================================
|
||||
class Ray : public Object
|
||||
{
|
||||
public:
|
||||
Ray();
|
||||
Ray(const Ray& other);
|
||||
~Ray();
|
||||
|
||||
void setOrigin(const Vec3d& orig);
|
||||
const Vec3d& origin() const;
|
||||
void setDirection(const Vec3d& dir);
|
||||
const Vec3d& direction() const;
|
||||
|
||||
void transform(const Mat4d& matrix);
|
||||
const Ray getTransformed(const Mat4d& matrix) const;
|
||||
|
||||
bool triangleIntersect(const Vec3d& v1, const Vec3d& v2, const Vec3d& v3, Vec3d* intersectionPoint = NULL) const;
|
||||
bool quadIntersect(const Vec3d& v1, const Vec3d& v2, const Vec3d& v3, const Vec3d& v4, Vec3d* intersectionPoint = NULL) const;
|
||||
bool boxIntersect(const BoundingBox& box, Vec3d* intersectionPoint = NULL) const;
|
||||
bool planeIntersect(const Plane& plane, Vec3d* intersectionPoint = NULL) const;
|
||||
|
||||
String toString() const;
|
||||
|
||||
private:
|
||||
Vec3d m_origin; ///< Starting point of ray
|
||||
Vec3d m_direction; ///< Vector specifying ray direction
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfTriangleMeshEdgeExtractor.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::TriangleMeshEdgeExtractor
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TriangleMeshEdgeExtractor::TriangleMeshEdgeExtractor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void TriangleMeshEdgeExtractor::addTriangles(const UIntArray& indices, const UIntArray& triangleKeys)
|
||||
{
|
||||
size_t index = 0;
|
||||
size_t numTris = indices.size()/3;
|
||||
size_t tri;
|
||||
for (tri = 0; tri < numTris; tri++)
|
||||
{
|
||||
uint key = triangleKeys[tri];
|
||||
|
||||
uint v1 = indices[index++];
|
||||
uint v2 = indices[index++];
|
||||
uint v3 = indices[index++];
|
||||
|
||||
addEdge(v1, v2, key);
|
||||
addEdge(v2, v3, key);
|
||||
addEdge(v3, v1, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void TriangleMeshEdgeExtractor::addEdge(uint v1, uint v2, uint key)
|
||||
{
|
||||
int64 edgeKeyVal = 0;
|
||||
|
||||
if (v1 < v2)
|
||||
{
|
||||
edgeKeyVal = v2;
|
||||
edgeKeyVal <<= 32;
|
||||
edgeKeyVal += v1;
|
||||
}
|
||||
else
|
||||
{
|
||||
edgeKeyVal = v1;
|
||||
edgeKeyVal <<= 32;
|
||||
edgeKeyVal += v2;
|
||||
}
|
||||
|
||||
std::map<int64, uint>::iterator it = m_edgeMap.find(edgeKeyVal);
|
||||
|
||||
if (it != m_edgeMap.end())
|
||||
{
|
||||
uint foundKey = it->second;
|
||||
|
||||
if (foundKey == key)
|
||||
{
|
||||
// Remove edge from map and return
|
||||
m_edgeMap.erase(it);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_edgeMap[edgeKeyVal] = key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UIntArray> TriangleMeshEdgeExtractor::lineIndices() const
|
||||
{
|
||||
ref<UIntArray> indices = new UIntArray;
|
||||
|
||||
size_t numEdges = m_edgeMap.size();
|
||||
if (numEdges == 0)
|
||||
{
|
||||
return indices;
|
||||
}
|
||||
|
||||
indices->reserve(2*numEdges);
|
||||
|
||||
std::map<cvf::int64, uint>::const_iterator it;
|
||||
for (it = m_edgeMap.begin(); it != m_edgeMap.end(); ++it)
|
||||
{
|
||||
int64 edgeKey = it->first;
|
||||
uint v1 = static_cast<uint>(edgeKey);
|
||||
uint v2 = static_cast<uint>(edgeKey>>32);
|
||||
|
||||
indices->add(v1);
|
||||
indices->add(v2);
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
} // namespace cvf
|
||||
@@ -0,0 +1,63 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfArray.h"
|
||||
#include <map>
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Extract mesh from triangles with a key per triangle. Mesh edges will not be produced between
|
||||
// triangles with the same key.
|
||||
//
|
||||
//==================================================================================================
|
||||
class TriangleMeshEdgeExtractor
|
||||
{
|
||||
public:
|
||||
TriangleMeshEdgeExtractor();
|
||||
|
||||
void addTriangles(const UIntArray& indices, const UIntArray& triangleKeys);
|
||||
|
||||
ref<UIntArray> lineIndices() const;
|
||||
|
||||
private:
|
||||
std::map<int64, uint> m_edgeMap;
|
||||
|
||||
inline int64 edgeKey(uint v1, uint v2)
|
||||
{
|
||||
if (v1 < v2)
|
||||
{
|
||||
int64 key = v2;
|
||||
key <<= 32;
|
||||
return key + v1;
|
||||
}
|
||||
|
||||
int64 key = v1;
|
||||
key <<= 32;
|
||||
return key + v2;
|
||||
}
|
||||
|
||||
void addEdge(uint v1, uint v2, uint key);
|
||||
};
|
||||
|
||||
}
|
||||
322
VisualizationModules/LibGeometry/cvfTriangleVertexSplitter.cpp
Normal file
322
VisualizationModules/LibGeometry/cvfTriangleVertexSplitter.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfTriangleVertexSplitter.h"
|
||||
#include "cvfFrustum.h"
|
||||
#include "cvfOutlineEdgeExtractor.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::TriangleVertexSplitter
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// This class takes a triangle mesh and duplicates nodes on edges where the normal of the two triangles
|
||||
/// on the edge differ more than the given crease angle.
|
||||
///
|
||||
/// The vertices are also compacted, so the returned vertexArray() contains only the vertices
|
||||
/// referenced by the triangles.
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TriangleVertexSplitter::TriangleVertexSplitter(double creaseAngle, const cvf::UIntValueArray& origTriangleIndices, const cvf::Vec3fValueArray& origVertexArray)
|
||||
: m_creaseAngle(creaseAngle),
|
||||
m_origTriangleIndices(origTriangleIndices),
|
||||
m_origVertexArray(origVertexArray),
|
||||
m_isComputed(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns the new connectivity table for the triangles. Same size as the input origTriangleIndices
|
||||
/// array
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UIntArray> TriangleVertexSplitter::triangleIndices()
|
||||
{
|
||||
if (!m_isComputed)
|
||||
{
|
||||
splitVertices();
|
||||
}
|
||||
|
||||
return m_triangleIndices;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns the new vertex array containg only the referenced nodes in the triangle mesh, but with
|
||||
/// split nodes wherever needed.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<Vec3fArray> TriangleVertexSplitter::vertexArray()
|
||||
{
|
||||
if (!m_isComputed)
|
||||
{
|
||||
splitVertices();
|
||||
}
|
||||
|
||||
ref<Vec3fArray> output = new Vec3fArray(m_vertexArray);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns an array with vertex indices into the input origVertexArray for each vertex in the
|
||||
/// output vertexArray(). Used to keep track of the original index of the compacted and split output
|
||||
/// array.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UIntArray> TriangleVertexSplitter::perVertexOriginalIndices()
|
||||
{
|
||||
if (!m_isComputed)
|
||||
{
|
||||
splitVertices();
|
||||
}
|
||||
|
||||
size_t numUsedVertices = m_vertexArray.size();
|
||||
ref<UIntArray> output = new UIntArray;
|
||||
|
||||
if (numUsedVertices == 0)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
output->resize(numUsedVertices);
|
||||
output->setAll(UNDEFINED_UINT);
|
||||
|
||||
size_t numOrigVertices = m_origVertexArray.size();
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numOrigVertices; i++)
|
||||
{
|
||||
uint usedIdx = m_origToUsedNodeMap[i];
|
||||
|
||||
if (usedIdx != UNDEFINED_UINT)
|
||||
{
|
||||
output->set(usedIdx, static_cast<uint>(i));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < numUsedVertices; i++)
|
||||
{
|
||||
if (output->get(i) != UNDEFINED_UINT)
|
||||
{
|
||||
uint origIndex = output->get(i);
|
||||
uint nextSplit = m_nextSplitVertexIdx[i];
|
||||
m_nextSplitVertexIdx[i] = UNDEFINED_UINT;
|
||||
|
||||
while (nextSplit != UNDEFINED_UINT)
|
||||
{
|
||||
CVF_TIGHT_ASSERT(output->get(nextSplit) == UNDEFINED_UINT);
|
||||
|
||||
output->set(nextSplit, origIndex);
|
||||
|
||||
uint nextSplitThis = nextSplit;
|
||||
nextSplit = m_nextSplitVertexIdx[nextSplit];
|
||||
m_nextSplitVertexIdx[nextSplitThis] = UNDEFINED_UINT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns an array of smooth per vertex normals corresponding to the output vertexArray().
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<Vec3fArray> TriangleVertexSplitter::vertexNormals()
|
||||
{
|
||||
if (!m_isComputed)
|
||||
{
|
||||
splitVertices();
|
||||
}
|
||||
|
||||
size_t numVertices = m_normalArray.size();
|
||||
ref<Vec3fArray> output = new Vec3fArray;
|
||||
|
||||
if (numVertices == 0)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
output->reserve(numVertices);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numVertices; i++)
|
||||
{
|
||||
output->add(m_normalArray[i].getNormalized());
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Worker. Split the vertices that needs splitting and compact the vertexArray and indices.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void TriangleVertexSplitter::splitVertices()
|
||||
{
|
||||
CVF_ASSERT(!m_isComputed);
|
||||
m_isComputed = true;
|
||||
|
||||
// Handle empty data;
|
||||
if (m_origTriangleIndices.size() == 0)
|
||||
{
|
||||
m_triangleIndices = new UIntArray;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
size_t origVertexCount = m_origVertexArray.size();
|
||||
m_triangleIndices = new UIntArray(m_origTriangleIndices);
|
||||
|
||||
m_vertexArray.reserve(origVertexCount);
|
||||
m_normalArray.reserve(origVertexCount);
|
||||
m_nextSplitVertexIdx.reserve(origVertexCount);
|
||||
|
||||
m_origToUsedNodeMap.resize(origVertexCount);
|
||||
m_origToUsedNodeMap.setAll(UNDEFINED_UINT);
|
||||
|
||||
size_t origConnIndex = 0;
|
||||
size_t numTris = m_triangleIndices->size() / 3;
|
||||
size_t tri;
|
||||
for (tri = 0; tri < numTris; tri++)
|
||||
{
|
||||
uint c0 = m_origTriangleIndices.val(origConnIndex);
|
||||
uint c1 = m_origTriangleIndices.val(origConnIndex + 1);
|
||||
uint c2 = m_origTriangleIndices.val(origConnIndex + 2);
|
||||
|
||||
// Compute normal
|
||||
Vec3f v0 = m_origVertexArray.val(c0);
|
||||
Vec3f v1 = m_origVertexArray.val(c1);
|
||||
Vec3f v2 = m_origVertexArray.val(c2);
|
||||
|
||||
Vec3f normal = (v1 - v0) ^ (v2 - v0);
|
||||
normal.normalize();
|
||||
|
||||
uint newConn1 = processVertex(c0, normal);
|
||||
uint newConn2 = processVertex(c1, normal);
|
||||
uint newConn3 = processVertex(c2, normal);
|
||||
|
||||
m_triangleIndices->set(origConnIndex, newConn1);
|
||||
m_triangleIndices->set(origConnIndex + 1, newConn2);
|
||||
m_triangleIndices->set(origConnIndex + 2, newConn3);
|
||||
|
||||
origConnIndex += 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns the new index of the given vertex based on if the vertex will be split or not.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint TriangleVertexSplitter::processVertex(uint origVertexIndex, const Vec3f& faceNormal)
|
||||
{
|
||||
uint vertexIndex = m_origToUsedNodeMap[origVertexIndex];
|
||||
|
||||
if (vertexIndex == UNDEFINED_UINT)
|
||||
{
|
||||
vertexIndex = static_cast<uint>(m_vertexArray.size());
|
||||
m_origToUsedNodeMap[origVertexIndex] = vertexIndex;
|
||||
|
||||
m_vertexArray.push_back(m_origVertexArray.val(origVertexIndex));
|
||||
m_normalArray.push_back(faceNormal);
|
||||
m_nextSplitVertexIdx.push_back(UNDEFINED_UINT);
|
||||
|
||||
return vertexIndex;
|
||||
}
|
||||
|
||||
uint outputIndex = vertexIndex;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
const Vec3f& vertexNormal = m_normalArray[outputIndex].getNormalized();
|
||||
|
||||
if (isNormalDifferenceBelowThreshold(faceNormal, vertexNormal))
|
||||
{
|
||||
m_normalArray[outputIndex] += faceNormal;
|
||||
return outputIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint nextVertexIndex = m_nextSplitVertexIdx[outputIndex];
|
||||
|
||||
if (nextVertexIndex == UNDEFINED_UINT)
|
||||
{
|
||||
// Cannot average with any existing normal in orig or new split vertices
|
||||
uint newVertexIndex = static_cast<uint>(m_vertexArray.size());
|
||||
|
||||
m_nextSplitVertexIdx[outputIndex] = newVertexIndex;
|
||||
outputIndex = newVertexIndex;
|
||||
|
||||
m_vertexArray.push_back(m_vertexArray[vertexIndex]);
|
||||
m_normalArray.push_back(faceNormal);
|
||||
m_nextSplitVertexIdx.push_back(UNDEFINED_UINT);
|
||||
|
||||
return outputIndex;
|
||||
}
|
||||
|
||||
outputIndex = nextVertexIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Return true if the angle between the two normals are below the current crease angle.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool TriangleVertexSplitter::isNormalDifferenceBelowThreshold(const Vec3f& n1, const Vec3f& n2)
|
||||
{
|
||||
if (n1.isZero() || n2.isZero())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double dotProduct = n1*n2;
|
||||
|
||||
// Guard acos against out-of-domain input
|
||||
|
||||
if (dotProduct <= -1.0)
|
||||
{
|
||||
dotProduct = -1.0;
|
||||
}
|
||||
else if (dotProduct >= 1.0)
|
||||
{
|
||||
dotProduct = 1.0;
|
||||
}
|
||||
|
||||
double angle = Math::acos(dotProduct);
|
||||
|
||||
if (Math::abs(angle) < m_creaseAngle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (Math::abs(angle) >= m_creaseAngle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace cvf
|
||||
59
VisualizationModules/LibGeometry/cvfTriangleVertexSplitter.h
Normal file
59
VisualizationModules/LibGeometry/cvfTriangleVertexSplitter.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfArray.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
//=================================================================================================
|
||||
//
|
||||
// Triangle Vertex Splitter Class
|
||||
//
|
||||
//=================================================================================================
|
||||
class TriangleVertexSplitter
|
||||
{
|
||||
public:
|
||||
TriangleVertexSplitter(double creaseAngle, const UIntValueArray& origTriangleIndices, const Vec3fValueArray& origVertexArray);
|
||||
|
||||
ref<UIntArray> triangleIndices();
|
||||
ref<Vec3fArray> vertexArray();
|
||||
ref<Vec3fArray> vertexNormals();
|
||||
ref<UIntArray> perVertexOriginalIndices(); // Per vertex (source) indices into origVertexArray
|
||||
|
||||
private:
|
||||
void splitVertices();
|
||||
uint processVertex(uint origVertexIndex, const Vec3f& faceNormal);
|
||||
bool isNormalDifferenceBelowThreshold(const Vec3f& n1, const Vec3f& n2);
|
||||
|
||||
private:
|
||||
double m_creaseAngle;
|
||||
const UIntValueArray& m_origTriangleIndices;
|
||||
const Vec3fValueArray& m_origVertexArray;
|
||||
|
||||
bool m_isComputed;
|
||||
ref<UIntArray> m_triangleIndices;
|
||||
UIntArray m_origToUsedNodeMap;
|
||||
std::vector<uint> m_nextSplitVertexIdx;
|
||||
std::vector<Vec3f> m_vertexArray;
|
||||
std::vector<Vec3f> m_normalArray;
|
||||
};
|
||||
|
||||
}
|
||||
119
VisualizationModules/LibGeometry/cvfVertexCompactor.cpp
Normal file
119
VisualizationModules/LibGeometry/cvfVertexCompactor.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfVertexCompactor.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::VertexCompactor
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Worker class for creating compact indices based on a "global" index array
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
VertexCompactor::VertexCompactor(const UIntValueArray& origIndices, const Vec3fValueArray& origVertexArray)
|
||||
: m_origIndices(origIndices),
|
||||
m_origVertexArray(origVertexArray)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void VertexCompactor::computeCompactedIndices()
|
||||
{
|
||||
m_newIndices = new UIntArray;
|
||||
m_newToOldVertexIndexMapping = new UIntArray;
|
||||
uint maxNumResultingVertices = static_cast<uint>(m_origVertexArray.size());
|
||||
GeometryUtils::removeUnusedVertices(m_origIndices, m_newIndices.p(), m_newToOldVertexIndexMapping.p(), maxNumResultingVertices);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Get indices into new vertex array
|
||||
///
|
||||
/// \return Newly allocated array with the new indices. An array is always returned, but may have zero entries.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UIntArray> VertexCompactor::indices()
|
||||
{
|
||||
if (m_newIndices.isNull())
|
||||
{
|
||||
computeCompactedIndices();
|
||||
}
|
||||
|
||||
CVF_ASSERT(m_newIndices.notNull());
|
||||
return m_newIndices;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<Vec3fArray> VertexCompactor::vertexArray()
|
||||
{
|
||||
if (m_newIndices.isNull())
|
||||
{
|
||||
computeCompactedIndices();
|
||||
}
|
||||
|
||||
CVF_ASSERT(m_newToOldVertexIndexMapping.notNull());
|
||||
ref<Vec3fArray> vertices = new Vec3fArray;
|
||||
size_t numNewVertices = m_newToOldVertexIndexMapping->size();
|
||||
if (numNewVertices > 0)
|
||||
{
|
||||
vertices->reserve(numNewVertices);
|
||||
size_t i;
|
||||
for (i = 0; i < numNewVertices; i++)
|
||||
{
|
||||
vertices->add(m_origVertexArray.val(m_newToOldVertexIndexMapping->get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
return vertices;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Get array of original indices per new vertex.
|
||||
///
|
||||
/// The returned array will be the same size as the array of vertices returned by vertexArray().
|
||||
/// The indices are the original/source indices of the vertices
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<UIntArray> VertexCompactor::perVertexOriginalIndices()
|
||||
{
|
||||
if (m_newToOldVertexIndexMapping.isNull())
|
||||
{
|
||||
computeCompactedIndices();
|
||||
}
|
||||
|
||||
CVF_ASSERT(m_newToOldVertexIndexMapping.notNull());
|
||||
return m_newToOldVertexIndexMapping;
|
||||
}
|
||||
|
||||
} // namespace cvf
|
||||
52
VisualizationModules/LibGeometry/cvfVertexCompactor.h
Normal file
52
VisualizationModules/LibGeometry/cvfVertexCompactor.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfArray.h"
|
||||
#include "cvfVector3.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
//=================================================================================================
|
||||
//
|
||||
// Vertex Compactor class
|
||||
//
|
||||
//=================================================================================================
|
||||
class VertexCompactor
|
||||
{
|
||||
public:
|
||||
VertexCompactor(const UIntValueArray& origIndices, const Vec3fValueArray& origVertexArray);
|
||||
|
||||
ref<UIntArray> indices();
|
||||
ref<Vec3fArray> vertexArray();
|
||||
ref<UIntArray> perVertexOriginalIndices();
|
||||
|
||||
private:
|
||||
void computeCompactedIndices();
|
||||
|
||||
private:
|
||||
const UIntValueArray& m_origIndices; // Indices into the original vertex array
|
||||
const Vec3fValueArray& m_origVertexArray; // Original vertex array
|
||||
|
||||
ref<UIntArray> m_newIndices; // Indices into new vertex array
|
||||
ref<UIntArray> m_newToOldVertexIndexMapping; // For each new vertex, this array will store the vertex' original (source) index into origVertexArray
|
||||
};
|
||||
|
||||
}
|
||||
260
VisualizationModules/LibGeometry/cvfVertexWelder.cpp
Normal file
260
VisualizationModules/LibGeometry/cvfVertexWelder.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfVertexWelder.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::VertexWelder
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// Supports welding of vertices based on vertex distance
|
||||
///
|
||||
/// \internal Adapted from the book: "Real time collision detection' by Christer Ericson
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
VertexWelder::VertexWelder()
|
||||
{
|
||||
m_weldEpsilon = 0;
|
||||
m_cellSize = 0;
|
||||
m_numBuckets = 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Initialize, must be done before usage of object
|
||||
///
|
||||
/// The cell size must be at least 2*weldingDistance, but should normally be much larger. If the
|
||||
/// specified cell size is too small, it will be set to approximately 2*weldingDistance
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void VertexWelder::initialize(double weldingDistance, double cellSize, uint numBuckets)
|
||||
{
|
||||
CVF_ASSERT(weldingDistance >= 0);
|
||||
CVF_ASSERT(cellSize > 2*weldingDistance);
|
||||
CVF_ASSERT(numBuckets > 0);
|
||||
|
||||
m_weldEpsilon = weldingDistance;
|
||||
m_cellSize = cellSize;
|
||||
if (m_cellSize < 2.1*weldingDistance)
|
||||
{
|
||||
m_cellSize = 2.1*weldingDistance;
|
||||
}
|
||||
|
||||
m_numBuckets = numBuckets;
|
||||
m_first.resize(numBuckets);
|
||||
m_first.setAll(UNDEFINED_UINT);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void VertexWelder::reserveVertices(uint vertexCount)
|
||||
{
|
||||
m_vertex.reserve(vertexCount);
|
||||
m_next.reserve(vertexCount);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint VertexWelder::weldVertex(const Vec3f& vertex, bool* wasWelded)
|
||||
{
|
||||
// Must be initialized
|
||||
CVF_ASSERT(m_cellSize > 0 && m_numBuckets > 0);
|
||||
|
||||
// Make sure welding distance (epsilon) is not too small for the coordinates used!
|
||||
// Not sure if we need to handle this case - unsure of what happens if epsilon gets too small.
|
||||
// Guess the only trouble is that we won't look into neighbor cells, which in turn
|
||||
// means that we won't be able to weld vertices even if they are closer than epsilon.
|
||||
//CVF_ASSERT(vertex.x() - m_weldEpsilon != vertex.x() && vertex.x() + m_weldEpsilon != vertex.x());
|
||||
//CVF_ASSERT(vertex.y() - m_weldEpsilon != vertex.y() && vertex.y() + m_weldEpsilon != vertex.y());
|
||||
//CVF_ASSERT(vertex.z() - m_weldEpsilon != vertex.z() && vertex.z() + m_weldEpsilon != vertex.z());
|
||||
|
||||
// Compute cell coordinates of bounding box of vertex epsilon neighborhood
|
||||
int left = int((vertex.x() - m_weldEpsilon) / m_cellSize);
|
||||
int right = int((vertex.x() + m_weldEpsilon) / m_cellSize);
|
||||
int front = int((vertex.y() - m_weldEpsilon) / m_cellSize);
|
||||
int back = int((vertex.y() + m_weldEpsilon) / m_cellSize);
|
||||
int bottom = int((vertex.z() - m_weldEpsilon) / m_cellSize);
|
||||
int top = int((vertex.z() + m_weldEpsilon) / m_cellSize);
|
||||
|
||||
// To lessen effects of worst-case behavior, track previously tested buckets
|
||||
// 4 in 2D, 8 in 3D
|
||||
uint prevBucket[8];
|
||||
int numPrevBuckets = 0;
|
||||
|
||||
// Loop over all overlapped cells and test against their buckets
|
||||
int i;
|
||||
for (i = left; i <= right; i++)
|
||||
{
|
||||
int j;
|
||||
for (j = front; j <= back; j++)
|
||||
{
|
||||
int k;
|
||||
for (k = bottom; k <= top; k++)
|
||||
{
|
||||
uint bucket = getGridCellBucket(i, j, k);
|
||||
|
||||
// If this bucket already tested, don't test it again
|
||||
bool bucketAlreadyTested = false;
|
||||
for (int b = 0; b < numPrevBuckets; b++)
|
||||
{
|
||||
if (bucket == prevBucket[b])
|
||||
{
|
||||
bucketAlreadyTested = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bucketAlreadyTested)
|
||||
{
|
||||
// Add this bucket to visited list, then test against its contents
|
||||
CVF_ASSERT(numPrevBuckets < 8);
|
||||
prevBucket[numPrevBuckets++] = bucket;
|
||||
|
||||
// Call function to step through linked list of bucket, testing
|
||||
// if vertex is within the epsilon of one of the vertices in the bucket
|
||||
uint indexOfLocatedVertex = locateVertexInBucket(vertex, bucket);
|
||||
if (indexOfLocatedVertex != UNDEFINED_UINT)
|
||||
{
|
||||
if (wasWelded) *wasWelded = true;
|
||||
|
||||
return indexOfLocatedVertex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't locate vertex, so add it to grid
|
||||
int x = int(vertex.x() / m_cellSize);
|
||||
int y = int(vertex.y() / m_cellSize);
|
||||
int z = int(vertex.z() / m_cellSize);
|
||||
uint indexOfAddedVertex = addVertexToBucket(vertex, getGridCellBucket(x, y, z));
|
||||
|
||||
if (wasWelded) *wasWelded = false;
|
||||
|
||||
return indexOfAddedVertex;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Maps unbounded grid cell coordinates (x, y, z) into an index into a fixed-size array of hash buckets
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint VertexWelder::getGridCellBucket(int x, int y, int z) const
|
||||
{
|
||||
// Large multiplicative constants; here arbitrarily chosen primes
|
||||
const uint magic1 = 0x8da6b343;
|
||||
const uint magic2 = 0xd8163841;
|
||||
const uint magic3 = 0xcb1ab31f;
|
||||
|
||||
uint index = magic1*x + magic2*y + z*magic3;
|
||||
|
||||
// Bring index into [0, m_numBuckets) range
|
||||
return index % m_numBuckets;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint VertexWelder::locateVertexInBucket(const Vec3f& v, uint bucket) const
|
||||
{
|
||||
const double weldEpsilonSqared = m_weldEpsilon*m_weldEpsilon;
|
||||
|
||||
// Scan through linked list of vertices at this bucket
|
||||
uint index = m_first[bucket];
|
||||
while (index != UNDEFINED_UINT)
|
||||
{
|
||||
// Weld this vertex to existing vertex if within given distance tolerance
|
||||
float sqDistPointPoint = (m_vertex[index] - v).lengthSquared();
|
||||
if (sqDistPointPoint < weldEpsilonSqared)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
index = m_next[index];
|
||||
}
|
||||
|
||||
// No vertex found to weld to.
|
||||
return UNDEFINED_UINT;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint VertexWelder::addVertexToBucket(const Vec3f& v, uint bucket)
|
||||
{
|
||||
CVF_TIGHT_ASSERT(bucket < m_numBuckets);
|
||||
CVF_TIGHT_ASSERT(m_numBuckets == m_first.size());
|
||||
|
||||
// Fill next available vertex buffer entry and link it into vertex list
|
||||
m_vertex.push_back(v);
|
||||
m_next.push_back(m_first[bucket]);
|
||||
CVF_TIGHT_ASSERT(m_vertex.size() == m_next.size());
|
||||
|
||||
uint indexOfAddedVertex = static_cast<uint>(m_vertex.size() - 1);
|
||||
m_first[bucket] = indexOfAddedVertex;
|
||||
|
||||
return indexOfAddedVertex;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
uint VertexWelder::vertexCount() const
|
||||
{
|
||||
return static_cast<uint>(m_vertex.size());
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const Vec3f& VertexWelder::vertex(uint index) const
|
||||
{
|
||||
return m_vertex[index];
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ref<Vec3fArray> VertexWelder::createVertexArray() const
|
||||
{
|
||||
ref<Vec3fArray> va = new Vec3fArray(m_vertex);
|
||||
return va;
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
68
VisualizationModules/LibGeometry/cvfVertexWelder.h
Normal file
68
VisualizationModules/LibGeometry/cvfVertexWelder.h
Normal file
@@ -0,0 +1,68 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfArray.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class VertexWelder
|
||||
{
|
||||
public:
|
||||
VertexWelder();
|
||||
|
||||
void initialize(double weldingDistance, double cellSize, uint numBuckets);
|
||||
void reserveVertices(uint vertexCount);
|
||||
|
||||
uint weldVertex(const Vec3f& vertex, bool* wasWelded);
|
||||
|
||||
uint vertexCount() const;
|
||||
const Vec3f& vertex(uint index) const;
|
||||
ref<Vec3fArray> createVertexArray() const;
|
||||
|
||||
private:
|
||||
uint getGridCellBucket(int x, int y, int z) const;
|
||||
uint locateVertexInBucket(const Vec3f& v, uint bucket) const;
|
||||
uint addVertexToBucket(const Vec3f& v, uint bucket);
|
||||
|
||||
private:
|
||||
double m_weldEpsilon; // Welding tolerance, radius around vertex defining welding neighborhood
|
||||
double m_cellSize; // Grid cell size; must be at least 2*m_weldEpsilon
|
||||
|
||||
uint m_numBuckets; // Number of hash buckets to map grid cells into
|
||||
UIntArray m_first; // Start of linked list for each bucket. Number of buckets long
|
||||
|
||||
std::vector<uint> m_next; // Links each vertex to next in linked list. Always numVertices long, will grow as vertices are added
|
||||
std::vector<Vec3f> m_vertex; // Unique vertices within tolerance
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user