Yea, but I have a handle on that part. Can ve done via read callback in the
registry, or saved as well, I saw there is serialization support.

I wrote a simple visitor that should convert a loaded model into meshlets.
I had it working nicely until I started to experiment with threaded access.

Attached is the source. Not elegant at all but I would be happy if you can
have a look and maybe spot the problem

Thanks a bunch!

On Wed, Jun 1, 2022, 09:25 Werner Modenbach <
[email protected]> wrote:

> Hi Nick,
> good to hear you are getting closer.
> Due to the fact that standard classes of paged data handle vertex arrays
> etc. autonomously and mesh shaders work different I think you have to look
> up where this handling is done and write your own derived class.
> Werner
>
>
> On 31. Mai 2022 21:28:08 MESZ, Trajce Nikolov NICK <
> [email protected]> wrote:
>>
>> Hi again Werner,
>>
>> I think I got it after reading few articles, actually the main one from
>> NVIDIA. Do you have experience in using this with paged data?
>>
>> On Sat, May 28, 2022 at 8:35 PM Trajce Nikolov NICK <
>> [email protected]> wrote:
>>
>>> Hi Werner!
>>>
>>> Thanks soo much for the shared code and the hints!!! I have a better
>>> understanding now how all works together wrt. buffers. Just this snippet,
>>> if you are willing to provide more hints.
>>>
>>> int startVertex = 1;
>>>
>>>     int anzahl = _anzahlVertices;
>>>
>>>     for (auto i=0; i<workgroupsInGeometry; ++i) {
>>>
>>>         (*MeshletInfosArray)[i][0] = startVertex;
>>>
>>>         (*MeshletInfosArray)[i][1] = min(TS_WORKGROUP_SIZE, anzahl);
>>>
>>>         startVertex += TS_WORKGROUP_STEP;
>>>
>>>         anzahl -=TS_WORKGROUP_STEP;
>>>
>>>     }
>>>
>>>
>>> The ideal is to have a working code, a bit more robust then the one I found 
>>> in the repo in the meshshaders branches. But I am getting there slowly :-)
>>>
>>>
>>> This is indeed a big thing!
>>>
>>>
>>> Big thanks!
>>>
>>> Nick
>>>
>>>
>>>
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
>>>  Virus-free.
>>> www.avast.com
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
>>> <#m_-7378692753233440497_m_-4127028168198206277_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
>>>
>>> On Sat, May 28, 2022 at 3:09 PM Trajce Nikolov NICK <
>>> [email protected]> wrote:
>>>
>>>> Okay. Thanks a buch for these  hints! I am starting next week with
>>>> this. Will post findings
>>>>
>>>> On Sat, May 28, 2022, 14:44 Werner Modenbach <
>>>> [email protected]> wrote:
>>>>
>>>>> Yes, that is the only (?) way.
>>>>>
>>>>>
>>>>> On 28. Mai 2022 12:23:48 MESZ, Trajce Nikolov NICK <
>>>>> [email protected]> wrote:
>>>>>>
>>>>>> Hi!
>>>>>>
>>>>>> I haven't looked at the code yet, just want to clarify one thing: you
>>>>>> are providing the meshlets verts uvs normals through 1d texture?
>>>>>>
>>>>>> On Wed, May 25, 2022, 12:17 Trajce Nikolov NICK <
>>>>>> [email protected]> wrote:
>>>>>>
>>>>>>> Hi!
>>>>>>>
>>>>>>> Thanks a bunch! Is your code in the repo so I can have a look?
>>>>>>>
>>>>>>> On Wed, May 25, 2022, 09:17 Werner Modenbach <
>>>>>>> [email protected]> wrote:
>>>>>>>
>>>>>>>> Hi Nick,
>>>>>>>> There is nothing special in the contents of the buffers. They are
>>>>>>>> just arrays like vertex array. Special is the definition as buffer 
>>>>>>>> objects
>>>>>>>> and "overlaying" them with a texture like shown in my code. In the 
>>>>>>>> shader
>>>>>>>> you have the instance ID and from that you access the meshlet info via 
>>>>>>>> the
>>>>>>>> 1D texture. Get your operation parameters from there and fetch 
>>>>>>>> vertices,
>>>>>>>> normals, colors etc. also via the textures.
>>>>>>>> The only difficulty is the size limit of the textures. So you
>>>>>>>> eventually have to split the arrays.
>>>>>>>> That's it.
>>>>>>>> Werner
>>>>>>>>
>>>>>>>>
>>>>>>>> On 24. Mai 2022 22:59:52 MESZ, Trajce Nikolov NICK <
>>>>>>>> [email protected]> wrote:
>>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> I am also researching this subject. Have you succeeded? Any hints
>>>>>>>>> about the meshelts buffer objects? Any other hints?
>>>>>>>>>
>>>>>>>>> Thank you a bunch for any shared info!
>>>>>>>>>
>>>>>>>>> Nick
>>>>>>>>>
>>>>>>>>> On Wed, May 11, 2022 at 5:35 PM DC <[email protected]>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> Thanks Werner!
>>>>>>>>>> This will certainly help me get started.
>>>>>>>>>>
>>>>>>>>>> Much appreciated,
>>>>>>>>>> DC
>>>>>>>>>>
>>>>>>>>>> On Wednesday, May 11, 2022 at 4:13:08 AM UTC-5 Werner Modenbach
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>> Hi DC,
>>>>>>>>>>>
>>>>>>>>>>> here is the link:
>>>>>>>>>>> https://github.com/nvpro-samples/gl_vk_meshlet_cadscene
>>>>>>>>>>> This should help you with items 1) and 2)
>>>>>>>>>>>
>>>>>>>>>>> For item 3) see my code below.
>>>>>>>>>>> The way I assign the data structures in OSG is like that:
>>>>>>>>>>>
>>>>>>>>>>>     // ----------------------
>>>>>>>>>>>     // Create Meshlet primitive    // ----------------------
>>>>>>>>>>>     
>>>>>>>>>>> _geode->getOrCreateStateSet()->getOrCreateUniform(TASK_INVOCATIONS_PER_MESHLET,
>>>>>>>>>>>  osg::Uniform::INT)->set(taskInvocationsPerMeshlet);
>>>>>>>>>>>
>>>>>>>>>>>     osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
>>>>>>>>>>>
>>>>>>>>>>>     osg::ref_ptr<osg::ProxyPrimitive> proxyPrimitive = new 
>>>>>>>>>>> osg::ProxyPrimitive;
>>>>>>>>>>>
>>>>>>>>>>>     proxyPrimitive->drawMeshTasks = new osg::DrawMeshTasks(0, 
>>>>>>>>>>> workgroupsInGeometry * taskInvocationsPerMeshlet);
>>>>>>>>>>>
>>>>>>>>>>>     geometry->setUseDisplayList(false);
>>>>>>>>>>>
>>>>>>>>>>>     geometry->addPrimitiveSet(proxyPrimitive.get());
>>>>>>>>>>>
>>>>>>>>>>>     _geode->addChild(geometry);
>>>>>>>>>>>
>>>>>>>>>>>     // ----------------------
>>>>>>>>>>>     // Vertices
>>>>>>>>>>>
>>>>>>>>>>>     // ----------------------
>>>>>>>>>>>
>>>>>>>>>>>     osg::ref_ptr<osg::Vec4Array> osgVertices = new 
>>>>>>>>>>> osg::Vec4Array(toCopy);
>>>>>>>>>>>
>>>>>>>>>>>     for (auto i=0; i<toCopy; ++i) {    // fill array        // Fill 
>>>>>>>>>>> buffer
>>>>>>>>>>>     }
>>>>>>>>>>>
>>>>>>>>>>>     // Create Buffer and Texture
>>>>>>>>>>>
>>>>>>>>>>>     osg::ref_ptr<osg::VertexBufferObject> verticesBufferObject = 
>>>>>>>>>>> new osg::VertexBufferObject();
>>>>>>>>>>>
>>>>>>>>>>>     verticesBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
>>>>>>>>>>>
>>>>>>>>>>>     osgVertices->setBufferObject(verticesBufferObject.get());
>>>>>>>>>>>
>>>>>>>>>>>     osg::ref_ptr<osg::TextureBuffer> vertexTexture = new 
>>>>>>>>>>> osg::TextureBuffer(osgVertices.get());
>>>>>>>>>>>
>>>>>>>>>>>     vertexTexture->setInternalFormat(GL_RGBA32F_ARB);
>>>>>>>>>>>
>>>>>>>>>>>     
>>>>>>>>>>> vertexTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
>>>>>>>>>>>
>>>>>>>>>>>     
>>>>>>>>>>> stateSet->setTextureAttributeAndModes(MESH_VERTEX_ARRAY_TEXTURE_UNIT,
>>>>>>>>>>>  vertexTexture.get());
>>>>>>>>>>>
>>>>>>>>>>>     // ----------------------
>>>>>>>>>>>     // MeshletInfos
>>>>>>>>>>>
>>>>>>>>>>>     // ----------------------
>>>>>>>>>>>
>>>>>>>>>>>     osg::ref_ptr<Vec4uiArray> MeshletInfosArray = new 
>>>>>>>>>>> Vec4uiArray(workgroupsInGeometry);
>>>>>>>>>>>
>>>>>>>>>>>     int startVertex = 1;
>>>>>>>>>>>
>>>>>>>>>>>     int anzahl = _anzahlVertices;
>>>>>>>>>>>
>>>>>>>>>>>     for (auto i=0; i<workgroupsInGeometry; ++i) {
>>>>>>>>>>>
>>>>>>>>>>>         (*MeshletInfosArray)[i][0] = startVertex;
>>>>>>>>>>>
>>>>>>>>>>>         (*MeshletInfosArray)[i][1] = min(TS_WORKGROUP_SIZE, anzahl);
>>>>>>>>>>>
>>>>>>>>>>>         startVertex += TS_WORKGROUP_STEP;
>>>>>>>>>>>
>>>>>>>>>>>         anzahl -= TS_WORKGROUP_STEP;
>>>>>>>>>>>
>>>>>>>>>>>     }
>>>>>>>>>>>
>>>>>>>>>>>     // Create Buffer and Texture
>>>>>>>>>>>
>>>>>>>>>>>     osg::ref_ptr<osg::VertexBufferObject> meshInfosBufferObject = 
>>>>>>>>>>> new osg::VertexBufferObject();
>>>>>>>>>>>
>>>>>>>>>>>     meshInfosBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
>>>>>>>>>>>
>>>>>>>>>>>     MeshletInfosArray->setBufferObject(meshInfosBufferObject.get());
>>>>>>>>>>>
>>>>>>>>>>>     osg::ref_ptr<osg::TextureBuffer> meshInfosTexture = new 
>>>>>>>>>>> osg::TextureBuffer(MeshletInfosArray.get());
>>>>>>>>>>>
>>>>>>>>>>>     meshInfosTexture->setInternalFormat(GL_RGBA32UI_EXT);
>>>>>>>>>>>
>>>>>>>>>>>     
>>>>>>>>>>> meshInfosTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
>>>>>>>>>>>
>>>>>>>>>>>     
>>>>>>>>>>> stateSet->setTextureAttributeAndModes(MESH_INFOS_ARRAY_TEXTURE_UNIT,
>>>>>>>>>>>  meshInfosTexture.get());
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>     // ----------------------
>>>>>>>>>>>     // Create and assign the Task- and Mesh shader as usual by 
>>>>>>>>>>> using the corresponding shader type    // ----------------------
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Am 10.05.2022 um 21:20 schrieb DC:
>>>>>>>>>>>
>>>>>>>>>>> OK.  Thank you.
>>>>>>>>>>>
>>>>>>>>>>> On Tuesday, May 10, 2022 at 12:59:37 PM UTC-5 Werner Modenbach
>>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Hi DC,
>>>>>>>>>>>> I think we should clarify some aspects before going into the
>>>>>>>>>>>> details. If I understand well, your problem can be split into 3 
>>>>>>>>>>>> parts
>>>>>>>>>>>> 1) You want to convert an existing model into meshlets. This is
>>>>>>>>>>>> not related to OSG. But I found a git repository from NVIDIA doing 
>>>>>>>>>>>> this
>>>>>>>>>>>> job. I will lookup the link and send it to you tomorrow.
>>>>>>>>>>>> 2) For this to work you need task/mesh shaders doing their job
>>>>>>>>>>>> on the GPU. This is also not related to OSG. Maybe you find some 
>>>>>>>>>>>> starting
>>>>>>>>>>>> point in the repository as well.
>>>>>>>>>>>> 3) You need to know how to load your shader and how to setup
>>>>>>>>>>>> the data structures in OSG. I hope I can help you with that by 
>>>>>>>>>>>> providing
>>>>>>>>>>>> some code snippets.
>>>>>>>>>>>> Just let me know when you are ready for that step. But the code
>>>>>>>>>>>> I provided already should help you.
>>>>>>>>>>>> Werner
>>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>> You received this message because you are subscribed to the
>>>>>>>>>> Google Groups "OpenSceneGraph Users" group.
>>>>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>>>>> send an email to [email protected].
>>>>>>>>>> To view this discussion on the web visit
>>>>>>>>>> https://groups.google.com/d/msgid/osg-users/7680959c-297e-41ff-9159-464b38c8df73n%40googlegroups.com
>>>>>>>>>> <https://groups.google.com/d/msgid/osg-users/7680959c-297e-41ff-9159-464b38c8df73n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>>> .
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> trajce nikolov nick
>>>>>>>>>
>>>>>>>>> --
>>>>>>>> You received this message because you are subscribed to the Google
>>>>>>>> Groups "OpenSceneGraph Users" group.
>>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>>> send an email to [email protected].
>>>>>>>> To view this discussion on the web visit
>>>>>>>> https://groups.google.com/d/msgid/osg-users/eb4531f5-3420-4c75-be46-539490c5c659%40email.android.com
>>>>>>>> <https://groups.google.com/d/msgid/osg-users/eb4531f5-3420-4c75-be46-539490c5c659%40email.android.com?utm_medium=email&utm_source=footer>
>>>>>>>> .
>>>>>>>>
>>>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "OpenSceneGraph Users" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to [email protected].
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/osg-users/3fd7dcac-1cec-43d9-ac91-04e22f331bd9%40email.android.com
>>>>> <https://groups.google.com/d/msgid/osg-users/3fd7dcac-1cec-43d9-ac91-04e22f331bd9%40email.android.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>>
>>>
>>> --
>>> trajce nikolov nick
>>>
>>>
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
>>>  Virus-free.
>>> www.avast.com
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
>>> <#m_-7378692753233440497_m_-4127028168198206277_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
>>>
>>
>>
>> --
>> trajce nikolov nick
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "OpenSceneGraph Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/osg-users/0ab4c82f-1f17-47e9-aa1d-9c02b5a3f7fb%40email.android.com
> <https://groups.google.com/d/msgid/osg-users/0ab4c82f-1f17-47e9-aa1d-9c02b5a3f7fb%40email.android.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"OpenSceneGraph Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osg-users/CAO-%2Bzi%3DoBzkPA8dKafgKp-ua2yeqijsvyyg-G14e%3DvTU%2BzF1yQ%40mail.gmail.com.
// This is public domain software and comes with
// absolutely no warranty. Use of public domain software
// may vary between counties, but in general you are free
// to use and distribute this software for any purpose.


