This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/intern/opensubdiv/internal/topology/topology_refiner_capi.cc

263 lines
9.7 KiB
C++

// Copyright 2018 Blender Foundation. All rights reserved.
//
// This program 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 2
// of the License, or (at your option) any later version.
//
// This program 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 for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// Author: Sergey Sharybin
#include "opensubdiv_topology_refiner_capi.h"
#include "MEM_guardedalloc.h"
#include "internal/base/type_convert.h"
#include "internal/topology/topology_refiner_impl.h"
using blender::opensubdiv::vector;
namespace {
const OpenSubdiv::Far::TopologyRefiner *getOSDTopologyRefiner(
const OpenSubdiv_TopologyRefiner *topology_refiner)
{
return topology_refiner->impl->topology_refiner;
}
const OpenSubdiv::Far::TopologyLevel &getOSDTopologyBaseLevel(
const OpenSubdiv_TopologyRefiner *topology_refiner)
{
return getOSDTopologyRefiner(topology_refiner)->GetLevel(0);
}
int getSubdivisionLevel(const OpenSubdiv_TopologyRefiner *topology_refiner)
{
return topology_refiner->impl->settings.level;
}
bool getIsAdaptive(const OpenSubdiv_TopologyRefiner *topology_refiner)
{
return topology_refiner->impl->settings.is_adaptive;
}
////////////////////////////////////////////////////////////////////////////////
// Query basic topology information from base level.
int getNumVertices(const OpenSubdiv_TopologyRefiner *topology_refiner)
{
return getOSDTopologyBaseLevel(topology_refiner).GetNumVertices();
}
int getNumEdges(const OpenSubdiv_TopologyRefiner *topology_refiner)
{
return getOSDTopologyBaseLevel(topology_refiner).GetNumEdges();
}
int getNumFaces(const OpenSubdiv_TopologyRefiner *topology_refiner)
{
return getOSDTopologyBaseLevel(topology_refiner).GetNumFaces();
}
////////////////////////////////////////////////////////////////////////////////
// PTex face geometry queries.
static void convertArrayToRaw(const OpenSubdiv::Far::ConstIndexArray &array, int *raw_array)
{
for (int i = 0; i < array.size(); ++i) {
raw_array[i] = array[i];
}
}
int getNumFaceVertices(const OpenSubdiv_TopologyRefiner *topology_refiner, const int face_index)
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
return base_level.GetFaceVertices(face_index).size();
}
void getFaceVertices(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
int *face_vertices_indices)
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
OpenSubdiv::Far::ConstIndexArray array = base_level.GetFaceVertices(face_index);
convertArrayToRaw(array, face_vertices_indices);
}
int getNumFaceEdges(const OpenSubdiv_TopologyRefiner *topology_refiner, const int face_index)
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
return base_level.GetFaceEdges(face_index).size();
}
void getFaceEdges(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
int *face_edges_indices)
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
OpenSubdiv::Far::ConstIndexArray array = base_level.GetFaceEdges(face_index);
convertArrayToRaw(array, face_edges_indices);
}
void getEdgeVertices(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int edge_index,
int edge_vertices_indices[2])
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
OpenSubdiv::Far::ConstIndexArray array = base_level.GetEdgeVertices(edge_index);
assert(array.size() == 2);
edge_vertices_indices[0] = array[0];
edge_vertices_indices[1] = array[1];
}
int getNumVertexEdges(const OpenSubdiv_TopologyRefiner *topology_refiner, const int vertex_index)
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
return base_level.GetVertexEdges(vertex_index).size();
}
void getVertexEdges(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int vertex_index,
int *vertex_edges_indices)
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
OpenSubdiv::Far::ConstIndexArray array = base_level.GetVertexEdges(vertex_index);
convertArrayToRaw(array, vertex_edges_indices);
}
int getNumFacePtexFaces(const OpenSubdiv_TopologyRefiner *topology_refiner, const int face_index)
{
const int num_face_vertices = topology_refiner->getNumFaceVertices(topology_refiner, face_index);
if (num_face_vertices == 4) {
return 1;
}
else {
return num_face_vertices;
}
}
int getNumPtexFaces(const OpenSubdiv_TopologyRefiner *topology_refiner)
{
const int num_faces = topology_refiner->getNumFaces(topology_refiner);
int num_ptex_faces = 0;
for (int face_index = 0; face_index < num_faces; ++face_index) {
num_ptex_faces += topology_refiner->getNumFacePtexFaces(topology_refiner, face_index);
}
return num_ptex_faces;
}
void fillFacePtexIndexOffset(const OpenSubdiv_TopologyRefiner *topology_refiner,
int *face_ptex_index_offset)
{
const int num_faces = topology_refiner->getNumFaces(topology_refiner);
int num_ptex_faces = 0;
for (int face_index = 0; face_index < num_faces; ++face_index) {
face_ptex_index_offset[face_index] = num_ptex_faces;
num_ptex_faces += topology_refiner->getNumFacePtexFaces(topology_refiner, face_index);
}
}
////////////////////////////////////////////////////////////////////////////////
// Face-varying data.
int getNumFVarChannels(const struct OpenSubdiv_TopologyRefiner *topology_refiner)
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
return base_level.GetNumFVarChannels();
}
OpenSubdiv_FVarLinearInterpolation getFVarLinearInterpolation(
const struct OpenSubdiv_TopologyRefiner *topology_refiner)
{
return blender::opensubdiv::getCAPIFVarLinearInterpolationFromOSD(
getOSDTopologyRefiner(topology_refiner)->GetFVarLinearInterpolation());
}
int getNumFVarValues(const struct OpenSubdiv_TopologyRefiner *topology_refiner, const int channel)
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
return base_level.GetNumFVarValues(channel);
}
const int *getFaceFVarValueIndices(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
const int channel)
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
return &base_level.GetFaceFVarValues(face_index, channel)[0];
}
////////////////////////////////////////////////////////////////////////////////
// Internal helpers.
void assignFunctionPointers(OpenSubdiv_TopologyRefiner *topology_refiner)
{
topology_refiner->getSubdivisionLevel = getSubdivisionLevel;
topology_refiner->getIsAdaptive = getIsAdaptive;
// Basic topology information.
topology_refiner->getNumVertices = getNumVertices;
topology_refiner->getNumEdges = getNumEdges;
topology_refiner->getNumFaces = getNumFaces;
topology_refiner->getNumFaceVertices = getNumFaceVertices;
topology_refiner->getFaceVertices = getFaceVertices;
topology_refiner->getNumFaceEdges = getNumFaceEdges;
topology_refiner->getFaceEdges = getFaceEdges;
topology_refiner->getEdgeVertices = getEdgeVertices;
topology_refiner->getNumVertexEdges = getNumVertexEdges;
topology_refiner->getVertexEdges = getVertexEdges;
// PTex face geometry.
topology_refiner->getNumFacePtexFaces = getNumFacePtexFaces;
topology_refiner->getNumPtexFaces = getNumPtexFaces;
topology_refiner->fillFacePtexIndexOffset = fillFacePtexIndexOffset;
// Face-varying data.
topology_refiner->getNumFVarChannels = getNumFVarChannels;
topology_refiner->getFVarLinearInterpolation = getFVarLinearInterpolation;
topology_refiner->getNumFVarValues = getNumFVarValues;
topology_refiner->getFaceFVarValueIndices = getFaceFVarValueIndices;
}
OpenSubdiv_TopologyRefiner *allocateTopologyRefiner()
{
OpenSubdiv_TopologyRefiner *topology_refiner = OBJECT_GUARDED_NEW(OpenSubdiv_TopologyRefiner);
assignFunctionPointers(topology_refiner);
return topology_refiner;
}
} // namespace
OpenSubdiv_TopologyRefiner *openSubdiv_createTopologyRefinerFromConverter(
OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings *settings)
{
using blender::opensubdiv::TopologyRefinerImpl;
TopologyRefinerImpl *topology_refiner_impl = TopologyRefinerImpl::createFromConverter(converter,
*settings);
if (topology_refiner_impl == nullptr) {
return nullptr;
}
OpenSubdiv_TopologyRefiner *topology_refiner = allocateTopologyRefiner();
topology_refiner->impl = static_cast<OpenSubdiv_TopologyRefinerImpl *>(topology_refiner_impl);
return topology_refiner;
}
void openSubdiv_deleteTopologyRefiner(OpenSubdiv_TopologyRefiner *topology_refiner)
{
delete topology_refiner->impl;
OBJECT_GUARDED_DELETE(topology_refiner, OpenSubdiv_TopologyRefiner);
}
bool openSubdiv_topologyRefinerCompareWithConverter(
const OpenSubdiv_TopologyRefiner *topology_refiner, const OpenSubdiv_Converter *converter)
{
return topology_refiner->impl->isEqualToConverter(converter);
}