google / flatbuffers

FlatBuffers: Memory Efficient Serialization Library
https://flatbuffers.dev/
Apache License 2.0
23.28k stars 3.25k forks source link

Java/C# - How do I go about creating a Vector of Structs or Tables when building my buffer? #2099

Closed vinaysshenoy closed 8 years ago

vinaysshenoy commented 8 years ago

My schema is as follows -

namespace dab.v1;

enum VertexAttributes : byte { POSITION, NORMAL, TANGENT, UV0, UV1, UV2, UV3}

enum FaceType : byte { TRIANGLES }

struct Vector2 {
    x:float;
    y:float;
}

struct Vector3 {
    x:float;
    y:float;
    z:float;
}

struct Vector4 {
    x:float;
    y:float;
    z:float;
    w:float;
}

table Node {
    id: string (id: 0, required: true);
    meshId: string (id: 1);
    rotation: Vector4 (id: 2);
    translation: Vector3 (id: 3);
    scale: Vector3 (id: 4);
    children: [Node] (id: 5);
}

table Mesh {
    id: string (id: 0, required: true);
    attributes: [VertexAttributes] (id: 1);
    positions: [Vector3] (id: 2);
    normals: [Vector3] (id: 3);
    tangents: [Vector3] (id: 4);
    uv0: [Vector2] (id: 5);
    uv1: [Vector2] (id: 6);
    uv2: [Vector2] (id: 7);
    uv3: [Vector2] (id: 8);
    faces: [int] (id: 9);
    faceType: FaceType (id: 10);
}

table DabModel {
    id: string (id: 0, required: true);
    meshes: [Mesh] (id: 1);
    visualScene: [Node] (id: 2);
}

root_type DabModel;

My problem is that I have no idea of the right way to build my buffer for creating the vector of Mesh objects in the DabModel table, or the vector of enums(attributes) and structs(positions, normals etc) in the Mesh table. The samples included in the project are extremely simple and basic and are of barely any help.

Could someone please help me out with explaining how to do this in either C# or Java?

evolutional commented 8 years ago

You need to build the inner-most data for the table before you use it.

For example, you're building a Mesh object - you need to first build the vectors for the properties, positions, etc outside the mesh table before using them. Before you can build the vectors, you need to build the structs into the buffer first.

Here's an annotated code example in C#:

            var fbb = new FlatBufferBuilder(128);

            // Let's build a mesh

            // We want to build the members of the Mesh from 'in' to 'out'

            // Create the id in the buffer
            var meshIdOffset = fbb.CreateString("mesh01");

            // This will create a vector of the Vertex Attributes in the buffer
            // there's a helper for these, as they're scalar types
            var meshAttributesVectorOffset = Mesh.CreateAttributesVector(fbb,
                new[] { VertexAttributes.POSITION, VertexAttributes.NORMAL });

            // Create your vector for positions, you have to 'Create' these
            // and do it in reverse order
            Mesh.StartPositionsVector(fbb, 2);
            var pos1 = Vector3.CreateVector3(fbb, 10, 20, 30);
            var pos2 = Vector3.CreateVector3(fbb, 40, 50, 60);
            var positionsVectorOffset = fbb.EndVector();

            // Do the same for normals, tangents, uv0, uv1, etc

            // Now start the mesh table...
            Mesh.StartMesh(fbb);
            Mesh.AddId(fbb, meshIdOffset);

            // Add the position vector to the vtable
            Mesh.AddPositions(fbb, positionsVectorOffset);

            // Do the same for normals, tangents, uv0, uv1, etc

            // finish the mesh
            var mesh01Offset = Mesh.EndMesh(fbb);

            // Now we're thinking about building the DabModel, same principle applies
            // -> build in to out

            // Create your data for the model first
            //id
            var modelIdOffset = fbb.CreateString("model01");
            // create a vector which points to the mesh we made earlier
            var meshesVector = DabModel.CreateMeshesVector(fbb, new[] {mesh01Offset});

            DabModel.StartDabModel(fbb);
            DabModel.AddId(fbb, modelIdOffset);
            DabModel.AddMeshes(fbb, meshesVector);
            var modelOffset = DabModel.EndDabModel(fbb);

            DabModel.FinishDabModelBuffer(fbb, modelOffset);

            // Now read it back
            var dabModel = DabModel.GetRootAsDabModel(fbb.DataBuffer);

            Console.WriteLine("Model id: {0}", dabModel.Id);
            Console.WriteLine("  Mesh Count: {0}", dabModel.MeshesLength);
            for (var i = 0; i < dabModel.MeshesLength; ++i)
            {
                var mesh = dabModel.GetMeshes(i);
                Console.WriteLine("    {0}: Mesh Id: {1}", i, mesh.Id);
                Console.WriteLine("      Positions: {0}", mesh.PositionsLength);
                for (var j = 0; j < mesh.PositionsLength; ++j)
                {
                    var pos = mesh.GetPositions(j);
                    Console.WriteLine("        {0}: X:{1} Y:{2} Z:{3}", j, pos.X, pos.Y, pos.Z);
                }
            }

I have been working on a tutorial for the C# generator and code, but progress is slow.

Hope this helps get you going!

vinaysshenoy commented 8 years ago

@evolutional I was actually able to figure it out through a lot of trial and error a few hours before you replied. Thanks for the sample, anyway!

I'm actually planning to submit a PR when I get a little time that reworks the samples in the project with more complexity and shows how to do this sort of stuff, which I feel is sorely needed.

ghost commented 8 years ago

We're actually working on restructuring the documentation at the moment (with a tutorial that shows how to do things in all supported languages), so you may wanted to wait until that lands to contribute further improvements (which would still be much appreciated!)

vinaysshenoy commented 8 years ago

@gwvo That's good news! I'll wait until the documentation is done then.

Closing this now.