public bool IsSame(TextureEntryFace face) => TextureColor == face.TextureColor && RepeatU == face.RepeatU && RepeatV == face.RepeatV && OffsetU == face.OffsetU && OffsetV == face.OffsetV && Rotation == face.Rotation && Glow == face.Glow && Material == face.Material && Media == face.Media && TextureID == face.TextureID && MaterialID == face.MaterialID;
public TextureEntry(TextureEntry src) { DefaultTexture = new TextureEntryFace(src.DefaultTexture); for (int i = 0; i < MAX_TEXTURE_FACES; ++i) { TextureEntryFace face = src.m_FaceTextures[i]; if (face != null) { m_FaceTextures[i] = new TextureEntryFace(face); } } }
internal TextureEntryFace(TextureEntryFace src) { if (src == null) { throw new ArgumentNullException(nameof(src)); } TextureColor = new ColorAlpha(src.TextureColor); RepeatU = src.RepeatU; RepeatV = src.RepeatV; OffsetU = src.OffsetU; OffsetV = src.OffsetV; Rotation = src.Rotation; Glow = src.Glow; Material = src.Material; Media = src.Media; TextureID = src.TextureID; MaterialID = src.MaterialID; }
public bool TryGetValue(uint index, out TextureEntryFace face) { face = default(TextureEntryFace); if (index >= MAX_TEXTURE_FACES) { return(false); } lock (m_Lock) { if (m_FaceTextures[index] == null) { return(false); } } face = m_FaceTextures[index]; return(true); }
public TextureEntryFace this[uint index] { get { if (index >= MAX_TEXTURE_FACES) { throw new KeyNotFoundException(index.ToString()); } lock (m_Lock) { if (m_FaceTextures[index] == null) { m_FaceTextures[index] = new TextureEntryFace(DefaultTexture); } } return(m_FaceTextures[index]); } }
public void OptimizeDefault(int optimizeForNumfaces) { if (DefaultTexture == null) { return; } var textureCounts = new Dictionary <UUID, int>(); var repeatUCounts = new Dictionary <float, int>(); var repeatVCounts = new Dictionary <float, int>(); var offsetUCounts = new Dictionary <short, int>(); var offsetVCounts = new Dictionary <short, int>(); var rotationCounts = new Dictionary <short, int>(); var glowCounts = new Dictionary <byte, int>(); var materialCounts = new Dictionary <byte, int>(); var mediaCounts = new Dictionary <byte, int>(); var materialIDCounts = new Dictionary <UUID, int>(); var textureColorCounts = new Dictionary <ColorAlpha, int>(); TextureEntryFace lazyDefaultCopy = null; for (int i = MAX_TEXTURE_FACES; i-- > optimizeForNumfaces;) { m_FaceTextures[i] = null; } for (int i = optimizeForNumfaces; i-- != 0;) { int cnt; TextureEntryFace face = m_FaceTextures[(uint)i]; if (face == null) { if (lazyDefaultCopy == null) { lazyDefaultCopy = new TextureEntryFace(DefaultTexture); } m_FaceTextures[(uint)i] = lazyDefaultCopy; face = lazyDefaultCopy; } UUID textureID = face.TextureID; textureCounts.TryGetValue(textureID, out cnt); textureCounts[textureID] = cnt + 1; float repeatU = face.RepeatU; repeatUCounts.TryGetValue(repeatU, out cnt); repeatUCounts[repeatU] = cnt + 1; float repeatV = face.RepeatV; repeatVCounts.TryGetValue(repeatV, out cnt); repeatVCounts[repeatV] = cnt + 1; short offsetu = TEOffsetShort(face.OffsetU); face.OffsetU = TEOffsetFloat(offsetu); offsetUCounts.TryGetValue(offsetu, out cnt); offsetUCounts[offsetu] = cnt + 1; short offsetv = TEOffsetShort(face.OffsetV); face.OffsetV = TEOffsetFloat(offsetv); offsetVCounts.TryGetValue(offsetv, out cnt); offsetVCounts[offsetv] = cnt + 1; short rotation = TERotationShort(face.Rotation); face.Rotation = TERotationFloat(rotation); rotationCounts.TryGetValue(rotation, out cnt); rotationCounts[rotation] = cnt + 1; byte glow = TEGlowByte(face.Glow); face.Glow = TEGlowFloat(glow); glowCounts.TryGetValue(glow, out cnt); glowCounts[glow] = cnt + 1; byte material = face.Material; materialCounts.TryGetValue(material, out cnt); materialCounts[material] = cnt + 1; byte media = face.Media; mediaCounts.TryGetValue(media, out cnt); mediaCounts[media] = cnt + 1; UUID materialID = face.MaterialID; materialIDCounts.TryGetValue(materialID, out cnt); materialIDCounts[materialID] = cnt + 1; ColorAlpha color = face.TextureColor; textureColorCounts.TryGetValue(color, out cnt); textureColorCounts[color] = cnt + 1; } if (textureColorCounts.Count > 0) { DefaultTexture.TextureColor = textureColorCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key; } if (textureCounts.Count > 0) { DefaultTexture.TextureID = textureCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key; } if (repeatUCounts.Count > 0) { DefaultTexture.RepeatU = repeatUCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key; } if (repeatVCounts.Count > 0) { DefaultTexture.RepeatV = repeatVCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key; } if (offsetUCounts.Count > 0) { DefaultTexture.OffsetU = TEOffsetFloat(offsetUCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key); } if (offsetVCounts.Count > 0) { DefaultTexture.OffsetV = TEOffsetFloat(offsetVCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key); } if (rotationCounts.Count > 0) { DefaultTexture.Rotation = TERotationFloat(rotationCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key); } if (glowCounts.Count > 0) { DefaultTexture.Glow = TEGlowFloat(glowCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key); } if (materialCounts.Count > 0) { DefaultTexture.Material = materialCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key; } if (mediaCounts.Count > 0) { DefaultTexture.Media = mediaCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key; } if (materialIDCounts.Count > 0) { DefaultTexture.MaterialID = materialIDCounts.Aggregate((l, r) => l.Value > r.Value ? l : r).Key; } bool firstLazyCopy = true; for (int i = MAX_TEXTURE_FACES; i-- != 0;) { TextureEntryFace face = m_FaceTextures[i]; if (face == null) { continue; } if (face.IsSame(DefaultTexture)) { m_FaceTextures[i] = null; } else if (lazyDefaultCopy == face) { /* ensure that we have non-shared objects */ if (!firstLazyCopy) { m_FaceTextures[i] = new TextureEntryFace(lazyDefaultCopy); } firstLazyCopy = false; } } }
public byte[] GetBytes(bool fullbrightdisable = false, float glowintensitylimit = 1.0f) { if (DefaultTexture == null) { return(new byte[0]); } using (var memStream = new MemoryStream()) { using (var binWriter = new BinaryWriter(memStream)) { #region Bitfield Setup ulong textures = 0; ulong texturecolors = 0; ulong repeatus = 0; ulong repeatvs = 0; ulong offsetus = 0; ulong offsetvs = 0; ulong rotations = 0; ulong materials = 0; ulong medias = 0; ulong glows = 0; ulong materialIDs = 0; ulong mask; int i; int j; ulong mask2; byte fbright_mask = (byte)~(fullbrightdisable ? FULLBRIGHT_MASK : 0); for (i = MAX_TEXTURE_FACES, mask = (ulong)1 << (MAX_TEXTURE_FACES - 1); i-- != 0; mask >>= 1) { TextureEntryFace face = m_FaceTextures[i]; if (face == null) { continue; } if (face.TextureID != DefaultTexture.TextureID) { textures |= mask; } if (face.TextureColor != DefaultTexture.TextureColor) { texturecolors |= mask; } if (face.RepeatU != DefaultTexture.RepeatU) { repeatus |= mask; } if (face.RepeatV != DefaultTexture.RepeatV) { repeatvs |= mask; } if (TEOffsetShort(face.OffsetU) != TEOffsetShort(DefaultTexture.OffsetU)) { offsetus |= mask; } if (TEOffsetShort(face.OffsetV) != TEOffsetShort(DefaultTexture.OffsetV)) { offsetvs |= mask; } if (TERotationShort(face.Rotation) != TERotationShort(DefaultTexture.Rotation)) { rotations |= mask; } if ((face.Material & fbright_mask) != (DefaultTexture.Material & fbright_mask)) { materials |= mask; } if (face.Media != DefaultTexture.Media) { medias |= mask; } if (TEGlowByte(Math.Min(glowintensitylimit, face.Glow)) != TEGlowByte(Math.Min(glowintensitylimit, DefaultTexture.Glow))) { glows |= mask; } if (face.MaterialID != DefaultTexture.MaterialID) { materialIDs |= mask; } } #endregion Bitfield Setup #region Texture binWriter.Write(DefaultTexture.TextureID.GetBytes()); for (i = 0, mask = 1; textures != 0; i++, mask <<= 1) { if ((textures & mask) == 0) { continue; } ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= textures; j++, mask2 <<= 1) { if ((textures & mask2) == 0) { continue; } if (m_FaceTextures[j].TextureID == m_FaceTextures[i].TextureID) { finalmask |= mask2; } } textures &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write(m_FaceTextures[i].TextureID.GetBytes()); } binWriter.Write((byte)0); #endregion Texture #region Color // Serialize the color bytes inverted to optimize for zerocoding binWriter.Write(ColorToBytes(DefaultTexture.TextureColor)); for (i = 0, mask = 1; texturecolors != 0; i++, mask <<= 1) { if ((texturecolors & mask) == 0) { continue; } ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= texturecolors; j++, mask2 <<= 1) { if ((texturecolors & mask2) == 0) { continue; } if (m_FaceTextures[j].TextureColor == m_FaceTextures[i].TextureColor) { finalmask |= mask2; } } texturecolors &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); // Serialize the color bytes inverted to optimize for zerocoding binWriter.Write(ColorToBytes(m_FaceTextures[i].TextureColor)); } binWriter.Write((byte)0); #endregion Color #region RepeatU binWriter.Write(DefaultTexture.RepeatU); for (i = 0, mask = 1; repeatus != 0; i++, mask <<= 1) { if ((repeatus & mask) == 0) { continue; } float repeatu = m_FaceTextures[i].RepeatU; ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= repeatus; j++, mask2 <<= 1) { if ((repeatus & mask2) == 0) { continue; } if (m_FaceTextures[j].RepeatU == repeatu) { finalmask |= mask2; } } repeatus &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write(FloatToBytes(repeatu)); } binWriter.Write((byte)0); #endregion RepeatU #region RepeatV binWriter.Write(DefaultTexture.RepeatV); for (i = 0, mask = 1; repeatvs != 0; i++, mask <<= 1) { if ((repeatvs & mask) == 0) { continue; } float repeatv = m_FaceTextures[i].RepeatV; ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= repeatvs; j++, mask2 <<= 1) { if ((repeatvs & mask2) == 0) { continue; } if (m_FaceTextures[j].RepeatV == repeatv) { finalmask |= mask2; } } repeatvs &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write(FloatToBytes(repeatv)); } binWriter.Write((byte)0); #endregion RepeatV #region OffsetU binWriter.Write(TEOffsetShort(DefaultTexture.OffsetU)); for (i = 0, mask = 1; offsetus != 0; i++, mask <<= 1) { short offsetudata; if ((offsetus & mask) == 0) { continue; } offsetudata = TEOffsetShort(m_FaceTextures[i].OffsetU); ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= offsetus; j++, mask2 <<= 1) { if ((offsetus & mask2) == 0) { continue; } if (TEOffsetShort(m_FaceTextures[j].OffsetU) == offsetudata) { finalmask |= mask2; } } offsetus &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write(offsetudata); } binWriter.Write((byte)0); #endregion OffsetU #region OffsetV binWriter.Write(TEOffsetShort(DefaultTexture.OffsetV)); for (i = 0, mask = 1; offsetvs != 0; i++, mask <<= 1) { short offsetvdata; if ((offsetvs & mask) == 0) { continue; } offsetvdata = TEOffsetShort(m_FaceTextures[i].OffsetV); ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= offsetvs; j++, mask2 <<= 1) { if ((offsetvs & mask2) == 0) { continue; } if (TEOffsetShort(m_FaceTextures[j].OffsetV) == offsetvdata) { finalmask |= mask2; } } offsetvs &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write(offsetvdata); } binWriter.Write((byte)0); #endregion OffsetV #region Rotation binWriter.Write(TERotationShort(DefaultTexture.Rotation)); for (i = 0, mask = 1; rotations != 0; i++, mask <<= 1) { short rotationdata; if ((rotations & mask) == 0) { continue; } rotationdata = TERotationShort(m_FaceTextures[i].Rotation); ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= rotations; j++, mask2 <<= 1) { if ((rotations & mask2) == 0) { continue; } if (TERotationShort(m_FaceTextures[j].Rotation) == rotationdata) { finalmask |= mask2; } } rotations &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write(rotationdata); } binWriter.Write((byte)0); #endregion Rotation #region Material binWriter.Write((byte)(DefaultTexture.Material & fbright_mask)); for (i = 0, mask = 1; materials != 0; i++, mask <<= 1) { if ((materials & mask) == 0) { continue; } ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= materials; j++, mask2 <<= 1) { if ((materials & mask2) == 0) { continue; } if (m_FaceTextures[j].Material == m_FaceTextures[i].Material) { finalmask |= mask2; } } materials &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write((byte)(m_FaceTextures[i].Material & fbright_mask)); } binWriter.Write((byte)0); #endregion Material #region Media binWriter.Write(DefaultTexture.Media); for (i = 0, mask = 1; medias != 0; i++, mask <<= 1) { if ((medias & mask) == 0) { continue; } ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= medias; j++, mask2 <<= 1) { if ((medias & mask2) == 0) { continue; } if (m_FaceTextures[j].Media == m_FaceTextures[i].Media) { finalmask |= mask2; } } medias &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write(m_FaceTextures[i].Media); } binWriter.Write((byte)0); #endregion Media #region Glow binWriter.Write(TEGlowByte(Math.Min(glowintensitylimit, DefaultTexture.Glow))); for (i = 0, mask = 1; glows != 0; i++, mask <<= 1) { byte glowbyte; if ((glows & mask) == 0) { continue; } glowbyte = TEGlowByte(Math.Min(glowintensitylimit, m_FaceTextures[i].Glow)); ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= glows; j++, mask2 <<= 1) { if ((glows & mask2) == 0) { continue; } if (TEGlowByte(Math.Min(glowintensitylimit, m_FaceTextures[j].Glow)) == glowbyte) { finalmask |= mask2; } } glows &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write(glowbyte); } binWriter.Write((byte)0); #endregion Glow #region MaterialID binWriter.Write(DefaultTexture.MaterialID.GetBytes()); for (i = 0, mask = 1; 0 != materialIDs; i++, mask <<= 1) { if ((materialIDs & mask) == 0) { continue; } ulong finalmask = mask; for (j = i + 1, mask2 = mask << 1; j < MAX_TEXTURE_FACES && mask2 <= materialIDs; j++, mask2 <<= 1) { if ((materialIDs & mask2) == 0) { continue; } if (m_FaceTextures[j].MaterialID == m_FaceTextures[i].MaterialID) { finalmask |= mask2; } } materialIDs &= ~finalmask; binWriter.Write(GetFaceBitfieldBytes(finalmask)); binWriter.Write(m_FaceTextures[i].MaterialID.GetBytes()); } binWriter.Write((byte)0); #endregion MaterialID return(memStream.ToArray()); } } }
public TextureEntry() { DefaultTexture = new TextureEntryFace(); }
private void FromBytes(byte[] data, int pos, int length) { DefaultTexture = new TextureEntryFace(); if (length < 16) { for (int idx = m_FaceTextures.Length; idx-- != 0;) { m_FaceTextures[idx] = null; } return; } uint bitfieldSize = 0; ulong faceBits = 0; int i = pos; #region Texture DefaultTexture.TextureID = new UUID(data, i); i += 16; while (ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { var tmpUUID = new UUID(data, i); i += 16; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].TextureID = tmpUUID; } } } #endregion Texture #region Color DefaultTexture.TextureColor = ColorFromBytes(data, i); i += 4; while (ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { var tmpColor = ColorFromBytes(data, i); i += 4; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].TextureColor = tmpColor; } } } #endregion Color #region RepeatU DefaultTexture.RepeatU = BytesToFloat(data, i); i += 4; while (ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { float tmpFloat = BytesToFloat(data, i); i += 4; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].RepeatU = tmpFloat; } } } #endregion RepeatU #region RepeatV DefaultTexture.RepeatV = BytesToFloat(data, i); i += 4; while (ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { float tmpFloat = BytesToFloat(data, i); i += 4; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].RepeatV = tmpFloat; } } } #endregion RepeatV #region OffsetU DefaultTexture.OffsetU = TEOffsetFloat(data, i); i += 2; while (ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { float tmpFloat = TEOffsetFloat(data, i); i += 2; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].OffsetU = tmpFloat; } } } #endregion OffsetU #region OffsetV DefaultTexture.OffsetV = TEOffsetFloat(data, i); i += 2; while (ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { float tmpFloat = TEOffsetFloat(data, i); i += 2; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].OffsetV = tmpFloat; } } } #endregion OffsetV #region Rotation DefaultTexture.Rotation = TERotationFloat(data, i); i += 2; while (ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { float tmpFloat = TERotationFloat(data, i); i += 2; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].Rotation = tmpFloat; } } } #endregion Rotation #region Material DefaultTexture.Material = data[i]; i++; while (ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { byte tmpByte = data[i]; i++; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].Material = tmpByte; } } } #endregion Material #region Media DefaultTexture.Media = data[i]; i++; while (i - pos < length && ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { byte tmpByte = data[i]; i++; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].Media = tmpByte; } } } #endregion Media #region Glow DefaultTexture.Glow = TEGlowFloat(data, i); i++; while (ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { float tmpFloat = TEGlowFloat(data, i); i++; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].Glow = tmpFloat; } } } #endregion Glow #region MaterialID if (i - pos + 16 <= length) { DefaultTexture.MaterialID = new UUID(data, i); i += 16; while (i - pos + 16 <= length && ReadFaceBitfield(data, ref i, ref faceBits, ref bitfieldSize)) { var tmpUUID = new UUID(data, i); i += 16; for (uint face = 0, bit = 1; face < bitfieldSize; face++, bit <<= 1) { if ((faceBits & bit) != 0) { this[face].MaterialID = tmpUUID; } } } } #endregion MaterialID }