// Example: OSG using an OpenGL 3.1 context.
// The comment block at the end of the source describes building OSG
// for use with OpenGL 3.x.

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osg/GraphicsContext>
#include <osg/Camera>
#include <osg/Viewport>
#include <osg/StateSet>
#include <osg/Program>
#include <osg/Shader>
#include <osg/DrawMeshTasks>
#include <osg/DrawMeshTasksIndirect>
#include <osg/MultiDrawMeshTasksIndirect>
#include <osg/MultiDrawMeshTasksIndirectCount>
#include <osgUtil/Optimizer>
#include <osg/TextureBuffer>
#include <osg/TriangleFUnctor>

#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>

#include <osg/MatrixTransform>

#include <osgSim/LightPointNode>

#define MESH_VERTEX_ARRAY_TEXTURE_UNIT 0
#define MESH_INFOS_ARRAY_TEXTURE_UNIT 1
#define MESH_INDEX_ARRAY_TEXTURE_UNIT 2

using namespace osg;

namespace osg
{

class ProxyPrimitive : public PrimitiveSet
{
public:

    ProxyPrimitive() {}

    ProxyPrimitive(const ProxyPrimitive& pp, const CopyOp& copyop=CopyOp::SHALLOW_COPY) :
        PrimitiveSet(pp, copyop),
        drawMeshTasks(pp.drawMeshTasks) {}

