Ejemplo n.º 1
0
    public void Populate(TiltBrush.GeometryPool pool)
    {
        positionAccessor.Populate(pool.m_Vertices, flipY: false, calculateMinMax: true);
        if (normalAccessor != null)
        {
            normalAccessor.Populate(pool.m_Normals, flipY: false, calculateMinMax: false);
        }
        if (colorAccessor != null)
        {
            colorAccessor.Populate(pool.m_Colors);
        }
        if (tangentAccessor != null)
        {
            tangentAccessor.Populate(pool.m_Tangents, flipY: false, calculateMinMax: false);
        }

        // UVs may be 1, 2, 3 or 4 element tuples, which the following helper method resolves.
        // In the case of zero UVs, the texCoord accessor will be null and will not be populated.
        Debug.Assert(TiltBrush.GeometryPool.kNumTexcoords == 3);
        Debug.Assert(texCoord3Accessor == null);
        var layout = pool.Layout;

        PopulateUv(0, pool, texCoord0Accessor, layout.texcoord0.semantic);
        PopulateUv(1, pool, texCoord1Accessor, layout.texcoord1.semantic);
        PopulateUv(2, pool, texCoord2Accessor, layout.texcoord2.semantic);
        PopulateUv(3, pool, texCoord3Accessor, Semantic.Unspecified);
    }
Ejemplo n.º 2
0
    public void Populate(TiltBrush.GeometryPool pool)
    {
        pool.EnsureGeometryResident();

        if (primitives.Count > 0)
        {
            // Vertex data is shared among all the primitives in the mesh, so only do [0]
            primitives[0].attributes.Populate(pool);
            primitives[0].Populate(pool);

            // I guess someone might want to map Unity submeshes -> gltf primitives.
            // - First you'd want to make sure that consuming tools won't freak out about that,
            //   since it doesn't seem to be the intended use for the mesh/primitive distinction.
            //   See https://github.com/KhronosGroup/glTF/issues/1278
            // - Then you'd want Populate() to take multiple GeometryPools, one per MeshSubset.
            // - Then you'd want those GeometryPools to indicate somehow whether their underlying
            //   vertex data is or can be shared -- maybe do this in GeometryPool.FromMesh()
            //   by having them point to the same Lists.
            // - Then you'd want to make GlTF_attributes.Populate() smart enough to understand that
            //   sharing (ie, memoizing on the List<Vector3> pointer)
            // None of that is implemented, which is okay since our current gltf generation
            // code doesn't add more than one GlTF_Primitive per GlTF_Mesh.
            if (primitives.Count > 1)
            {
                Debug.LogError("More than one primitive per mesh is unimplemented and unsupported");
            }
        }


        // The mesh data is only ever needed once (because it only goes into the .bin
        // file once), but ExportMeshGeomPool still uses bits of data like pool.NumTris
        // so we can't destroy it.
        //
        // We could MakeNotResident(filename) again, but that's wasteful and I'd need to
        // add an API to get the cache filename. So this "no coming back" API seems like
        // the most expedient solution.
        // TODO: replace this hack with something better? eg, a way to reload from
        // file without destroying the file?
        // pool.Destroy();
        pool.MakeGeometryPermanentlyNotResident();
    }
Ejemplo n.º 3
0
 public void Populate(TiltBrush.GeometryPool pool)
 {
     indices.PopulateUshort(pool.m_Tris.ToArray());
 }
Ejemplo n.º 4
0
    private void PopulateUv(
        int channel, TiltBrush.GeometryPool pool, GlTF_Accessor accessor,
        Semantic semantic)
    {
        bool packVertId = m_layout.PackVertexIdIntoTexcoord1W && channel == 1;

        if (packVertId)
        {
            // Guaranteed by GlTF_VertexLayout
            Debug.Assert(m_layout.m_tbLayout.GetTexcoordInfo(channel).size == 3);
            Debug.Assert(m_layout.GetTexcoordSize(channel) == 4);
        }
        if (accessor == null)
        {
            return;
        }
        if (channel < 0 || channel > 3)
        {
            throw new ArgumentException("Invalid channel");
        }
        TiltBrush.GeometryPool.TexcoordData texcoordData = pool.GetTexcoordData(channel);

        if (semantic == Semantic.XyIsUvZIsDistance && accessor.type != GlTF_Accessor.Type.VEC3)
        {
            throw new ArgumentException("XyIsUvZIsDistance semantic can only be applied to VEC3");
        }

        bool flipY;

        if (semantic == Semantic.Unspecified && channel == 0 &&
            accessor.type == GlTF_Accessor.Type.VEC2)
        {
            Debug.LogWarning("Assuming Semantic.XyIsUv");
            semantic = Semantic.XyIsUv;
        }
        switch (semantic)
        {
        case Semantic.Position:
        case Semantic.Vector:
        case Semantic.Timestamp:
            flipY = false;
            break;

        case Semantic.XyIsUvZIsDistance:
        case Semantic.XyIsUv:
            flipY = true;
            break;

        default:
            throw new ArgumentException("semantic");
        }

        switch (accessor.type)
        {
        case GlTF_Accessor.Type.SCALAR:
            throw new NotImplementedException();

        case GlTF_Accessor.Type.VEC2:
            accessor.Populate(texcoordData.v2, flipY: flipY, calculateMinMax: false);
            break;

        case GlTF_Accessor.Type.VEC3:
            accessor.Populate(texcoordData.v3, flipY: flipY, calculateMinMax: false);
            break;

        case GlTF_Accessor.Type.VEC4:
            if (packVertId)
            {
                // In the vertexId case, we actually have a vec3, which needs to be augmented to a vec4.
                // TODO: this should happen at some higher level.
                int i  = 0;
                var v4 = texcoordData.v3.ConvertAll <Vector4>((v => new Vector4(v.x, v.y, v.z, i++)));
                accessor.Populate(v4, flipY: flipY, calculateMinMax: false);
            }
            else
            {
                accessor.Populate(texcoordData.v4, flipY: flipY, calculateMinMax: false);
            }
            break;

        default:
            throw new ArgumentException("Unexpected accessor.type");
        }
    }