public virtual void TesselateShape() { if (!loaded) { return; } shapeFresh = true; CompositeShape compositeShape = OverrideCompositeShape != null ? OverrideCompositeShape : entity.Properties.Client.Shape; Shape entityShape = OverrideEntityShape != null ? OverrideEntityShape : entity.Properties.Client.LoadedShapeForEntity; if (entityShape == null) { return; } OnTesselation?.Invoke(ref entityShape, compositeShape.Base.ToString()); entity.OnTesselation(ref entityShape, compositeShape.Base.ToString()); defaultTexSource = GetTextureSource(); TyronThreadPool.QueueTask(() => { MeshData meshdata; if (entity.Properties.Client.Shape.VoxelizeTexture) { int altTexNumber = entity.WatchedAttributes.GetInt("textureIndex", 0); TextureAtlasPosition pos = defaultTexSource["all"]; CompositeTexture[] Alternates = entity.Properties.Client.FirstTexture.Alternates; CompositeTexture tex = altTexNumber == 0 ? entity.Properties.Client.FirstTexture : Alternates[altTexNumber % Alternates.Length]; meshdata = capi.Tesselator.VoxelizeTexture(tex, capi.EntityTextureAtlas.Size, pos); for (int i = 0; i < meshdata.xyz.Length; i += 3) { meshdata.xyz[i] -= 0.125f; meshdata.xyz[i + 1] -= 0.5f; meshdata.xyz[i + 2] += 0.125f / 2; } } else { try { TesselationMetaData meta = new TesselationMetaData() { quantityElements = compositeShape.QuantityElements, selectiveElements = compositeShape.SelectiveElements, texSource = this, withJointIds = true, withDamageEffect = true, typeForLogging = "entity" }; capi.Tesselator.TesselateShape(meta, entityShape, out meshdata, new Vec3f(compositeShape.rotateX, compositeShape.rotateY, compositeShape.rotateZ)); meshdata.Translate(compositeShape.offsetX, compositeShape.offsetY, compositeShape.offsetZ); } catch (Exception e) { capi.World.Logger.Fatal("Failed tesselating entity {0} with id {1}. Entity will probably be invisible!. The teselator threw {2}", entity.Code, entity.EntityId, e); return; } } MeshData opaqueMesh = meshdata.Clone().Clear(); MeshData oitMesh = meshdata.Clone().Clear(); opaqueMesh.AddMeshData(meshdata, EnumChunkRenderPass.Opaque); oitMesh.AddMeshData(meshdata, EnumChunkRenderPass.Transparent); capi.Event.EnqueueMainThreadTask(() => { if (meshRefOpaque != null) { meshRefOpaque.Dispose(); meshRefOpaque = null; } if (meshRefOit != null) { meshRefOit.Dispose(); meshRefOit = null; } if (capi.IsShuttingDown) { return; } if (opaqueMesh.VerticesCount > 0) { meshRefOpaque = capi.Render.UploadMesh(opaqueMesh); } if (oitMesh.VerticesCount > 0) { meshRefOit = capi.Render.UploadMesh(oitMesh); } }, "uploadentitymesh"); capi.TesselatorManager.ThreadDispose(); }); }
private static MeshRef GenerateMesh(ClientMain game, string meshId, ItemStack stack) { MeshRef meshRef = null; UnloadableShape shape = new UnloadableShape(); if (stack.Item.Shape?.Base != null) { shape.Load(game, new AssetLocationAndSource(stack.Item.Shape.Base)); } if (shape.Textures == null) { shape.Textures = new Dictionary <string, AssetLocation>(); } if (shape.AttachmentPointsByCode == null) { shape.AttachmentPointsByCode = new Dictionary <string, AttachmentPoint>(); } Item item = new Item(); item.Textures = new Dictionary <string, CompositeTexture>(); foreach (ItemstackAttribute attr in stack.Attributes.GetOrAddTreeAttribute("toolparts").Values) { ItemStack partstack = attr.GetValue() as ItemStack; IToolPart part = partstack.Item as IToolPart; if (part != null) { if (part.TinkerProps?.ProvidedTextures == null) { partstack.Item.Textures.ToList().ForEach(kp => { shape.Textures[kp.Key] = kp.Value.Base; item.Textures[kp.Key] = kp.Value; }); UnloadableShape tmp = new UnloadableShape(); if (!tmp.Load(game, new AssetLocationAndSource(partstack.Item.Shape.Base))) { continue; } ShapeElement slot = shape.GetElementByName(part.TinkerProps.PartType); if (slot != null) { slot.Children = slot.Children.Concat(tmp.CloneElements()[0].Children).ToArray(); } if (tmp.AttachmentPointsByCode != null) { tmp.AttachmentPointsByCode.ToList().ForEach(kp => shape.AttachmentPointsByCode[kp.Key] = kp.Value); } } else { part.TinkerProps.ProvidedTextures.ToList().ForEach(kp => { shape.Textures[kp.Key] = kp.Value; item.Textures[kp.Key] = new CompositeTexture() { Base = kp.Value.Clone() }; }); } } } ShapeTesselatorManager manager = game.GetType().GetField("TesselatorManager", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(game) as ShapeTesselatorManager; ItemTextureAtlasManager blockAtlas = game.GetType().GetField("ItemAtlasManager", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(game) as ItemTextureAtlasManager; ClientPlatformAbstract platform = game.GetType().GetField("Platform", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(game) as ClientPlatformAbstract; if (manager != null && blockAtlas != null && platform != null) { TextureSource source = new TextureSource(game, blockAtlas.Size, item); var field = manager.Tesselator.GetType().GetField("meta", BindingFlags.Instance | BindingFlags.NonPublic); var oldMeta = field.GetValue(manager.Tesselator) as TesselationMetaData; TesselationMetaData meta = oldMeta.Clone(); meta.texSource = source; meta.withJointIds = false; MeshData meshData; manager.TLTesselator.Value.TesselateShape((Shape)shape, out meshData, new Vec3f(), new Vec3f(), meta); meshRef = platform.UploadMesh(meshData); MeshRefs[meshId] = new AccessLifetime <MeshRef>(meshRef); } return(meshRef); }