Example #1
0
  static void WriteMesh(JsonWriter json, Mesh mesh, GeometryPool.VertexLayout layout) {
    // Unity does not import .obj verbatim. It makes these changes:
    // - flip x axis
    // - reverse winding of triangles
    // We undo these changes when exporting to obj.
    // NOTE: It's currently unknown whether this also happens for fbx files.

    int nVert = mesh.vertexCount;
    WriteArray(json, "v", AsByte(mesh.vertices, nVert, flip: true));
    if (layout.bUseNormals) {
      WriteArray(json, "n", AsByte(mesh.normals, nVert, flip: true));
    }
    WriteUvChannel(json, 0, layout.texcoord0.size, mesh, nVert);
    WriteUvChannel(json, 1, layout.texcoord1.size, mesh, nVert);
    if (layout.bUseColors) {
      WriteArray(json, "c", AsByte(mesh.colors32, nVert));
    }
    // NOTE(b/30710462): Bubble wand lies about its tangents, so check they are really there
    if (layout.bUseTangents && mesh.tangents.Length > 0) {
      WriteArray(json, "t", AsByte(mesh.tangents, nVert, flip: true));
    }

    var tris = mesh.GetTriangles(0);
    // Reverse winding, per above
    for (int i = 0; i < tris.Length; i += 3) {
      var tmp = tris[i+1];
      tris[i+1] = tris[i+2];
      tris[i+2] = tmp;
    }
    WriteArray(json, "tri", AsByte(tris, tris.Length));
  }
 public override GeometryPool.VertexLayout GetVertexLayout(BrushDescriptor desc) {
   // XXX: This doesn't work because blocks models may not always have the same vertex layout.
   //      It happens to work currently.
   var layout = new GeometryPool.VertexLayout();
   layout.bUseColors = true;
   layout.bUseNormals = true;
   layout.bUseTangents = false;
   layout.bUseVertexIds = false;
   return layout;
 }
Example #3
0
 // Puts the passed timestamp data into pool.texcoord2.
 // It's assumed that the pool does not already have anything in texcoord2.
 private static void AugmentWithTimestamps(GeometryPool pool, ref List <Vector3> timestamps)
 {
     if (App.UserConfig.Export.ExportStrokeTimestamp)
     {
         GeometryPool.VertexLayout withTxc2 = pool.Layout;
         if (withTxc2.texcoord2.size == 0 && timestamps.Count == pool.NumVerts)
         {
             withTxc2.texcoord2 = new TexcoordInfo {
                 size = 3, semantic = Semantic.Timestamp
             };
             pool.Layout         = withTxc2;
             pool.m_Texcoord2.v3 = timestamps;
             timestamps          = null; // don't let caller reuse the list
         }
         else
         {
             Debug.LogError("Internal error; cannot add timestamps");
         }
     }
 }
