ModelEditor - Add material render support

This commit is contained in:
miku-666
2024-11-11 17:53:24 +01:00
parent b4ca5ad810
commit e5f4f39a18
6 changed files with 105 additions and 21 deletions

View File

@@ -15,6 +15,7 @@ using PckStudio.Interfaces;
using PckStudio.Internal.Json;
using PckStudio.Internal.App;
using PckStudio.Extensions;
using OMI.Formats.Material;
namespace PckStudio.Forms.Editor
{
@@ -22,13 +23,14 @@ namespace PckStudio.Forms.Editor
{
private readonly ModelContainer _models;
private readonly ITryGetSet<string, Image> _textures;
private readonly ITryGet<string, MaterialContainer.Material> _tryGetEntityMaterial;
public ModelEditor(ModelContainer models, TryGetDelegate<string, Image> tryGetTexture, TrySetDelegate<string, Image> trySetTexture)
public ModelEditor(ModelContainer models, ITryGetSet<string, Image> tryGetSetTextures, ITryGet<string, MaterialContainer.Material> tryGetEntityMaterial)
{
InitializeComponent();
_models = models;
_textures = TryGetSet<string, Image>.FromDelegates(tryGetTexture, trySetTexture);
_textures = tryGetSetTextures;
_tryGetEntityMaterial = tryGetEntityMaterial;
modelTreeView.ImageList = new ImageList
{
ColorDepth = ColorDepth.Depth32Bit,
@@ -240,6 +242,12 @@ namespace PckStudio.Forms.Editor
modelViewport.Texture = textures[0].Texture;
modelViewport.LoadModel(modelNode.Model);
if (GameModelImporter.ModelMetaData.TryGetValue(modelNode.Model.Name, out JsonModelMetaData modelMetaData) && !string.IsNullOrEmpty(modelMetaData.MaterialName) &&
_tryGetEntityMaterial.TryGet(modelMetaData.MaterialName, out MaterialContainer.Material entityMaterial) ||
_tryGetEntityMaterial.TryGet(modelNode.Model.Name, out entityMaterial))
{
modelViewport.SetModelMaterial(entityMaterial);
}
modelViewport.ResetCamera();
}
if (e.Node is ModelPartNode modelPartNode && modelPartNode.Parent is ModelNode parentNode && modelViewport.CurrentModelName == parentNode.Model.Name)

View File

@@ -24,6 +24,9 @@ namespace PckStudio.Internal.Json
[JsonProperty("textureLocations", Required = Required.Always)]
public string[] TextureLocations { get; set; }
[JsonProperty("materialName", NullValueHandling = NullValueHandling.Ignore)]
public string MaterialName { get; set; } = string.Empty;
[JsonProperty("parts", NullValueHandling = NullValueHandling.Ignore)]
public ModelMetaDataPart[] RootParts { get; set; } = Array.Empty<ModelMetaDataPart>();
}

View File

@@ -41,6 +41,7 @@ using PckStudio.Internal.Serializer;
using PckStudio.Internal.App;
using PckStudio.Internal.Skin;
using PckStudio.Interfaces;
using System.Collections.ObjectModel;
namespace PckStudio
{
@@ -621,7 +622,24 @@ namespace PckStudio
return true;
};
var editor = new ModelEditor(modelContainer, tryGetTexture, trySetTexture);
bool hasMaterialAsset = currentPCK.TryGetAsset("entityMaterials.bin", PckAssetType.MaterialFile, out PckAsset entityMaterialAsset);
IReadOnlyDictionary<string, MaterialContainer.Material> entityMaterials =
hasMaterialAsset
? entityMaterialAsset?.GetData(new MaterialFileReader()).ToDictionary(mat => mat.Name)
: new Dictionary<string, MaterialContainer.Material>();
TryGetDelegate<string, MaterialContainer.Material> tryGetEntityMaterial = (string materialName, out MaterialContainer.Material materialInfo) =>
{
if (entityMaterials.TryGetValue(materialName, out MaterialContainer.Material material))
{
materialInfo = material;
return true;
}
materialInfo = default;
return false;
};
var editor = new ModelEditor(modelContainer, TryGetSet<string, Image>.FromDelegates(tryGetTexture, trySetTexture), TryGet<string, MaterialContainer.Material>.FromDelegate(tryGetEntityMaterial));
if (editor.ShowDialog() == DialogResult.OK)
{
return;

View File

@@ -66,7 +66,7 @@ namespace PckStudio.Rendering
Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(Rotation.Z))
);
Matrix4 translation = Matrix4.CreateTranslation(Translation + Offset);
return translation * (rotations).Pivoted(Pivot - Offset);
return translation * rotations.Pivoted(Pivot - Offset);
}
public int Count => cubes.Count;

View File

