feat: render open and closed faces/lines

This commit is contained in:
parker
2025-08-04 13:47:08 +01:00
parent c685e4b9bd
commit 05a2284773
11 changed files with 117 additions and 66 deletions

View File

@@ -14,16 +14,19 @@ ga::Attribute::Attribute(std::string name, ga::AttributeType type)
switch(type_) switch(type_)
{ {
case(AttrType::intT): case(AttrType::intT):
intStore_=std::make_shared<std::vector<int>>(); intStore_=std::make_shared<std::vector<bt::intT>>();
break; break;
case(AttrType::floatT): case(AttrType::floatT):
floatStore_=std::make_shared<std::vector<float>>(); floatStore_=std::make_shared<std::vector<bt::floatT>>();
break; break;
case(AttrType::vectorT): case(AttrType::vectorT):
vector3Store_=std::make_shared<std::vector<enzo::bt::Vector3>>(); vector3Store_=std::make_shared<std::vector<enzo::bt::Vector3>>();
break; break;
case(AttrType::boolT):
boolStore_=std::make_shared<std::vector<enzo::bt::boolT>>();
break;
default: default:
throw std::runtime_error("Type " + std::to_string(static_cast<int>(type_)) + " was not properly accounted for"); throw std::runtime_error("Type " + std::to_string(static_cast<int>(type_)) + " was not properly accounted for in Attribute constructor");
} }
@@ -40,16 +43,19 @@ ga::Attribute::Attribute(const Attribute& other)
switch(type_) switch(type_)
{ {
case(AttrType::intT): case(AttrType::intT):
intStore_=std::make_shared<std::vector<int>>(*other.intStore_); intStore_=std::make_shared<std::vector<bt::intT>>(*other.intStore_);
break; break;
case(AttrType::floatT): case(AttrType::floatT):
floatStore_=std::make_shared<std::vector<float>>(*other.floatStore_); floatStore_=std::make_shared<std::vector<bt::floatT>>(*other.floatStore_);
break; break;
case(AttrType::vectorT): case(AttrType::vectorT):
vector3Store_=std::make_shared<std::vector<enzo::bt::Vector3>>(*other.vector3Store_); vector3Store_=std::make_shared<std::vector<enzo::bt::Vector3>>(*other.vector3Store_);
break; break;
case(AttrType::boolT):
boolStore_=std::make_shared<std::vector<enzo::bt::boolT>>(*other.boolStore_);
break;
default: default:
throw std::runtime_error("Type " + std::to_string(static_cast<int>(type_)) + " was not properly accounted for"); throw std::runtime_error("Type " + std::to_string(static_cast<int>(type_)) + " was not properly accounted for in Attribute copy constructor");
} }
} }

View File

@@ -46,9 +46,10 @@ namespace enzo{
// void* data_; // void* data_;
// data stores // data stores
std::shared_ptr<StoreContainer<int>> intStore_; std::shared_ptr<StoreContainer<bt::intT>> intStore_;
std::shared_ptr<StoreContainer<float>> floatStore_; std::shared_ptr<StoreContainer<bt::floatT>> floatStore_;
std::shared_ptr<StoreContainer<enzo::bt::Vector3>> vector3Store_; std::shared_ptr<StoreContainer<enzo::bt::Vector3>> vector3Store_;
std::shared_ptr<StoreContainer<enzo::bt::boolT>> boolStore_;
}; };

View File