Example #4
0
        /// Rewrite vertices and indices, welding together identical verts.
        /// Input topology must be as documented at the top of QuadStripBrush.cs
        /// Output topology is the same as FlatGeometryBrush
        private static void WeldSingleSidedQuadStrip(
            GeometryPool.VertexLayout layout,
            MasterBrush geometry,
            int numVerts,
            out int newNumVerts,
            out int newNumTris)
        {
            // Offsets to Front/Back Left/Right verts, QuadStrip-style (see ascii art at top of file)
            // Because of duplication, there are sometimes multiple offsets.
            // "S" is the stride, either 6 or 12 depending on usesDoubleSidedGeometry.
            // In cases where there are multiple offsets to choose from, we choose the offset
            // which makes it safe to reorder verts in-place. See the comment below re: overlaps
            const int kBrOld = 2; // also -S+5, 3
            const int kBlOld = 0; // also -S+1, -S+4
            const int kFrOld = 5; // also S+2, S+3
            const int kFlOld = 1; // also 4, S+0

            // Offsets to Front/Back Left/Right verts, FlatGeometry-style
            // See FlatGeometryBrush.cs:15
            const int kBrNew = 0;
            const int kBlNew = 1;
            const int kFrNew = 2;
            const int kFlNew = 3;

            // End result:
            //     0--1  4      keep 2, 0, 5, 1      0--1
            //     |,' ,'|  ->  ignore 3, 4      ->  |,'|
            //     2  3--5                           2--5

            int vertRead  = 0; // vertex read index
            int vertWrite = 0; // vertex write index
            int triWrite  = 0; // triangle write index

            var vs = geometry.m_Vertices;
            var ns = geometry.m_Normals;
            var cs = geometry.m_Colors;
            var ts = geometry.m_Tangents;

            var tris = geometry.m_Tris;

            var uv2s = geometry.m_UVs;
            var uv3s = geometry.m_UVWs.GetBackingArray();

            while (vertRead < numVerts)
            {
                // Compress a single connected strip.
                // The first quad is treated differently from subsequent quads,
                // because it doesn't have a previous quad to share its first two verts with.

                // First quad

                // We write to the same buffer being read from, which is a bit dangerous.
                // Correctness requires we not copy from a location that's been written to.
                // The potential problem cases where the read area overlaps the write area are:
                //   Quad #0:   write [0, 4)   read [0, 6)
                //   Quad #1:   write [4, 8)   read [6, 12)
                // For subsequent quads the read area is ahead of, and does not overlap, the write area.
                vs[vertWrite + kFlNew] = vs[vertRead + kFlOld]; // 3 <- 1   7 <- 7
                ns[vertWrite + kFlNew] = ns[vertRead + kFlOld];
                cs[vertWrite + kFlNew] = cs[vertRead + kFlOld];
                ts[vertWrite + kFlNew] = ts[vertRead + kFlOld];

                vs[vertWrite + kBlNew] = vs[vertRead + kBlOld]; // 1 <- 0   5 <- 6
                ns[vertWrite + kBlNew] = ns[vertRead + kBlOld];
                cs[vertWrite + kBlNew] = cs[vertRead + kBlOld];
                ts[vertWrite + kBlNew] = ts[vertRead + kBlOld];

                vs[vertWrite + kBrNew] = vs[vertRead + kBrOld]; // 0 <- 2   4 <- 8
                ns[vertWrite + kBrNew] = ns[vertRead + kBrOld];
                cs[vertWrite + kBrNew] = cs[vertRead + kBrOld];
                ts[vertWrite + kBrNew] = ts[vertRead + kBrOld];

                vs[vertWrite + kFrNew] = vs[vertRead + kFrOld]; // 2 <- 5   6 <- 11
                ns[vertWrite + kFrNew] = ns[vertRead + kFrOld];
                cs[vertWrite + kFrNew] = cs[vertRead + kFrOld];
                ts[vertWrite + kFrNew] = ts[vertRead + kFrOld];

                if (layout.texcoord0.size == 2)
                {
                    uv2s[vertWrite + kFlNew] = uv2s[vertRead + kFlOld];
                    uv2s[vertWrite + kBlNew] = uv2s[vertRead + kBlOld];
                    uv2s[vertWrite + kBrNew] = uv2s[vertRead + kBrOld];
                    uv2s[vertWrite + kFrNew] = uv2s[vertRead + kFrOld];
                }
                else
                {
                    uv3s[vertWrite + kFlNew] = uv3s[vertRead + kFlOld];
                    uv3s[vertWrite + kBlNew] = uv3s[vertRead + kBlOld];
                    uv3s[vertWrite + kBrNew] = uv3s[vertRead + kBrOld];
                    uv3s[vertWrite + kFrNew] = uv3s[vertRead + kFrOld];
                }

                // See FlatGeometryBrush.cs:240
                // SetTri(cur.iTri, cur.iVert, 0, BR, BL, FL);
                // SetTri(cur.iTri, cur.iVert, 1, BR, FL, FR);
                tris[triWrite + 0] = vertWrite + kBrNew;
                tris[triWrite + 1] = vertWrite + kBlNew;
                tris[triWrite + 2] = vertWrite + kFlNew;
                tris[triWrite + 3] = vertWrite + kBrNew;
                tris[triWrite + 4] = vertWrite + kFlNew;
                tris[triWrite + 5] = vertWrite + kFrNew;

                vertWrite += 4; // we wrote to a range of 4 verts
                vertRead  += 6; // we read from a range of 6 verts
                triWrite  += 6; // we wrote 6 indices

                // Remaining quads.

                // Detect strip continuation by checking a single vertex position.
                // To be fully correct, we should check both the left and right verts, and all the
                // attributes. However, as of M16 this simpler version suffices for all shipping
                // QuadStripBrushes.
                while (vertRead < numVerts && vs[vertRead + kBrOld] == vs[vertWrite - 4 + kFrNew])
                {
                    vertWrite -= 2; // Share 2 verts with the previous quad

                    // The read range will provably never overlap with the write range. Note that
                    // this cannot be quad 0 since there exists a previous quad.
                    // Therefore, the closest the ranges get is:
                    //   Quad #1:   write [2, 6)   read [6, 12)
                    vs[vertWrite + kFlNew] = vs[vertRead + kFlOld];
                    ns[vertWrite + kFlNew] = ns[vertRead + kFlOld];
                    cs[vertWrite + kFlNew] = cs[vertRead + kFlOld];
                    ts[vertWrite + kFlNew] = ts[vertRead + kFlOld];

                    vs[vertWrite + kFrNew] = vs[vertRead + kFrOld];
                    ns[vertWrite + kFrNew] = ns[vertRead + kFrOld];
                    cs[vertWrite + kFrNew] = cs[vertRead + kFrOld];
                    ts[vertWrite + kFrNew] = ts[vertRead + kFrOld];

                    if (layout.texcoord0.size == 2)
                    {
                        uv2s[vertWrite + kFlNew] = uv2s[vertRead + kFlOld];
                        uv2s[vertWrite + kFrNew] = uv2s[vertRead + kFrOld];
                    }
                    else
                    {
                        uv3s[vertWrite + kFlNew] = uv3s[vertRead + kFlOld];
                        uv3s[vertWrite + kFrNew] = uv3s[vertRead + kFrOld];
                    }

                    tris[triWrite + 0] = vertWrite + kBrNew;
                    tris[triWrite + 1] = vertWrite + kBlNew;
                    tris[triWrite + 2] = vertWrite + kFlNew;
                    tris[triWrite + 3] = vertWrite + kBrNew;
                    tris[triWrite + 4] = vertWrite + kFlNew;
                    tris[triWrite + 5] = vertWrite + kFrNew;

                    vertWrite += 4;
                    vertRead  += 6;
                    triWrite  += 6;
                }
            }

            newNumVerts = vertWrite;
            newNumTris  = triWrite;
        }