Пример #1
0
        /// <summary>
        /// Handle additional <see cref="CreateMessage"/> data.
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <param name="cache"></param>
        /// <param name="shapeIndex"></param>
        /// <returns></returns>
        protected override Error PostHandleMessage(CreateMessage msg, PacketBuffer packet, BinaryReader reader,
                                                   ShapeCache cache, int shapeIndex)
        {
            if (shapeIndex >= 0)
            {
                // Read the text in the buffer.
                TextShapeData textData   = new TextShapeData();
                int           textLength = reader.ReadUInt16();
                textData.Mesh = null;
                textData.Text = string.Empty;
                if (textLength > 0)
                {
                    byte[] textBytes = reader.ReadBytes(textLength);
                    textData.Text = System.Text.Encoding.UTF8.GetString(textBytes);
                }

                textData.FontSize = (int)msg.Attributes.ScaleZ;

                if ((msg.Flags & (ushort)Text3DFlag.ScreenFacing) != 0)
                {
                    // Need to use -forward for text.
                    // ScreenFacing.AddToManager(obj, -Vector3.forward, Vector3.up);
                    textData.ScreenFacing = true;
                }
                cache.SetShapeDataByIndex(shapeIndex, textData);
            }

            return(base.PostHandleMessage(msg, packet, reader, cache, shapeIndex));
        }
Пример #2
0
        /// <summary>
        /// Overridden to read information about mesh parts.
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected override Error PostHandleMessage(CreateMessage msg, PacketBuffer packet, BinaryReader reader,
                                                   ShapeCache cache, int shapeIndex)
        {
            PartSet parts         = new PartSet();
            ushort  meshPartCount = reader.ReadUInt16();

            parts.MeshIDs           = new uint[meshPartCount];
            parts.Meshes            = new MeshCache.MeshDetails[meshPartCount];
            parts.Transforms        = new Matrix4x4[meshPartCount];
            parts.Tints             = new Maths.Colour[meshPartCount];
            parts.MaterialOverrides = new Material[meshPartCount];
            parts.ObjectFlags       = (ObjectFlag)msg.Flags;

            for (ushort i = 0; i < meshPartCount; ++i)
            {
                parts.MeshIDs[i] = reader.ReadUInt32();
                ObjectAttributes attributes = new ObjectAttributes();
                if (!attributes.Read(reader))
                {
                    return(new Error(ErrorCode.MalformedMessage, (int)ObjectMessageID.Create));
                }

                DecodeTransform(attributes, out parts.Transforms[i]);
                parts.Tints[i] = new Maths.Colour(attributes.Colour);
            }

            cache.SetShapeDataByIndex(shapeIndex, parts);
            RegisterForMesh(msg, parts);

            return(new Error());
        }
Пример #3
0
        /// <summary>
        /// Handle triangle count.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="msg"></param>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected override Error PostHandleMessage(CreateMessage msg, PacketBuffer packet, BinaryReader reader,
                                                   ShapeCache cache, int shapeIndex)
        {
            int          vertexCount = reader.ReadInt32();
            int          indexCount  = reader.ReadInt32();
            MeshDrawType drawType    = (MeshDrawType)reader.ReadByte();

            RenderMesh mesh      = new RenderMesh(drawType, vertexCount, indexCount);
            MeshEntry  meshEntry = new MeshEntry
            {
                Mesh             = mesh,
                CalculateNormals = (msg.Flags & (ushort)MeshShapeFlag.CalculateNormals) != 0,
                DrawScale        = 0.0f
            };

            if (packet.Header.VersionMajor == 0 && packet.Header.VersionMinor == 1)
            {
                // Legacy handling.
                meshEntry.DrawScale = 0.0f;
            }
            else
            {
                meshEntry.DrawScale = reader.ReadSingle();
            }

            cache.SetShapeDataByIndex(shapeIndex, meshEntry);

            if (meshEntry.CalculateNormals)
            {
                _toCalculateNormals.Add(mesh);
            }
            return(base.PostHandleMessage(msg, packet, reader, cache, shapeIndex));
        }
        /// <summary>
        /// Overridden to read information about mesh parts.
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected override Error PostHandleMessage(CreateMessage msg, PacketBuffer packet, BinaryReader reader,
                                                   ShapeCache cache, int shapeIndex)
        {
            // Read additional attributes.
            PointsComponent pointsComp = new PointsComponent();

            // Read the mesh ID to render points from.
            pointsComp.MeshID = reader.ReadUInt32();
            // Read the number of indices (zero implies show entire mesh).
            pointsComp.IndexCount = reader.ReadUInt32();

            if (packet.Header.VersionMajor == 0 && packet.Header.VersionMinor == 1)
            {
                // Legacy support.
                pointsComp.PointScale = (float)reader.ReadByte();
            }
            else
            {
                pointsComp.PointScale = reader.ReadSingle();
            }

            cache.SetShapeDataByIndex(shapeIndex, pointsComp);

            if (pointsComp.IndexCount == 0)
            {
                pointsComp.IndicesDirty = false;
                // Not expecting any index data messages.
                // Register the mesh now.
                RegisterForMesh(pointsComp);
            }

            return(new Error());
        }