@@ -27,13 +27,13 @@ public:
// TODO: add the other types // TODO: add the other types
// int // int
if constexpr (std::is_same<int, T>::value) if constexpr (std::is_same<bt::intT, T>::value)
{ {
data_=attribute->intStore_; data_=attribute->intStore_;
} }
// float // float
else if constexpr (std::is_same<float, T>::value) else if constexpr (std::is_same<bt::floatT, T>::value)
{ {
data_=attribute->floatStore_; data_=attribute->floatStore_;
} }
@@ -43,9 +43,13 @@ public:
{ {
data_=attribute->vector3Store_; data_=attribute->vector3Store_;
} }
else if constexpr (std::is_same<enzo::bt::boolT, T>::value)
{
data_=attribute->boolStore_;
}
else else
{ {
throw std::runtime_error("Type " + std::to_string(static_cast<int>(type_)) + " was not properly accounted for"); throw std::runtime_error("Type " + std::to_string(static_cast<int>(type_)) + " was not properly accounted for in AttributeHandle constructor");
} }
} }
@@ -109,8 +113,9 @@ private:
}; };
using AttributeHandleInt = AttributeHandle<int>; using AttributeHandleInt = AttributeHandle<bt::intT>;
using AttributeHandleFloat = AttributeHandle<float>; using AttributeHandleFloat = AttributeHandle<bt::floatT>;
using AttributeHandleVector3 = AttributeHandle<enzo::bt::Vector3>; using AttributeHandleVector3 = AttributeHandle<enzo::bt::Vector3>;
using AttributeHandleBool = AttributeHandle<enzo::bt::boolT>;
} }

View File

