Drawing large amounts of billboarded triangles in the viewport
-
@r_gigante Hey thanks for the great suggestions.
Not sure why I didn't think of adding a camera check... Now in combination with the BaseDraw::DrawPolygonObject() the performance is quite ok.
If I could bother you guys for 1 more question : ), would really appreciate it. It is regarding per vertex colors. I followed the guide here - https://developers.maxon.net/docs/cpp/2023_2/page_manual_vertexcolortag.html
Created the VertexColorTag , inserted in the PolygonObject, got the write address and filled it up, but i'm crashing at VertexColorTag::Get() during the write process.
Is there anything specific when using the per vertex color tag in a PolygonObject that is drawn with BaseDraw::DrawPolygonObject(). Basically should that guide work out of the box?Regards,
Georgi. -
Hi @mastergog the manual just illustrates the standard case and, as much as for any other snippet, it might be adapted to your scope to deliver the desired function.
Give the limited information, I can only assume that the
VertexColorHandle
passed as first parameter toVertexColorTag::Get()
might be invalid. Have you checked ifvcTag->GetDataAddressW();
returns a valid pointer? Can you share a code to reproduce the issue? What's the instance scope in the code of thePolygonObject
you've inserted to Tag into?Cheers, r
-
@maxon Hey sorry for the weird phrasing, had some other tasks and I was just wondering if there is some known issue with this functionality before i got back to it.
Anyway about the code. As suggested, created a zero polygon PolygonObject* with my base vertices in GetVirtualObjects() and inserted it under the cache root.
In Draw() I find that PolygonObject and use its point data to allocate a PolygonObject with actual polygons that is drawn with DrawPolygonObject(). This just created PolygonObject pointer is kept as a member in my class.So the vertex color tag code is the following. And the VertexColorHandle seems to be valid. Tried this code in both my Draw() and GetVirtualObjects() implementation to the same effect.
BaseTag* tag = polygonObjectToDraw->GetTag(Tvertexcolor); if (tag == nullptr) { tag = VertexColorTag::Alloc(polygonObjectToDraw->GetPointCount()); VertexColorTag* vcTag = static_cast<VertexColorTag*>(tag); vcTag->SetPerPointMode(false); } VertexColorTag* vcTag = static_cast<VertexColorTag*>(tag); VertexColorHandle handle = vcTag->GetDataAddressW(); for (Int32 i = 0; i < Int32(polygonObjectToDraw->GetPointCount()); i++) { VertexColorStruct vcs; VertexColorTag::Get(handle, i, vcs); for (int p = 0; p < 4; p ++) { vcs[p] = maxon::ColorA32(1.0f, 1.0f, 0.0f, 1.0f); } VertexColorTag::Set(handle, i, vcs); } polygonObjectToDraw->InsertTag(tag); baseDraw->DrawPolygonObject(baseDrawHelp, polygonObjectToDraw, DRAWOBJECT::NONE);
-
@maxon Hey so the crashing was because I was looping out of bounds it seems. Corrected my code like so:
BaseTag* tag = polygonObjectToDraw->GetTag(Tvertexcolor); if (tag == nullptr) { tag = VertexColorTag::Alloc(polygonObjectToDraw->GetPolygonCount() * 4); VertexColorTag* vcTag = static_cast<VertexColorTag*>(tag); vcTag->SetPerPointMode(true); } VertexColorTag* vcTag = static_cast<VertexColorTag*>(tag); VertexColorHandle handle = vcTag->GetDataAddressW(); for (Int32 i = 0; i < Int32(polygonObjectToDraw->GetPolygonCount()); i++) { VertexColorStruct vcs; VertexColorTag::Get(handle, i, vcs); for (int p = 0; p < 4; p++) { vcs[p] = maxon::ColorA32(1.0f, 1.0f, 0.0f, 1.0f); } VertexColorTag::Set(handle, i, vcs); } polygonObjectToDraw->InsertTag(tag); baseDraw->DrawPolygonObject(baseDrawHelp, polygonObjectToDraw, DRAWOBJECT::NONE);
Still this doesn't use the color i've specified, but rather the default grey.
-
@maxon Hey guys, one more update.
Edited my code so that I allocate the full PolygonObject in GetVirtualObjects(), place it under the cache, and just modify it in Draw(), without using DrawPolygonObject()
Managed to get the per vertex colors to show when I select my object, click "c" so i can get the edit mode and see the cache. Then I select the PolygonObject in the cache with the per vertex color tag and double click the tag as if I'm editing the colors. That's when my colors show up.Any ideas how to get them without going into edit mode and double clicking the tag?
Regards,
Georgi. -
Hey guys, it was suggested to me that the vertex color tag is designed to pass data to the renderer not the viewport. And the reason my colors were showing up using the paint tool was because it overrides the viewport. Is that correct?
Also one of your tutorials showed how to create a Material with a vertex map using a vertex color tag, so I tried that. And applied the Material to my object and the colors showed up. So perhaps this is the "correct" way to use the vertex color tag for representation in the viewport? Achieved this through the UI but I assume there's a way to do it programmatically. correct?
Thanks for taking the time!
-Georgi.
-
Ok resolved this by making the following connection TextureTag->Material->Shader->VertexColorTag and inserting the TextureTag in my object.
Going to close this. Thanks for the support.
-
Hi @mastergog,
we are sorry that it took us so long. We actually were aware of your problem, and had it in the workings, but were a bit busy with all the
and Cinema supporting it from the get go. Thank your for sharing your solution and thank you for your understanding.Cheers
Ferdinand -
@zipit Oh no worries you provided great support to get me started. As someone had suggested will also write you guys a more detailed email about the next representations I plan on implementing.
Regards,
Georgi. -
As already told by @zipit, I'm terribly sorry for coming so late here.
I've prepared a full example showing how to fill aVertexColorTag
in theObjectData::GetVirtualObjects()
and use this values to color the triangles shown up in the ObjectData::Draw() method. My code actually uses theVertexColorTag::SetColor()/GetColor()
.
The
VertexColorTag
in this case is not specify to each vertex of the triangle but specifies the color for the whole triangle: this is because the tag is created in theObjectData::GetVirtualObjects()
and store color for each point of the cloud, but then it's used in theObjectData::Draw()
method to specify theObjectColorProperty
used to color the drawn PolygonObject. As far as I know theBaseDraw::DrawPolygonObject()
ignores any VertexColorTag assigned to the PolygonObject to be drawn.BaseObject* PC_12974::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh) { // check cache before continue BaseObject* cache = op->GetCache(); if (cache) return cache; // init the random gen and get a arbitrary number of tris _rndGen.Init(GeGetTimer()); _randomTrisCnt = (SAFEINT32(_rndGen.Get01() * (1 + _max - _min)) + _min); // allocate a PolygonObject and fill it with points randomly PolygonObject* po = PolygonObject::Alloc(_randomTrisCnt, 0); if (!po) return BaseObject::Alloc(Onull); // fill the points array with random positions Vector* points = po->GetPointW(); for (Int32 i = 0; i < _randomTrisCnt; i++) points[i] = Vector (100.0 * _rndGen.Get11(), 100.0 * _rndGen.Get11(), 100.0 * _rndGen.Get11()); // look for VertexColor tag BaseTag* tag = po->GetTag(Tvertexcolor); // if not existing just create a new one VertexColorTag* vcTag = nullptr; if (!tag) { tag = VertexColorTag::Alloc(_randomTrisCnt); po->InsertTag(tag); } vcTag = static_cast<VertexColorTag*>(tag); vcTag->SetPerPointMode(true); VertexColorHandle handle = vcTag->GetDataAddressW(); // fill the vertexcolor tag with random values for (Int32 i = 0; handle && i < _randomTrisCnt; i++) VertexColorTag::SetColor(handle, nullptr, nullptr, i, maxon::Color32(_rndGen.Get01(), _rndGen.Get01(), _rndGen.Get01())); // update host object po->Message(MSG_UPDATE); return po; } Bool PC_12974::TriangleOnPoint(const Vector &pos, PolygonObject& po) { // given a point create a triangle centered over there. Vector* points = po.GetPointW(); const Matrix poMG = po.GetMg(); const Vector posMG = poMG * pos; if (!points) return false; // set vertexes positions for the triangle. points[0] = Vector(0, 0, _triangleRad) + posMG; points[1] = Vector(_triangleRad * Cos(-PI / 6), 0, _triangleRad * Sin(-PI / 6)) + posMG; points[2] = Vector(_triangleRad * Cos(-PI * 5 / 6), 0, _triangleRad * Sin(-PI * 5 / 6)) + posMG; // create the polygon CPolygon* polys = po.GetPolygonW(); if (!polys) return false; polys[0] = CPolygon(0, 1, 2); return true; } DRAWRESULT PC_12974::Draw (BaseObject *op, DRAWPASS drawpass, BaseDraw *bd, BaseDrawHelp *bh) { // skip anything but OBJECT drawpass if (drawpass != DRAWPASS::OBJECT) return DRAWRESULT::SKIP; // check for the object and its cache if (op && op->GetCache()) { // get the PolygonObject from the cache PolygonObject* opPO = static_cast<PolygonObject*>(op->GetCache()); // look for the attached VertexColor Tag BaseTag* const tag = opPO->GetTag(Tvertexcolor); if (!tag) return DRAWRESULT::SKIP; VertexColorTag* const vcTag = static_cast<VertexColorTag*>(tag); // retrieve the read-only handle ConstVertexColorHandle vcTagHandleR = vcTag->GetDataAddressR(); // get the points and iterate over the VertexColor to set the color // of each triangle drawn maxon::Int pointCnt = opPO->GetPointCount(); Vector const *points = opPO->GetPointR(); for (maxon::Int i = 0; i < pointCnt; i++) { maxon::Color32 vtxCol(0.0); // get the color if (vcTagHandleR && vcTag->IsPerPointColor()) vtxCol = VertexColorTag::GetColor(vcTagHandleR, nullptr, nullptr, (Int32)i); // set the color in the ObjectColorProperties ObjectColorProperties colProp; colProp.usecolor = ID_BASEOBJECT_USECOLOR_ALWAYS; colProp.color.x = vtxCol.r; colProp.color.y = vtxCol.g; colProp.color.z = vtxCol.b; colProp.xray = false; // allocate the temp triangle PolygonObject* tri = PolygonObject::Alloc(3, 1); // set the color prop, create the tri and draw! tri->SetColorProperties(&colProp); if (TriangleOnPoint(op->GetMg() * points[i], *tri)) bd->DrawPolygonObject(bh, tri, DRAWOBJECT::NONE, nullptr); // free the tri PolygonObject::Free(tri); } } return DRAWRESULT::OK; }
Feel free to comment and again sorry for the silence.
Riccardo