@@ -7,6 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OMI.Formats.Material;
using OMI.Formats.Model;
using OpenTK;
using OpenTK.Graphics.OpenGL;
@@ -147,6 +148,10 @@ namespace PckStudio.Rendering
ShaderProgram shader = GetShader("CubeShader");
shader.Bind();
shader.SetUniform2("TexSize", model.TextureSize);
// Reset "Material"
GL.Disable(EnableCap.AlphaTest);
GL.BlendFunc(BlendingFactor.One, BlendingFactor.Zero);
}
_currentModelName = model.Name;
}
@@ -266,5 +271,34 @@ namespace PckStudio.Rendering
{
_highlightingInfo = HighlightInfo.Empty;
}
internal void SetModelMaterial(MaterialContainer.Material entityMaterial)
{
if (entityMaterial is null)
return;
switch (entityMaterial.Type)
{
// todo
//case "entity":
// break;
//case "entity_change_color":
// break;
case "entity_alphatest":
GL.Enable(EnableCap.AlphaTest);
break;
case "entity_alphatest_change_color":
GL.Enable(EnableCap.AlphaTest);
goto default;
case "entity_emissive_alpha":
GL.BlendFunc(BlendingFactor.One, BlendingFactor.Zero);
break;
case "entity_emissive_alpha_only":
GL.BlendFuncSeparate(BlendingFactorSrc.One, BlendingFactorDest.One, BlendingFactorSrc.One, BlendingFactorDest.Zero);
break;
default:
Debug.WriteLine($"[{nameof(ModelRenderer)}@{nameof(SetModelMaterial)}]: Unhandled entity material(type: {entityMaterial.Type})");
break;
}
}
}
}

View File

@@ -3,6 +3,7 @@
"textureLocations": [
"res/mob/bat"
],
"materialName": "bat",
"parts": [
{
"name": "head",
@@ -38,7 +39,8 @@
"blaze": {
"textureLocations": [
"res/mob/fire"
]
],
"materialName": "blaze_head"
},
"boat": {
"textureLocations": [
@@ -97,6 +99,7 @@
"textureLocations": [
"res/mob/enderdragon/ender"
],
"materialName": "ender_dragon",
"parts": [
{ "name": "body" },
// only needs to be inside when neck 1-5 aren't present
@@ -186,19 +189,22 @@
"enderman": {
"textureLocations": [
"res/mob/enderman"
]
],
"materialName": "enderman" // "enderman_invisible" also valid
},
"ghast": {
"textureLocations": [
"res/mob/ghast",
"res/mob/ghast_fire"
]
],
"materialName": "ghast"
},
"guardian": {
"textureLocations": [
"res/mob/guardian",
"res/mob/guardian_elder"
],
"materialName": "guardian",
"parts": [
{
"name": "head",
@@ -220,12 +226,14 @@
"irongolem": {
"textureLocations": [
"res/mob/villager_golem"
]
],
"materialName": "iron_golem"
},
"lavaslime": {
"textureLocations": [
"res/mob/lava"
]
],
"materialName": "magma_cube"
},
"llama": {
"textureLocations": [
@@ -282,6 +290,7 @@
"textureLocations": [
"res/mob/phantom"
],
"materialName": "phantom", // phantom_invisible is also valid
"parts": [
{
"name": "body",
@@ -312,7 +321,8 @@
"pigzombie": {
"textureLocations": [
"res/mob/pigzombie"
]
],
"materialName": "zombie_pigman"
},
"polarbear": {
"textureLocations": [
@@ -333,19 +343,23 @@
},
"sheep": {
"textureLocations": [
"res/mob/sheep",
"res/mob/sheep_fur"
]
],
"materialName": "sheep"
},
"sheep.sheared": {
"textureLocations": [
"res/mob/sheep"
]
],
"materialName": "sheep"
},
"shulker": {
"textureLocations": [
"res/mob/shulker/endergolem",
"res/mob/shulker/spark"
]
],
"materialName": "shulker"
},
"silverfish": {
"textureLocations": [
@@ -355,17 +369,20 @@
"skeleton": {
"textureLocations": [
"res/mob/skeleton"
]
],
"materialName": "skeleton"
},
"skeleton.stray": {
"textureLocations": [
"res/mob/skeleton/stray"
]
],
"materialName": "stray"
},
"skeleton.wither": {
"textureLocations": [
"res/mob/skeleton_wither"
]
],
"materialName": "wither_skeleton"
},
"slime": {
"textureLocations": [
@@ -386,7 +403,8 @@
"textureLocations": [
"res/mob/spider",
"res/mob/cavespider"
]
],
"materialName": "spider" // "spider_invisible" also valid
},
"squid": {
"textureLocations": [
@@ -438,14 +456,16 @@
"textureLocations": [
"res/mob/wither/wither",
"res/mob/wither/wither_invulnerable"
]
],
"materialName": "wither_boss"
},
"wolf": {
"textureLocations": [
"res/mob/wolf",
"res/mob/wolf_angry",
"res/mob/wolf_tame"
]
],
"materialName": "wolf"
},
"zombie": {
"textureLocations": [
@@ -529,7 +549,8 @@
"zombie.drowned": {
"textureLocations": [
"res/mob/zombie/drowned"
]
],
"materialName": "drowned"
},
"endermite": {
"textureLocations": [