@@ -12,6 +12,7 @@
using namespace enzo; using namespace enzo;
geo::Geometry::Geometry() : geo::Geometry::Geometry() :
vertexCountHandlePrim_{addIntAttribute(ga::AttrOwner::PRIMITIVE, "vertexCount")}, vertexCountHandlePrim_{addIntAttribute(ga::AttrOwner::PRIMITIVE, "vertexCount")},
closedHandlePrim_{addBoolAttribute(ga::AttrOwner::PRIMITIVE, "closed")},
pointOffsetHandleVert_{addIntAttribute(ga::AttrOwner::VERTEX, "point")}, pointOffsetHandleVert_{addIntAttribute(ga::AttrOwner::VERTEX, "point")},
posHandlePoint_{addVector3Attribute(ga::AttrOwner::POINT, "P")} posHandlePoint_{addVector3Attribute(ga::AttrOwner::POINT, "P")}
{ {
@@ -19,27 +20,39 @@ geo::Geometry::Geometry() :
} }
geo::Geometry::Geometry(const Geometry& other): geo::Geometry::Geometry(const Geometry& other):
// attributes
pointAttributes_{deepCopyAttributes(other.pointAttributes_)}, pointAttributes_{deepCopyAttributes(other.pointAttributes_)},
vertexAttributes_{deepCopyAttributes(other.vertexAttributes_)}, vertexAttributes_{deepCopyAttributes(other.vertexAttributes_)},
primitiveAttributes_{deepCopyAttributes(other.primitiveAttributes_)}, primitiveAttributes_{deepCopyAttributes(other.primitiveAttributes_)},
globalAttributes_{deepCopyAttributes(other.globalAttributes_)}, globalAttributes_{deepCopyAttributes(other.globalAttributes_)},
// handles
vertexCountHandlePrim_{enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount"))}, vertexCountHandlePrim_{enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount"))},
closedHandlePrim_{enzo::ga::AttributeHandleBool(getAttribByName(ga::AttrOwner::PRIMITIVE, "closed"))},
pointOffsetHandleVert_{enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::VERTEX, "point"))}, pointOffsetHandleVert_{enzo::ga::AttributeHandleInt(getAttribByName(ga::AttrOwner::VERTEX, "point"))},
posHandlePoint_{enzo::ga::AttributeHandleVector3(getAttribByName(ga::AttrOwner::POINT, "P"))} posHandlePoint_{enzo::ga::AttributeHandleVector3(getAttribByName(ga::AttrOwner::POINT, "P"))}
{ {
} }
void geo::Geometry::addFace(std::initializer_list<ga::Offset> pointOffsets) void geo::Geometry::addFace(std::vector<ga::Offset> pointOffsets, bool closed)
{ {
for(ga::Offset pointOffset : pointOffsets) for(ga::Offset pointOffset : pointOffsets)
{ {
pointOffsetHandleVert_.addValue(pointOffset); pointOffsetHandleVert_.addValue(pointOffset);
} }
vertexCountHandlePrim_.addValue(pointOffsets.size()); vertexCountHandlePrim_.addValue(pointOffsets.size());
closedHandlePrim_.addValue(closed);
} }
void geo::Geometry::addPoint(const bt::Vector3& pos)
{
posHandlePoint_.addValue(pos);
}
bt::Vector3 geo::Geometry::getPosFromVert(ga::Offset vertexOffset) const bt::Vector3 geo::Geometry::getPosFromVert(ga::Offset vertexOffset) const
{ {
// get point offset // get point offset
@@ -53,6 +66,12 @@ bt::Vector3 geo::Geometry::getPointPos(ga::Offset pointOffset) const
return posHandlePoint_.getValue(pointOffset); return posHandlePoint_.getValue(pointOffset);
} }
void geo::Geometry::setPointPos(const ga::Offset offset, const bt::Vector3& pos)
{
posHandlePoint_.setValue(offset, pos);
}
unsigned int geo::Geometry::getPrimVertCount(ga::Offset primOffset) const unsigned int geo::Geometry::getPrimVertCount(ga::Offset primOffset) const
{ {
return vertexCountHandlePrim_.getValue(primOffset); return vertexCountHandlePrim_.getValue(primOffset);
@@ -68,6 +87,11 @@ ga::Offset geo::Geometry::getNumVerts() const
return pointOffsetHandleVert_.getSize(); return pointOffsetHandleVert_.getSize();
} }
ga::Offset geo::Geometry::getNumPoints() const
{
return posHandlePoint_.getSize();
}
@@ -191,13 +215,26 @@ void geo::Geometry::computePrimStartVertices()
ga::AttributeHandle<int> geo::Geometry::addIntAttribute(ga::AttributeOwner owner, std::string name) ga::AttributeHandleInt geo::Geometry::addIntAttribute(ga::AttributeOwner owner, std::string name)
{ {
auto newAttribute = std::make_shared<ga::Attribute>(name, ga::AttrType::intT); auto newAttribute = std::make_shared<ga::Attribute>(name, ga::AttrType::intT);
getAttributeStore(owner).push_back(newAttribute); getAttributeStore(owner).push_back(newAttribute);
return ga::AttributeHandle<int>(newAttribute); return ga::AttributeHandleInt(newAttribute);
} }
ga::AttributeHandleBool geo::Geometry::addBoolAttribute(ga::AttributeOwner owner, std::string name)
{
auto newAttribute = std::make_shared<ga::Attribute>(name, ga::AttrType::boolT);
getAttributeStore(owner).push_back(newAttribute);
return ga::AttributeHandleBool(newAttribute);
}
bt::boolT geo::Geometry::isClosed(ga::Offset primOffset) const
{
return closedHandlePrim_.getValue(primOffset);
}
ga::AttributeHandle<bt::Vector3> geo::Geometry::addVector3Attribute(ga::AttributeOwner owner, std::string name) ga::AttributeHandle<bt::Vector3> geo::Geometry::addVector3Attribute(ga::AttributeOwner owner, std::string name)
{ {
auto newAttribute = std::make_shared<ga::Attribute>(name, ga::AttrType::vectorT); auto newAttribute = std::make_shared<ga::Attribute>(name, ga::AttrType::vectorT);

View File

@@ -24,21 +24,28 @@ class Geometry
public: public:
Geometry(); Geometry();
Geometry(const Geometry& other); Geometry(const Geometry& other);
ga::AttributeHandle<int> addIntAttribute(ga::AttributeOwner owner, std::string name); ga::AttributeHandle<bt::intT> addIntAttribute(ga::AttributeOwner owner, std::string name);
ga::AttributeHandleBool addBoolAttribute(ga::AttributeOwner owner, std::string name);
ga::AttributeHandle<bt::Vector3> addVector3Attribute(ga::AttributeOwner owner, std::string name); ga::AttributeHandle<bt::Vector3> addVector3Attribute(ga::AttributeOwner owner, std::string name);
// TODO: return weak ptr // TODO: return weak ptr
std::shared_ptr<ga::Attribute> getAttribByName(ga::AttributeOwner owner, std::string name); std::shared_ptr<ga::Attribute> getAttribByName(ga::AttributeOwner owner, std::string name);
std::vector<bt::Vector3> derivePointNormals(); std::vector<bt::Vector3> derivePointNormals();
HeMesh computeHalfEdgeMesh(); HeMesh computeHalfEdgeMesh();
// returns the first vertex of the primitive void addFace(std::vector<ga::Offset> pointOffsets, bool closed=true);
void addFace(std::initializer_list<ga::Offset> pointOffsets); void addPoint(const bt::Vector3& pos);
ga::Offset getPrimStartVertex(ga::Offset primOffset) const; void setPointPos(const ga::Offset offset, const bt::Vector3& pos);
ga::Offset getPrimStartVertex(ga::Offset primOffset) const; // returns the first vertex of the primitive
bt::Vector3 getPosFromVert(ga::Offset vertexOffset) const; bt::Vector3 getPosFromVert(ga::Offset vertexOffset) const;
bt::Vector3 getPointPos(ga::Offset pointOffset) const; bt::Vector3 getPointPos(ga::Offset pointOffset) const;
unsigned int getPrimVertCount(ga::Offset primOffset) const; unsigned int getPrimVertCount(ga::Offset primOffset) const;
ga::Offset getNumPrims() const; ga::Offset getNumPrims() const;
ga::Offset getNumVerts() const; ga::Offset getNumVerts() const;
ga::Offset getNumPoints() const;
bt::boolT isClosed(ga::Offset primOffset) const;
void computePrimStartVertices(); void computePrimStartVertices();
private: private:
using attribVector = std::vector<std::shared_ptr<ga::Attribute>>; using attribVector = std::vector<std::shared_ptr<ga::Attribute>>;
@@ -55,6 +62,7 @@ private:
// handles // handles
enzo::ga::AttributeHandleInt vertexCountHandlePrim_; enzo::ga::AttributeHandleInt vertexCountHandlePrim_;
enzo::ga::AttributeHandleBool closedHandlePrim_;
enzo::ga::AttributeHandleInt pointOffsetHandleVert_; enzo::ga::AttributeHandleInt pointOffsetHandleVert_;
enzo::ga::AttributeHandleVector3 posHandlePoint_; enzo::ga::AttributeHandleVector3 posHandlePoint_;
}; };