Пример #5
0
        /// <summary>
        /// Handle additional <see cref="UpdateMessage"/> data.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="msg"></param>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected override Error PostHandleMessage(UpdateMessage msg, PacketBuffer packet, BinaryReader reader,
                                                   ShapeCache cache, int shapeIndex)
        {
            TextShapeData textData = cache.GetShapeDataByIndex <TextShapeData>(shapeIndex);

            // textData.Mesh.fontSize = (int)msg.Attributes.ScaleZ;
            // textData.Mesh.color = Maths.ColourExt.ToUnity32(new Maths.Colour(msg.Attributes.Colour));
            textData.ScreenFacing = (msg.Flags & (ushort)Text3DFlag.ScreenFacing) != 0;

            cache.SetShapeDataByIndex(shapeIndex, textData);

            return(base.PostHandleMessage(msg, packet, reader, cache, shapeIndex));
        }
Пример #6
0
        protected void Render(CameraContext cameraContext, ShapeCache shapeCache)
        {
            // TODO: (KS) verify material setup.
            // TODO: (KS) incorporate the 3es scene transform.
            // TODO: (KS) handle multiple cameras (code only tailored to one).
            Vector3         cameraPosition = (Vector3)cameraContext.CameraToWorldTransform.GetColumn(3);
            CategoriesState categories     = this.CategoriesState;

            // Walk the items in the shape cache.
            foreach (int shapeIndex in shapeCache.ShapeIndices)
            {
                // if (shapeCache.GetShapeDataByIndex<CreateMessage>(shapeIndex).Category)
                CreateMessage shape = shapeCache.GetShapeByIndex(shapeIndex);
                if (!categories.IsActive(shape.Category))
                {
                    // Category not enabled.
                    continue;
                }

                // Get transform and text data.
                Matrix4x4     transform = shapeCache.GetShapeTransformByIndex(shapeIndex);
                TextShapeData textData  = shapeCache.GetShapeDataByIndex <TextShapeData>(shapeIndex);

                if (textData.Mesh == null || textData.Material == null)
                {
                    // No mesh/material. Try instantiate via the delegate.
                    if (CreateTextMeshHandler != null)
                    {
                        CreateTextMeshHandler(textData.Text, textData.FontSize,
                                              Maths.ColourExt.ToUnity(new Maths.Colour(shape.Attributes.Colour)),
                                              ref textData.Mesh, ref textData.Material);
                    }

                    if (textData.Mesh == null || textData.Material == null)
                    {
                        continue;
                    }

                    // Newly creates mesh/material. Store the changes.
                    shapeCache.SetShapeDataByIndex <TextShapeData>(shapeIndex, textData);
                }

                if (textData.Mesh == null || textData.Material == null)
                {
                    continue;
                }

                if (textData.ScreenFacing)
                {
                    Vector3 textPosition = cameraContext.TesSceneToWorldTransform * (Vector3)transform.GetColumn(3);
                    Vector3 toCamera     = cameraPosition - textPosition;
                    // Remove any height component from the camera. Indexing using Unity's left handed, Y up system.
                    toCamera[1] = 0;

                    if (toCamera.sqrMagnitude > 1e-3f)
                    {
                        toCamera = toCamera.normalized;
                        Vector3 side = Vector3.Cross(toCamera, Vector3.up);
                        // Build new rotation axes using toCamera for forward and a new Up axis.
                        transform.SetColumn(0, new Vector4(side.x, side.y, side.z));
                        transform.SetColumn(1, new Vector4(Vector3.up.x, Vector3.up.y, Vector3.up.z));
                        transform.SetColumn(2, new Vector4(toCamera.x, toCamera.y, toCamera.z));
                        transform.SetColumn(3, new Vector4(textPosition.x, textPosition.y, textPosition.z, 1.0f));
                    }
                    // else too close to the camera to build a rotation.
                }
                else
                {
                    // transform = cameraContext.TesSceneToWorldTransform * transform;
                    // Just extract the text position.
                    // TODO: (KS) will have to look at allowing users to orient the text from the server.
                    Vector3 textPosition = cameraContext.TesSceneToWorldTransform * (Vector3)transform.GetColumn(3);
                    transform = Matrix4x4.identity;
                    transform.SetColumn(3, new Vector4(textPosition.x, textPosition.y, textPosition.z, 1.0f));
                }

                cameraContext.TransparentBuffer.DrawMesh(textData.Mesh, transform, textData.Material);

                // TODO: (KS) resolve procedural rendering without a game object. Consider TextMeshPro.
                // TODO: (KS) select opaque layer.
                // Graphics.DrawMesh(textData.Mesh, transform, material, 0);
            }
        }
