/// <summary> /// Overridden to write the point cloud indices. /// </summary> /// <param name="packet">Packet to write to.</param> /// <param name="progressMarker">Number of indices written so far.</param> /// <returns>0 when complete, 1 to call again.</returns> public override int WriteData(PacketBuffer packet, ref uint progressMarker) { // Max items based on packet size of 0xffff, minus some overhead divide by index size. DataMessage msg = new DataMessage(); const uint MaxItems = (uint)((0xffff - 256) / 4); packet.Reset(RoutingID, DataMessage.MessageID); msg.ObjectID = ID; msg.Write(packet); // Write indices for this view into the cloud. uint offset = progressMarker; uint count = IndexCount - progressMarker; if (count > MaxItems) { count = MaxItems; } // Use 32-bits for both values though count will never need greater than 16-bit. packet.WriteBytes(BitConverter.GetBytes(offset), true); packet.WriteBytes(BitConverter.GetBytes(count), true); if (count != 0) { for (uint i = offset; i < offset + count; ++i) { packet.WriteBytes(BitConverter.GetBytes(Index(i)), true); } } progressMarker += count; return((progressMarker < IndexCount) ? 1 : 0); }
public override int WriteData(PacketBuffer packet, ref uint progressMarker) { if (_shapes.Length <= BlockCountLimit) { // Nothing more to write. Creation packet was enough. return(0); } DataMessage msg = new DataMessage(); msg.ObjectID = ID; packet.Reset(RoutingID, DataMessage.MessageID); msg.Write(packet); UInt32 itemOffset = (progressMarker + (uint)BlockCountLimit); UInt32 remainingItems = (uint)_shapes.Length - itemOffset; UInt16 blockCount = (UInt16)(Math.Min(remainingItems, BlockCountLimit)); packet.WriteBytes(BitConverter.GetBytes(blockCount), true); for (uint i = 0; i < blockCount; ++i) { if (!_shapes[itemOffset + i].GetAttributes().Write(packet)) { return(-1); } } progressMarker += blockCount; if (remainingItems > blockCount) { // More to come. return(1); } // All done. return(0); }
/// <summary> /// A helper function for writing as many <see cref="DataMessage"/> messsages as required. /// </summary> /// <param name="routingID">Routing id for the message being composed.</param> /// <param name="objectID">ID of the object to which the data belong.</param> /// <param name="packet">Data packet to compose in.</param> /// <param name="progressMarker">Progress or pagination marker.</param> /// <param name="vertices">Mesh vertex array.</param> /// <param name="normals">Mesh normal array. One per vertex or just a single normal to apply to all vertices.</param> /// <param name="indices">Mesh indices.</param> /// <param name="colours">Per vertex colours. See <see cref="Colour"/> for format details.</param> /// <remarks>Call recursively until zero is returned. Packet does not get finalised here.</remarks> public static int WriteData(ushort routingID, uint objectID, PacketBuffer packet, ref uint progressMarker, Vector3[] vertices, Vector3[] normals, int[] indices, UInt32[] colours) { DataMessage msg = new DataMessage(); // Local byte overhead needs to account for the size of sendType, offset and itemCount. // Use a larger value as I haven't got the edge cases quite right yet. const int localByteOverhead = 100; msg.ObjectID = objectID; packet.Reset(routingID, DataMessage.MessageID); msg.Write(packet); uint offset; uint itemCount; ushort sendType; int verticesLength = (vertices != null) ? vertices.Length : 0; int normalsLength = (normals != null) ? normals.Length : 0; int coloursLength = (colours != null) ? colours.Length : 0; int indicesLength = (indices != null) ? indices.Length : 0; DataPhase[] phases = new DataPhase[] { new DataPhase((normalsLength == 1) ? SendDataType.UniformNormal : SendDataType.Normals, normalsLength, (uint index) => { Vector3 n = normals[index]; packet.WriteBytes(BitConverter.GetBytes(n.X), true); packet.WriteBytes(BitConverter.GetBytes(n.Y), true); packet.WriteBytes(BitConverter.GetBytes(n.Z), true); }, 4, 3), new DataPhase(SendDataType.Colours, coloursLength, (uint index) => { packet.WriteBytes(BitConverter.GetBytes(colours[index]), true); }, 4), new DataPhase(SendDataType.Vertices, verticesLength, (uint index) => { Vector3 v = vertices[index]; packet.WriteBytes(BitConverter.GetBytes(v.X), true); packet.WriteBytes(BitConverter.GetBytes(v.Y), true); packet.WriteBytes(BitConverter.GetBytes(v.Z), true); }, 4, 3), new DataPhase(SendDataType.Indices, indicesLength, (uint index) => { packet.WriteBytes(BitConverter.GetBytes(indices[index]), true); }, 4), }; int phaseIndex = 0; uint previousPhaseOffset = 0u; // While progressMarker is greater than or equal to the sum of the previous phase counts and the current phase count. // Also terminate of out of phases. while (phaseIndex < phases.Length && progressMarker >= previousPhaseOffset + phases[phaseIndex].ItemCount) { previousPhaseOffset += phases[phaseIndex].ItemCount; ++phaseIndex; } bool done = false; // Check if we have anything to send. if (phaseIndex < phases.Length) { DataPhase phase = phases[phaseIndex]; // Send part of current phase. // Estimate element count limit. int maxItemCount = MeshBase.EstimateTransferCount(phase.DataSizeBytes * phase.TupleSize, 0, DataMessage.Size + localByteOverhead); offset = progressMarker - previousPhaseOffset; itemCount = (uint)Math.Min(phase.ItemCount - offset, maxItemCount); sendType = (ushort)((int)phase.Type | (int)SendDataType.ExpectEnd); packet.WriteBytes(BitConverter.GetBytes(sendType), true); packet.WriteBytes(BitConverter.GetBytes(offset), true); packet.WriteBytes(BitConverter.GetBytes(itemCount), true); for (uint i = offset; i < offset + itemCount; ++i) { phase.WriteElement(i); } progressMarker += itemCount; } else { // Either all done or no data to send. // In the latter case, we need to populate the message anyway. offset = itemCount = 0; sendType = (int)SendDataType.ExpectEnd | (int)SendDataType.End; packet.WriteBytes(BitConverter.GetBytes(sendType), true); packet.WriteBytes(BitConverter.GetBytes(offset), true); packet.WriteBytes(BitConverter.GetBytes(itemCount), true); done = true; } // Return 1 while there is more data to process. return((!done) ? 1 : 0); }