11#ifndef JAU_GAMP_GRAPH_TESS_GL_GLUTESSELATOR_HPP_
12#define JAU_GAMP_GRAPH_TESS_GL_GLUTESSELATOR_HPP_
17#include <GL/glutess2.h>
31 using namespace jau::math;
32 using namespace jau::math::geom;
33 using namespace gamp::graph;
34 using namespace gamp::render::gl::data;
72 r.append(
jau::format_string_v(256,
"%sSegment[%zu]: %s\n", pre.c_str(), i++, s.toString().c_str()) );
78 std::string_view type_s;
80 case GL_TRIANGLE_STRIP:
81 type_s =
"triangle_strip";
break;
83 type_s =
"triangle_fan";
break;
85 type_s =
"triangles";
break;
89 return std::string(
"Segment[").append(type_s)
90 .append(
", 1st ").append(std::to_string(
first))
91 .append(
", count ").append(std::to_string(
count)).append(
"]");
99 std::vector<std::shared_ptr<Vertex>> m_vcache;
101 uint32_t m_nextIndex = 0;
102 uint32_t m_curIndex = 0;
110 : m_array(array), m_indices(indices),
133 bool empty() const noexcept {
return m_segments.empty(); }
137 constexpr const std::vector<Segment>&
segments() const noexcept {
return m_segments; }
141 static void cbBeginData( GLenum
type,
void *polygonData ) {
143 os->m_curIndex =
os->m_nextIndex++;
145 os->m_segments.push_back(s);
146 if(
os->m_indices ) {
147 os->m_indices->putu32(
os->m_curIndex);
149 if(
os->verbose() ) {
153 static void cbVertexData(
void *data,
void *polygonData ) {
155 Vertex* v =
reinterpret_cast<Vertex*
>(data);
156 if( os->verbose() ) {
159 os->m_array.put3f(v->
coord());
160 if( os->useNormal() ) {
161 os->m_array.put3f(os->m_normal);
164 static void cbEndData(
void *polygonData ) {
166 Segment& s = os->m_segments.at(os->m_segments.size()-1);
168 if( os->verbose() ) {
169 jau::INFO_PRINT(
"GLUtess end %02d, %s", os->m_curIndex, s.toString().c_str());
172 static void cbErrorData( GLenum errnum,
void *polygonData ) {
174 if( os->verbose() ) {
176 jau::INFO_PRINT(
"GLUtess error %02d, errnum 0x%X", os->m_curIndex, errnum);
179 static void cbCombineData( GLUTessFloat coords[3],
void *data[4],
180 GLfloat weight[4],
void **outData,
181 void *polygonData ) {
183 if( os->verbose() ) {
184 jau::INFO_PRINT(
"GLUtess combine %02d, %f, %f, %f", os->m_curIndex, coords[0], coords[1], coords[2]);
187 std::shared_ptr<Vertex> v = std::make_shared<Vertex>((
float)coords[0], (
float)coords[1], (
float)coords[2],
true);
188 os->m_vcache.push_back(v);
189 for (
int i = 0; i < 4; ++i) {
190 Vertex* s = (Vertex*) data[i];
192 for (
int j = 0;
j < 3; ++
j) {
194 v->texCoord()[
j] += (float)( weight[i] * s->
texCoord()[j] );
197 outData[0] = v.get();
211 size_t outlineCount = 0;
212 if( odirty ||
empty() ) {
214 GLUtesselator*
tess = gluNewTess();
215 if( !
tess ) {
return m_segments; }
216 m_normal = outlines.
normal();
220 gluTessNormal(
tess, m_normal.x, m_normal.y, m_normal.z);
221 gluTessCallback(
tess, GLU_TESS_BEGIN_DATA, (_GLUfuncptr)cbBeginData);
222 gluTessCallback(
tess, GLU_TESS_END_DATA, (_GLUfuncptr)cbEndData);
223 gluTessCallback(
tess, GLU_TESS_VERTEX_DATA, (_GLUfuncptr)cbVertexData);
224 gluTessCallback(
tess, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)cbCombineData);
225 gluTessCallback(
tess, GLU_TESS_ERROR_DATA, (_GLUfuncptr)cbErrorData);
227 gluTessBeginPolygon(
tess,
this);
230 jau::INFO_PRINT(
"GLUtess: outline %zu: Vertices %zu, Winding %s", outlineCount, o.vertexCount(),
to_string(o.getWinding()).c_str());
233 gluTessBeginContour(
tess);
234 if constexpr (
sizeof(GLfloat) ==
sizeof(GLUTessFloat) ) {
235 for(
const Vertex& v : o.vertices()) {
236 gluTessVertex(
tess,
const_cast<GLfloat*
>(v.coord().cbegin()), (
void*)&v);
239 for(
const Vertex& v : o.vertices()) {
240 GLUTessFloat coords[] = { v.coord().x, v.coord().y, v.coord().z };
241 gluTessVertex(
tess, coords, (
void*)&v);
244 gluTessEndContour(
tess);
246 gluTessEndPolygon(
tess);
260 jau::INFO_PRINT(
"GLUtess: indices: %s", m_indices->toString().c_str());
A Generic shape objects which is defined by a list of Outlines.
const OutlineList & outlines() const noexcept
constexpr bool verticesDirty() const noexcept
constexpr const Vec3f & normal() const noexcept
Normal vector, optionally used by tesselator to add (interleaved) normals.
constexpr bool trianglesDirty() const noexcept
Define a single continuous stroke by control vertices.
constexpr const Vec3f & texCoord() const noexcept
constexpr const Vec3f & coord() const noexcept
GLUtilTesselator transform OutlineShapes to triangles using glutess2.
GLUtilTesselator(int flags, GLFloatArrayDataServer &array) noexcept
constexpr bool useIndices() const noexcept
static constexpr int FLAG_TEXTURE
void clear()
Clears all internal data, not passed array or indices.
constexpr bool verbose() const noexcept
std::vector< Segment > SegmentList
bool empty() const noexcept
Returns true if segments() is empty.
static SegmentList tesselate(int flags, GLFloatArrayDataServer &array, OutlineShape &outlines)
jau::nsize_t elementCount() const noexcept
GLUtilTesselator(int flags, GLFloatArrayDataServer &array, GLUIntArrayDataServer *indices) noexcept
constexpr bool useColor() const noexcept
const SegmentList & tesselate(OutlineShape &outlines)
constexpr const std::vector< Segment > & segments() const noexcept
static SegmentList tesselate(int flags, GLFloatArrayDataServer &array, GLUIntArrayDataServer *indices, OutlineShape &outlines)
constexpr bool useTexture() const noexcept
static constexpr int FLAG_NORMAL
static constexpr int FLAG_INDICES
static constexpr int FLAG_COLOR
static constexpr int FLAG_VERBOSE
constexpr bool useNormal() const noexcept
std::string toString() const noexcept
GLArrayDataServer< float > GLFloatArrayDataServer
GLArrayDataServer< uint32_t > GLUIntArrayDataServer
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
std::string to_string(const math_error_t v) noexcept
Returns std::string representation of math_error_t.
constexpr std::string format_string_v(const std::size_t maxStrLen, const std::string_view format, const Args &...args)
Safely returns a string according to printf() formatting rules and variable number of arguments follo...
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2024 Gothel Software e.K.
void INFO_PRINT(const char *format,...) noexcept
Use for unconditional informal messages, prefix '[elapsed_time] Info: '.
GLsizei count
number of elements in data-sink for this segment
static std::string toString(const std::string &pre, const SegmentList &segments) noexcept
GLint first
index of first element in data-sink for this segment
GLenum type
render implementation specific triangle type, i.e. triangle-strip, -fan or just triangles.
std::string toString() const