    META_Object(osg, ProxyPrimitive)

    ref_ptr<DrawMeshTasks> drawMeshTasks;

    void draw(State& state, bool) const
    {
		state.apply();
        drawMeshTasks->draw(state);
    }

    void accept(PrimitiveFunctor&) const {}
    void accept(PrimitiveIndexFunctor&) const {}

    unsigned int index(unsigned int) const { return 0; }
    unsigned int getNumIndices() const { return 0; }
    void offsetIndices(int) {}
};

}

struct ToMeshletsVisitor : public osg::NodeVisitor
{
	ToMeshletsVisitor()
		: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
	{

	}

	//virtual void apply(osg::Transform& node)
	//{
	//	if (node.asMatrixTransform())
	//	{
	//		node.asMatrixTransform()->setMatrix(osg::Matrixd::identity());
	//	}
	//	traverse(node);
	//}

	//virtual void apply(osg::LOD& node)
	//{
	//	node.setCenter(osg::Vec3(0, 0, 0));
	//	traverse(node);
	//}

	
	struct Triangulate
	{
		struct Meshlet
		{
			size_t start = 0;
			size_t index_start = 0;
			std::vector<uint32_t> vertices;
			std::vector<uint32_t> indices;
			size_t count = 0;
			std::vector<osg::Vec3> v_vec;