Пример #7
0
        /// <summary>
        /// Overridden to handle triangle data in the <paramref name="msg"/>
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="packet"></param>
        /// <param name="reader"></param>
        /// <returns></returns>
        protected override Error HandleMessage(DataMessage msg, PacketBuffer packet, BinaryReader reader)
        {
            ShapeCache cache      = (msg.ObjectID == 0) ? _transientCache : _shapeCache;
            int        shapeIndex = (msg.ObjectID == 0) ? _lastTransientIndex : cache.GetShapeIndex(msg.ObjectID);

            if (shapeIndex < 0)
            {
                return(new Error(ErrorCode.InvalidObjectID, msg.ObjectID));
            }

            // Naive support for multiple packets. Assume:
            // - In order.
            MeshEntry meshEntry = cache.GetShapeDataByIndex <MeshEntry>(shapeIndex);

            // Well, this is confusing indirection...
            int readComponent = MeshShape.ReadDataComponentDeferred(
                reader, (uint)meshEntry.Mesh.VertexCount, (uint)meshEntry.Mesh.IndexCount,
                // Vertex handler.
                new MeshShape.ComponentBlockReader((MeshShape.SendDataType dataType, BinaryReader reader2, uint offset, uint count) =>
            {
                return(ReadMeshVector3Data(reader2, offset, count, (Vector3[] buffer, int writeOffset, int writeCount) =>
                {
                    meshEntry.Mesh.SetVertices(buffer, 0, writeOffset, writeCount, true);
                }));
            }),
                // Index handler
                new MeshShape.ComponentBlockReader((MeshShape.SendDataType dataType, BinaryReader reader2, uint offset, uint count) =>
            {
                return(ReadIndexComponent(reader2, offset, count, meshEntry.Mesh));
            }),
                // Normals handler.
                new MeshShape.ComponentBlockReader((MeshShape.SendDataType dataType, BinaryReader reader2, uint offset, uint count) =>
            {
                return(ReadMeshVector3Data(reader2, offset, count, (Vector3[] buffer, int writeOffset, int writeCount) =>
                {
                    if (dataType == MeshShape.SendDataType.UniformNormal)
                    {
                        // Only one normal for the whole mesh.
                        // Fill the buffer and write in chunks.
                        for (int i = 1; i < buffer.Length; ++i)
                        {
                            buffer[i] = buffer[0];
                        }
                        int localOffset = 0;
                        for (int i = 0; i < meshEntry.Mesh.VertexCount; i += buffer.Length)
                        {
                            int blockCount = Math.Min(buffer.Length, meshEntry.Mesh.VertexCount - localOffset);
                            meshEntry.Mesh.SetNormals(buffer, 0, localOffset, blockCount);
                            writeOffset += blockCount;
                        }
                    }
                    else
                    {
                        meshEntry.Mesh.SetNormals(buffer, 0, writeOffset, writeCount);
                    }
                }));
            }),
                // Colours handler.
                new MeshShape.ComponentBlockReader((MeshShape.SendDataType dataType, BinaryReader reader2, uint offset, uint count) =>
            {
                return(ReadColourComponent(reader2, offset, count, meshEntry.Mesh));
            })
                );

            if (readComponent == -1)
            {
                return(new Error(ErrorCode.MalformedMessage, DataMessage.MessageID));
            }

            if (readComponent == (int)(MeshShape.SendDataType.Vertices | MeshShape.SendDataType.End))
            {
                // Finalise the material.
                meshEntry.Material = CreateMaterial(cache.GetShapeByIndex(shapeIndex), meshEntry);
                cache.SetShapeDataByIndex(shapeIndex, meshEntry);
            }

            return(new Error());
        }