예제 #1
0
        /// <summary>
        /// Handles <see cref="MeshFinaliseMessage"/>.
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        /// <remarks>
        /// This creates the required Unity <c>Mesh</c> objects and emits <see cref="OnMeshFinalised"/>.
        /// </remarks>
        protected Error FinaliseMesh(PacketBuffer packet, BinaryReader reader)
        {
            MeshFinaliseMessage msg = new MeshFinaliseMessage();

            if (!msg.Read(reader))
            {
                return(new Error(ErrorCode.MalformedMessage, MeshFinaliseMessage.MessageID));
            }

            MeshDetails meshEntry;

            if (!_meshes.TryGetValue(msg.MeshID, out meshEntry))
            {
                return(new Error(ErrorCode.InvalidObjectID, msg.MeshID));
            }

            if (meshEntry.Finalised)
            {
                return(new Error(ErrorCode.MeshAlreadyFinalised, meshEntry.ID));
            }

            bool generateNormals = (msg.Flags & (uint)MeshBuildFlags.CalculateNormals) != 0;

            if (generateNormals)
            {
                meshEntry.Mesh.CalculateNormals();
            }

            SelectMaterial(meshEntry.Mesh);

            // Generate the meshes here.
            meshEntry.Finalised = true;
            NotifyMeshFinalised(meshEntry);
            return(new Error());
        }
예제 #2
0
        /// <summary>
        /// Handles transfer of mesh content.
        /// </summary>
        /// <param name="packet">The packet buffer in which to compose the transfer message.</param>
        /// <param name="byteLimit">An advisory byte limit used to restrict how much data should be sent (in bytes).</param>
        /// <param name="progress">The progress value from the last call to this method.</param>
        /// <returns>A new value for <paramref name="progress"/> to use on the next call.</returns>
        /// <remarks>
        /// Supports amortised transfer via the <paramref name="progress"/> argument.
        /// On first call, this is the default initialised structure (zero). On subsequent
        /// calls it is the last returned value unless <c>Failed</c> was true.
        ///
        /// The semantics of this value are entirely dependent on the internal implementation.
        /// </remarks>
        public void Transfer(PacketBuffer packet, int byteLimit, ref TransferProgress progress)
        {
            // Initial call?
            bool phaseComplete = false;

            switch (progress.Phase)
            {
            case (int)Phase.Vertex:
                phaseComplete = Transfer(packet, MeshMessageType.Vertex, Vertices(), byteLimit, ref progress);
                break;

            case (int)Phase.Index:
                if (IndexSize == 2)
                {
                    phaseComplete = Transfer(packet, MeshMessageType.Index, Indices2(), byteLimit, ref progress);
                }
                else if (IndexSize == 4)
                {
                    phaseComplete = Transfer(packet, MeshMessageType.Index, Indices4(), byteLimit, ref progress);
                }
                break;

            case (int)Phase.Normal:
                phaseComplete = Transfer(packet, MeshMessageType.Normal, Normals(), byteLimit, ref progress);
                break;

            case (int)Phase.Colour:
                phaseComplete = Transfer(packet, MeshMessageType.VertexColour, Colours(), byteLimit, ref progress);
                break;

            case (int)Phase.UV:
                phaseComplete = Transfer(packet, MeshMessageType.UV, UVs(), byteLimit, ref progress);
                break;

            case (int)Phase.Finalise:
                MeshFinaliseMessage msg = new MeshFinaliseMessage();
                msg.MeshID = ID;
                msg.Flags  = 0;
                if (CalculateNormals && (Components & MeshComponentFlag.Normal) != MeshComponentFlag.Normal)
                {
                    msg.Flags |= (uint)MeshFinaliseFlag.CalculateNormals;
                }
                packet.Reset((ushort)RoutingID.Mesh, MeshFinaliseMessage.MessageID);
                msg.Write(packet);
                progress.Phase = (int)Phase.End;
                phaseComplete  = true;
                break;
            }

            if (!progress.Failed)
            {
                if (phaseComplete)
                {
                    progress.Phase    = (int)NextPhase((Phase)progress.Phase);
                    progress.Progress = 0;
                    progress.Complete = progress.Phase == (int)Phase.End;
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Handles <see cref="MeshFinaliseMessage"/>.
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        /// <remarks>
        /// This creates the required Unity <c>Mesh</c> objects and emits <see cref="OnMeshFinalised"/>.
        /// </remarks>
        protected Error FinaliseMesh(PacketBuffer packet, BinaryReader reader)
        {
            MeshFinaliseMessage msg = new MeshFinaliseMessage();

            if (!msg.Read(reader))
            {
                return(new Error(ErrorCode.MalformedMessage, MeshFinaliseMessage.MessageID));
            }

            MeshDetails meshDetails;

            if (!_meshes.TryGetValue(msg.MeshID, out meshDetails))
            {
                return(new Error(ErrorCode.InvalidObjectID, msg.MeshID));
            }

            if (meshDetails.Finalised)
            {
                return(new Error(ErrorCode.MeshAlreadyFinalised, meshDetails.ID));
            }

            bool generateNormals = (msg.Flags & (uint)MeshBuildFlags.CalculateNormals) != 0;
            bool haveNormals     = meshDetails.Builder.Normals.Length > 0;

            switch (meshDetails.Topology)
            {
            case MeshTopology.Triangles:
            case MeshTopology.Quads:
                if (haveNormals || generateNormals)
                {
                    meshDetails.Material = LitMaterial;
                }
                else
                {
                    meshDetails.Material = UnlitMaterial;
                }
                break;

            case MeshTopology.Points:
                generateNormals = false;
                if (meshDetails.DrawType == (byte)MeshDrawType.Voxels)
                {
                    meshDetails.Material = VoxelsMaterial;
                    generateNormals      = !haveNormals;
                }
                else if (haveNormals)
                {
                    meshDetails.Material = PointsLitMaterial;
                    meshDetails.Material.SetInt("_LeftHanded", ServerInfo.IsLeftHanded ? 1 : 0);
                }
                else
                {
                    meshDetails.Material = PointsUnlitMaterial;
                    meshDetails.Material.SetInt("_LeftHanded", ServerInfo.IsLeftHanded ? 1 : 0);
                }
                //if (entry.VertexColours == null)
                //{
                //  entry.VertexColours = new Color32[entry.VertexCount];
                //  for (int i = 0; i < entry.VertexCount; ++i)
                //  {
                //    entry.VertexColours[i] = new Color32(1, 1, 1, 1);
                //  }
                //}
                break;

            default:
            case MeshTopology.Lines:
            case MeshTopology.LineStrip:
                generateNormals      = false;
                meshDetails.Material = UnlitMaterial;
                break;
            }

            // Generate the meshes here.
            Error err = new Error();

            meshDetails.Builder.CalculateNormals = generateNormals;
            meshDetails.Builder.GetMeshes();

            meshDetails.Finalised = true;
            NotifyMeshFinalised(meshDetails);

            return(err);
        }