			bool v_exists(const osg::Vec3& v)
			{
				for (size_t i = 0; i < v_vec.size(); ++i)
				{
					if (v_vec.at(i) == v) return true;
				}
				return false;
			}
		};

		std::vector<Meshlet> meshlets_from_geometry;


		size_t vxs_start = 0;
		size_t idx_start = 0;

		inline void operator () (const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3)
		{
			if (!meshlets_from_geometry.size())
			{
				meshlets_from_geometry.push_back(Meshlet());
			}			

			bool unique_v1 = false;
			bool unique_v2 = false;
			bool unique_v3 = false;
			size_t num_unique_verts = 0;

			
			

			Meshlet& meshlet = meshlets_from_geometry.back();

			if (!meshlet.v_exists(v1))			
			{
				unique_v1 = true;
				++num_unique_verts;

				//meshlet.v_vec.push_back(v1);
			}			
			if (!meshlet.v_exists(v2))
			{
				unique_v2 = true;
				++num_unique_verts;

				//meshlet.v_vec.push_back(v2);
			}
			if (!meshlet.v_exists(v3))
			{
				unique_v3 = true;
				++num_unique_verts;

				//meshlet.v_vec.push_back(v3);
			}

			


			if (num_unique_verts + meshlet.vertices.size() > 32)
			{					
				vxs_start += meshlet.vertices.size();
				idx_start += meshlet.indices.size();

				meshlets_from_geometry.push_back(Meshlet());
				Meshlet& meshlet = meshlets_from_geometry.back();

				meshlet.start = vxs_start;
				meshlet.index_start = idx_start;

				unique_v1 = true;				
				//meshlet.v_vec.push_back(v1);

				unique_v2 = true;
				//meshlet.v_vec.push_back(v2);

				unique_v3 = true;
				//meshlet.v_vec.push_back(v3);
			}
			
			std::map<osg::Vec3, size_t>::iterator itr = vxs_map.find(v1);
			if (itr == vxs_map.end())
			{
				indices->push_back(vxs->size());
				vxs_map[v1] = vxs->size();

				vxs->push_back(v1);
			}
			else
			{
				indices->push_back(itr->second);
			}
			meshlet.indices.push_back(indices->back());

			itr = vxs_map.find(v2);
			if (itr == vxs_map.end())
			{
				indices->push_back(vxs->size());
				vxs_map[v2] = vxs->size();

				vxs->push_back(v2);
			}
			else
			{
				indices->push_back(itr->second);
			}
			meshlet.indices.push_back(indices->back());
			itr = vxs_map.find(v3);
			if (itr == vxs_map.end())
			{
				indices->push_back(vxs->size());
				vxs_map[v3] = vxs->size();

				vxs->push_back(v3);
			}
			else
			{
				indices->push_back(itr->second);
			}			
			meshlet.indices.push_back(indices->back());
	
			{
				Meshlet& meshlet = meshlets_from_geometry.back();

				if (meshlet.count + 1 == 126)
				{
					vxs_start += meshlet.vertices.size();
					idx_start += meshlet.indices.size();

					meshlets_from_geometry.push_back(Meshlet());
					Meshlet& meshlet = meshlets_from_geometry.back();

					meshlet.start = vxs_start;
					meshlet.index_start = idx_start;

					meshlet.start = vxs_start;
					meshlet.index_start = idx_start;

					unique_v1 = true;
					//meshlet.v_vec.push_back(v1);

					unique_v2 = true;
					//meshlet.v_vec.push_back(v2);

					unique_v3 = true;
					//meshlet.v_vec.push_back(v3);
				}

				{
					Meshlet& meshlet = meshlets_from_geometry.back();

					if (unique_v1) { meshlet.vertices.push_back(vxs_map[v1]); meshlet.v_vec.push_back(v1); }
					if (unique_v2) { meshlet.vertices.push_back(vxs_map[v2]); meshlet.v_vec.push_back(v2); }
					if (unique_v3) { meshlet.vertices.push_back(vxs_map[v3]); meshlet.v_vec.push_back(v3); }
				}

				{
					Meshlet& meshlet = meshlets_from_geometry.back();

					/*meshlet.indices.push_back(vxs_map[v1]);
					meshlet.indices.push_back(vxs_map[v2]);
					meshlet.indices.push_back(vxs_map[v3]);*/

					meshlet.count++;
				}
			}

		}