View File

@@ -19,6 +19,7 @@ namespace enzo
floatT, floatT,
listT, listT,
vectorT, vectorT,
boolT,
}; };
using AttrType = AttributeType; using AttrType = AttributeType;
using AttrOwner = AttributeOwner; using AttrOwner = AttributeOwner;
@@ -29,6 +30,7 @@ namespace enzo
{ {
using floatT = double; using floatT = double;
using intT = int64_t; using intT = int64_t;
using boolT = bool;
using Vector3 = Eigen::Vector3d; using Vector3 = Eigen::Vector3d;
using Vector4 = Eigen::Vector4d; using Vector4 = Eigen::Vector4d;
using String = std::string; using String = std::string;

View File

@@ -117,21 +117,29 @@ void GLMesh::setPosBuffer(enzo::geo::Geometry& geometry)
unbind(); unbind();
} }
void GLMesh::setIndexBuffer(std::vector<int> pointIndices, std::vector<int> primVertexCounts) void GLMesh::setIndexBuffer(enzo::geo::Geometry& geometry)
{ {
bind(); bind();
faceIndexData.clear(); faceIndexData.clear();
lineIndexData.clear(); lineIndexData.clear();
unsigned int startVert = 0;
// create triangle fan from potentially ngon inputs // create triangle fan from potentially ngon inputs
for(size_t primNum=0; primNum<primVertexCounts.size(); ++primNum) for(enzo::ga::Offset primOffset=0; primOffset<geometry.getNumPrims(); ++primOffset)
{ {
int primVertexCount = primVertexCounts[primNum]; int primVertexCount = geometry.getPrimVertCount(primOffset);
const enzo::ga::Offset startVert = geometry.getPrimStartVertex(primOffset);
const enzo::bt::boolT closed = geometry.isClosed(primOffset);
if(!closed && primVertexCount>=2)
if(primVertexCount>=3) {
for(size_t i=0; i<primVertexCount-1; ++i)
{
lineIndexData.push_back(startVert+i);
lineIndexData.push_back(startVert+i+1);
}
}
else if(primVertexCount>=3)
{ {
for(size_t i=1; i<primVertexCount-1; ++i) for(size_t i=1; i<primVertexCount-1; ++i)
{ {
@@ -141,14 +149,7 @@ void GLMesh::setIndexBuffer(std::vector<int> pointIndices, std::vector<int> prim
} }
} }
if(primVertexCount==2)
{
IC(startVert, startVert+1);
lineIndexData.push_back(startVert);
lineIndexData.push_back(startVert+1);
}
startVert += primVertexCount;
} }
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, faceIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, faceIndexBuffer);

View File

@@ -29,7 +29,7 @@ public:
void init(); void init();
void initBuffers(); void initBuffers();
void setPosBuffer(enzo::geo::Geometry& geometry); void setPosBuffer(enzo::geo::Geometry& geometry);
void setIndexBuffer(std::vector<int> pointIndices, std::vector<int> primVertexCounts); void setIndexBuffer(enzo::geo::Geometry& geometry);
void bind(); void bind();
void unbind(); void unbind();
void draw(); void draw();

View File

@@ -184,14 +184,7 @@ std::unique_ptr<GLMesh> ViewportGLWidget::meshFromGeo(enzo::geo::Geometry& geome
mesh->setPosBuffer(geometry); mesh->setPosBuffer(geometry);
mesh->setIndexBuffer(geometry);
std::shared_ptr<ga::Attribute> pointAttr = geometry.getAttribByName(ga::AttrOwner::VERTEX, "point");
ga::AttributeHandleInt pointAttrHandle = ga::AttributeHandleInt(pointAttr);
std::shared_ptr<ga::Attribute> vertexCountAttr = geometry.getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount");
ga::AttributeHandleInt vertexCountHandle = ga::AttributeHandleInt(vertexCountAttr);
mesh->setIndexBuffer(pointAttrHandle.getAllValues(), vertexCountHandle.getAllValues());
@@ -205,12 +198,5 @@ void ViewportGLWidget::geometryChanged(enzo::geo::Geometry& geometry)
ga::AttributeHandleVector3 PAttrHandle = ga::AttributeHandleVector3(PAttr); ga::AttributeHandleVector3 PAttrHandle = ga::AttributeHandleVector3(PAttr);
triangleMesh_->setPosBuffer(geometry); triangleMesh_->setPosBuffer(geometry);
triangleMesh_->setIndexBuffer(geometry);
std::shared_ptr<ga::Attribute> pointAttr = geometry.getAttribByName(ga::AttrOwner::VERTEX, "point");
ga::AttributeHandleInt pointAttrHandle = ga::AttributeHandleInt(pointAttr);
std::shared_ptr<ga::Attribute> vertexCountAttr = geometry.getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount");
ga::AttributeHandleInt vertexCountHandle = ga::AttributeHandleInt(vertexCountAttr);
triangleMesh_->setIndexBuffer(pointAttrHandle.getAllValues(), vertexCountHandle.getAllValues());
} }

View File

@@ -40,14 +40,14 @@ void GopGeometryImport::cookOp(enzo::op::Context context)
} }
auto PAttr = geo.getAttribByName(ga::AttrOwner::POINT, "P"); // auto PAttr = geo.getAttribByName(ga::AttrOwner::POINT, "P");
ga::AttributeHandleVector3 PAttrHandle(PAttr); // ga::AttributeHandleVector3 PAttrHandle(PAttr);
auto pointAttr = geo.getAttribByName(ga::AttrOwner::VERTEX, "point"); // auto pointAttr = geo.getAttribByName(ga::AttrOwner::VERTEX, "point");
ga::AttributeHandleInt pointAttrHandle(pointAttr); // ga::AttributeHandleInt pointAttrHandle(pointAttr);
auto vertexCountAttr = geo.getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount"); // auto vertexCountAttr = geo.getAttribByName(ga::AttrOwner::PRIMITIVE, "vertexCount");
ga::AttributeHandleInt vertexCountHandle(vertexCountAttr); // ga::AttributeHandleInt vertexCountHandle(vertexCountAttr);
std::ifstream file(filePath); std::ifstream file(filePath);
if(!file.is_open()) if(!file.is_open())
@@ -76,10 +76,12 @@ void GopGeometryImport::cookOp(enzo::op::Context context)
} }
const bt::Vector3 pointPos = {std::stod(result[1]), std::stod(result[2]), std::stod(result[3])}; const bt::Vector3 pointPos = {std::stod(result[1]), std::stod(result[2]), std::stod(result[3])};
PAttrHandle.addValue(pointPos); geo.addPoint(pointPos);
} }
else if(firstChar=='f' || firstChar=='l') else if(firstChar=='f' || firstChar=='l')
{ {
bool closedFace = firstChar=='f';
std::vector<std::string> result; std::vector<std::string> result;
boost::split(result, line, isspace); boost::split(result, line, isspace);
if(result.size()<3) if(result.size()<3)
@@ -88,16 +90,18 @@ void GopGeometryImport::cookOp(enzo::op::Context context)
} }
ga::Offset numVerts = result.size()-1;
std::vector<ga::Offset> verts;
verts.reserve(numVerts);
// set vertex attributes // set vertex attributes
for(int i=1; i<result.size(); ++i) for(int i=1; i<numVerts+1; ++i)
{ {
const int primNum = std::stoi(result[i]); verts.push_back(std::stoi(result[i])-1);
pointAttrHandle.addValue(primNum-1);
} }
// set face attribute geo.addFace(verts, closedFace);
vertexCountHandle.addValue(result.size()-1);
} }
} }
@@ -106,11 +110,12 @@ void GopGeometryImport::cookOp(enzo::op::Context context)
// scale // scale
const float scale = context.evalFloatParm("size"); const float scale = context.evalFloatParm("size");
for(int i=0; i<PAttrHandle.getSize(); ++i) const ga::Offset numPoints = geo.getNumPoints();
for(ga::Offset i=0; i<numPoints; ++i)
{ {
enzo::bt::Vector3 pointPos = PAttrHandle.getValue(i); enzo::bt::Vector3 pointPos = geo.getPointPos(i);
pointPos*=scale; pointPos*=scale;
PAttrHandle.setValue(i, pointPos); geo.setPointPos(i, pointPos);
} }
// ---- // ----

View File

@@ -24,7 +24,7 @@ TEST_CASE("geometry")
using namespace enzo; using namespace enzo;
geo::Geometry geo; geo::Geometry geo;
// check add function // check add function
ga::AttributeHandle<int> myHandle = geo.addIntAttribute(ga::AttrOwner::POINT, "index"); ga::AttributeHandleInt myHandle = geo.addIntAttribute(ga::AttrOwner::POINT, "index");
myHandle.addValue(5); myHandle.addValue(5);
myHandle.addValue(6); myHandle.addValue(6);
REQUIRE(myHandle.getValue(0)==5); REQUIRE(myHandle.getValue(0)==5);