		inline void set(osg::Vec3Array* vertices)
		{
			vxs = vertices;
		}
		
		osg::Vec3Array* vxs;
		osg::ref_ptr<osg::UIntArray> indices = new osg::UIntArray;
		std::map<osg::Vec3, size_t> vxs_map;
	};

	virtual void apply(osg::Node& node)
	{
		osg::ref_ptr<osgSim::LightPointNode> lpn = dynamic_cast<osgSim::LightPointNode*>(&node);
		if (lpn.valid())
		{
			lpn->setNodeMask(0);
			return;
		}
		traverse(node);
	}
	

	virtual void apply(osg::Geode& node)
	{
		

		for (size_t i = 0; i < node.getNumDrawables(); ++i)
		{
			osg::ref_ptr<osg::Geometry> g = node.getDrawable(i)->asGeometry();
			if (g.valid())
			{			
				osg::ref_ptr<osg::Vec3Array> vxs = new osg::Vec3Array;
				
				osg::TriangleFunctor<Triangulate> t;
				t.set(vxs);

				

				g->accept(t);								
				if (vxs->size() < 3) continue;
				if (t.indices->size() < 3) continue;



				size_t maxVertices = 32;				
				

				osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
				geometry->setUseDisplayList(false);

				size_t cnt = 0;
				//for (auto i = 0; i < numMeshlets; ++i)
				{
					size_t numVertices = vxs->size();// osg::minimum(maxVertices, vxs->size() - cnt);
					osg::ref_ptr<osg::Vec4Array> osgVertices = new osg::Vec4Array(numVertices);

					osg::BoundingBox bb;

					for (auto j = 0; j < numVertices; ++j) {    // fill array
						(*osgVertices)[j] = osg::Vec4(vxs->at(j), 1);

						bb.expandBy(vxs->at(j));
					}

					osg::ref_ptr<osg::FloatArray> osgIndices = new osg::FloatArray(t.indices->size());

					for (auto j = 0; j < t.indices->size(); ++j) {    // fill array
						(*osgIndices)[j] = t.indices->at(j);
					}



					// Create Buffer and Texture
					osg::ref_ptr<osg::VertexBufferObject> verticesBufferObject = new osg::VertexBufferObject();
					verticesBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
					osgVertices->setBufferObject(verticesBufferObject.get());
					osg::ref_ptr<osg::TextureBuffer> vertexTexture = new osg::TextureBuffer(osgVertices.get());
					vertexTexture->setInternalFormat(GL_RGBA32F_ARB);
					vertexTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
					geometry->getOrCreateStateSet()->setTextureAttributeAndModes(MESH_VERTEX_ARRAY_TEXTURE_UNIT, vertexTexture.get());

					// Create Buffer and Texture
					osg::ref_ptr<osg::VertexBufferObject> indicesBufferObject = new osg::VertexBufferObject();
					indicesBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
					osgIndices->setBufferObject(indicesBufferObject.get());
					osg::ref_ptr<osg::TextureBuffer> indexTexture = new osg::TextureBuffer(osgIndices.get());
					indexTexture->setInternalFormat(GL_LUMINANCE32F_ARB);
					indexTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
					geometry->getOrCreateStateSet()->setTextureAttributeAndModes(MESH_INDEX_ARRAY_TEXTURE_UNIT, indexTexture.get());

					geometry->setComputeBoundingBoxCallback(new MyCB(bb));
				}
				size_t ts = t.meshlets_from_geometry.size();
				while (ts > GL_TASK_WORK_GROUP_SIZE_NV)
				{

					osg::ref_ptr<osg::ProxyPrimitive> proxyPrimitive = new osg::ProxyPrimitive;
					proxyPrimitive->drawMeshTasks = new osg::DrawMeshTasks(0, GL_TASK_WORK_GROUP_SIZE_NV);
					geometry->addPrimitiveSet(proxyPrimitive.get());					

					ts -= GL_TASK_WORK_GROUP_SIZE_NV;
				}
				osg::ref_ptr<osg::ProxyPrimitive> proxyPrimitive = new osg::ProxyPrimitive;
				proxyPrimitive->drawMeshTasks = new osg::DrawMeshTasks(0, ts);
				geometry->addPrimitiveSet(proxyPrimitive.get());

				

				osg::ref_ptr<Vec4Array> MeshletInfosArray = new Vec4Array(t.meshlets_from_geometry.size());
				for (auto i = 0; i < t.meshlets_from_geometry.size(); ++i)
				{
					(*MeshletInfosArray)[i][0] = (int)t.meshlets_from_geometry.at(i).start;
					(*MeshletInfosArray)[i][1] = (int)t.meshlets_from_geometry.at(i).vertices.size();					

					(*MeshletInfosArray)[i][2] = (int)t.meshlets_from_geometry.at(i).index_start;
					(*MeshletInfosArray)[i][3] = (int)t.meshlets_from_geometry.at(i).indices.size();

					
				}

				
				// Create Buffer and Texture
				osg::ref_ptr<osg::VertexBufferObject> meshInfosBufferObject = new osg::VertexBufferObject();
				meshInfosBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
				MeshletInfosArray->setBufferObject(meshInfosBufferObject.get());
				osg::ref_ptr<osg::TextureBuffer> meshInfosTexture = new osg::TextureBuffer(MeshletInfosArray.get());
				meshInfosTexture->setInternalFormat(GL_RGBA32F_ARB);
				meshInfosTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
				geometry->getOrCreateStateSet()->setTextureAttributeAndModes(MESH_INFOS_ARRAY_TEXTURE_UNIT, meshInfosTexture.get());

				

				meshlets.push_back(geometry);				
			}
		}
		node.getOrCreateStateSet()->setTextureAttributeAndModes(MESH_VERTEX_ARRAY_TEXTURE_UNIT, 0);
		node.removeDrawables(0, node.getNumDrawables());

		for (size_t i = 0; i < meshlets.size(); ++i)
		{
			node.addDrawable(meshlets.at(i));
		}
		meshlets.clear();

		traverse(node);
	}
	std::vector<osg::ref_ptr<osg::Geometry>> meshlets;

	struct MyCB : public osg::Drawable::ComputeBoundingBoxCallback
	{
		MyCB(const osg::BoundingBox& bb)
			: _bb(bb)
		{

		}

		virtual BoundingBox computeBound(const osg::Drawable&) const
		{			
			return _bb;
		}

		osg::BoundingBox _bb;
	};

	osg::ref_ptr<osg::Geode> geode = new osg::Geode;
};



int main( int argc, char** argv )
{
    osg::ArgumentParser arguments( &argc, argv );

	static const char* meshSource = \
		"#version 450 \n"
		"#extension GL_NV_mesh_shader : enable\n"
		"layout(local_size_x = 32) in;"
		"layout(max_vertices = 64) out;"
		"layout(max_primitives = 126) out;"
		"layout(triangles) out;"
		"uniform samplerBuffer vertices;"
		"uniform samplerBuffer meshletsInfo;"
		"uniform samplerBuffer indices;"
		"uniform mat4 osg_ModelViewProjectionMatrix;"
        "void main()"
        "{"		
			"uint mi = gl_WorkGroupID.x;"
			"vec4 u = texelFetch(meshletsInfo, int(mi));"
			"int start = int(u.x);"
			"int count = int(u.y);"
			"int idx_start = int(u.z);"
			"int idx_count = int(u.w);"
            "uint id = gl_LocalInvocationID.x;"				
			"if (id < count)"
			"{"
				"vec4 t = texelFetch(vertices, int(start+id));"
				"gl_MeshVerticesNV[id].gl_Position = osg_ModelViewProjectionMatrix* t;"
			"}"
			"for (int i = 0; i < idx_count; ++i)"
			"{"
				"uint idx = uint(texelFetch(indices,int(idx_start+i)).x);"
				"gl_PrimitiveIndicesNV[i] = idx;"
			"}"			
			//"if (id == 0)"
				"gl_PrimitiveCountNV = idx_count/3;"
        "}";


    static const char* fragmentSource = \
        "#version 450 \n"
        "#extension GL_NV_fragment_shader_barycentric : enable\n"
        "out vec4 color;"
        "void main()"
        "{"
            "color = vec4(gl_BaryCoordNV, 1.0);"
        "}";

    osg::ref_ptr<osg::Shader> vShader = new osg::Shader( osg::Shader::MESH, meshSource );
    osg::ref_ptr<osg::Shader> fShader = new osg::Shader( osg::Shader::FRAGMENT, fragmentSource );

    osg::ref_ptr<osg::Program> program = new osg::Program;
    program->addShader( vShader.get() );
    program->addShader( fShader.get() );

    osg::ref_ptr<osg::Group> group = new osg::Group;
    group->getOrCreateStateSet()->setAttribute( program.get() );

	group->getOrCreateStateSet()->getOrCreateUniform("meshletsInfo", osg::Uniform::SAMPLER_BUFFER)->set(1);
	group->getOrCreateStateSet()->getOrCreateUniform("indices", osg::Uniform::SAMPLER_BUFFER)->set(2);


    // group->addChild( new osg::DrawMeshTasksIndirect(0) ); // will require a buffer to be bound.
    // group->addChild( new osg::MultiDrawMeshTasksIndirect(0, 0, 0) ); // will require a buffer to be bound.
    // group->addChild( new osg::MultiDrawMeshTasksIndirectCount(0, 0, 0, 0) ); // will require a buffer to be bound.

    osgDB::writeNodeFile(*group, "test.osg");

    osgViewer::Viewer viewer(arguments);

	// add the state manipulator
	viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));

	// add the thread model handler
	viewer.addEventHandler(new osgViewer::ThreadingHandler);

	// add the window size toggle handler
	viewer.addEventHandler(new osgViewer::WindowSizeHandler);

	// add the stats handler
	viewer.addEventHandler(new osgViewer::StatsHandler);

	// add the help handler
	viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));

	// add the record camera path handler
	viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

	// add the LOD Scale handler
	viewer.addEventHandler(new osgViewer::LODScaleHandler);

	// add the screen capture handler
	viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);

	osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);

	ToMeshletsVisitor nv;
	model->accept(nv);

	group->addChild( model );

    viewer.setSceneData( group );
	viewer.realize();

	osg::setNotifyLevel(osg::NOTICE);

    // for non GL3/GL4 and non GLES2 platforms we need enable the osg_ uniforms that the shaders will use,
    // you don't need thse two lines on GL3/GL4 and GLES2 specific builds as these will be enable by default.
	viewer.getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true);
	viewer.getCamera()->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);

    return( viewer.run() );
}

Reply via email to