mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 14:31:50 +00:00
Added support for SurfaceSkin MODELDEF property.
Changed, Visual mode: increased maximum rendreable dynamic lights count to 64.
This commit is contained in:
parent
68c5ed1747
commit
3f93525ebc
7 changed files with 143 additions and 39 deletions
|
@ -3210,7 +3210,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Load the skysphere model...
|
||||
BoundingBoxSizes bbs = new BoundingBoxSizes();
|
||||
Stream modeldata = General.ThisAssembly.GetManifestResourceStream("CodeImp.DoomBuilder.Resources.SkySphere.md3");
|
||||
ModelReader.MD3LoadResult meshes = ModelReader.ReadMD3Model(ref bbs, true, modeldata, device, 0);
|
||||
ModelReader.MD3LoadResult meshes = ModelReader.ReadMD3Model(ref bbs, new Dictionary<int, string>(), modeldata, device, 0);
|
||||
if(meshes.Meshes.Count != 3) throw new Exception("Skybox creation failed: "
|
||||
+ (string.IsNullOrEmpty(meshes.Errors) ? "skybox model must contain 3 surfaces" : meshes.Errors));
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
#region ================== Properties
|
||||
|
||||
internal List<string> ModelNames;
|
||||
internal List<string> TextureNames;
|
||||
internal List<string> SkinNames;
|
||||
internal List<Dictionary<int, string>> SurfaceSkinNames;
|
||||
internal List<string> FrameNames;
|
||||
internal List<int> FrameIndices;
|
||||
|
||||
|
@ -62,7 +63,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
internal ModelData()
|
||||
{
|
||||
ModelNames = new List<string>();
|
||||
TextureNames = new List<string>();
|
||||
SkinNames = new List<string>();
|
||||
SurfaceSkinNames = new List<Dictionary<int, string>>();
|
||||
FrameNames = new List<string>();
|
||||
FrameIndices = new List<int>();
|
||||
transform = Matrix.Identity;
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
}
|
||||
|
||||
//clear unneeded data
|
||||
mde.TextureNames = null;
|
||||
mde.SkinNames = null;
|
||||
mde.ModelNames = null;
|
||||
|
||||
if(mde.Model.Meshes == null || mde.Model.Meshes.Count == 0)
|
||||
|
@ -95,10 +95,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
//load models and textures
|
||||
for(int i = 0; i < mde.ModelNames.Count; i++)
|
||||
{
|
||||
//need to use model skins?
|
||||
bool useSkins = string.IsNullOrEmpty(mde.TextureNames[i]);
|
||||
// Use model skins?
|
||||
// INFO: Skin MODELDEF property overrides both embedded surface names and ones set using SurfaceSkin MODELDEF property
|
||||
Dictionary<int, string> skins = null;
|
||||
if(string.IsNullOrEmpty(mde.SkinNames[i]))
|
||||
{
|
||||
skins = (mde.SurfaceSkinNames[i].Count > 0 ? mde.SurfaceSkinNames[i] : new Dictionary<int, string>());
|
||||
}
|
||||
|
||||
//load mesh
|
||||
// Load mesh
|
||||
MemoryStream ms = LoadFile(containers, mde.ModelNames[i], true);
|
||||
if(ms == null)
|
||||
{
|
||||
|
@ -115,7 +120,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
General.ErrorLogger.Add(ErrorType.Error, "Error while loading \"" + mde.ModelNames[i] + "\": frame names are not supported for MD3 models!");
|
||||
continue;
|
||||
}
|
||||
result = ReadMD3Model(ref bbs, useSkins, ms, device, mde.FrameIndices[i]);
|
||||
result = ReadMD3Model(ref bbs, skins, ms, device, mde.FrameIndices[i]);
|
||||
break;
|
||||
case ".md2":
|
||||
result = ReadMD2Model(ref bbs, ms, device, mde.FrameIndices[i], mde.FrameNames[i]);
|
||||
|
@ -145,7 +150,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
List<string> errors = new List<string>();
|
||||
|
||||
// Texture not defined in MODELDEF?
|
||||
if(useSkins)
|
||||
if(skins != null)
|
||||
{
|
||||
//try to use model's own skins
|
||||
for(int m = 0; m < result.Meshes.Count; m++)
|
||||
|
@ -169,7 +174,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
//relative path?
|
||||
if(path.IndexOf(Path.DirectorySeparatorChar) == -1)
|
||||
path = Path.Combine(Path.GetDirectoryName(mde.ModelNames[useSkins ? i : m]), path);
|
||||
path = Path.Combine(Path.GetDirectoryName(mde.ModelNames[i]), path);
|
||||
|
||||
Texture t = LoadTexture(containers, path, device);
|
||||
|
||||
|
@ -186,11 +191,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
//Try to use texture loaded from MODELDEFS
|
||||
else
|
||||
{
|
||||
Texture t = LoadTexture(containers, mde.TextureNames[i], device);
|
||||
Texture t = LoadTexture(containers, mde.SkinNames[i], device);
|
||||
if(t == null)
|
||||
{
|
||||
mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture);
|
||||
errors.Add("unable to load texture \"" + mde.TextureNames[i] + "\"");
|
||||
errors.Add("unable to load texture \"" + mde.SkinNames[i] + "\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -208,7 +213,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
}
|
||||
|
||||
//clear unneeded data
|
||||
mde.TextureNames = null;
|
||||
mde.SkinNames = null;
|
||||
mde.ModelNames = null;
|
||||
|
||||
if(mde.Model.Meshes == null || mde.Model.Meshes.Count == 0)
|
||||
|
@ -231,7 +236,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
#region ================== MD3
|
||||
|
||||
internal static MD3LoadResult ReadMD3Model(ref BoundingBoxSizes bbs, bool useSkins, Stream s, Device device, int frame)
|
||||
internal static MD3LoadResult ReadMD3Model(ref BoundingBoxSizes bbs, Dictionary<int, string> skins, Stream s, Device device, int frame)
|
||||
{
|
||||
long start = s.Position;
|
||||
MD3LoadResult result = new MD3LoadResult();
|
||||
|
@ -265,6 +270,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
Dictionary<string, List<List<int>>> polyIndecesListsPerTexture = new Dictionary<string, List<List<int>>>(StringComparer.Ordinal);
|
||||
Dictionary<string, List<WorldVertex>> vertListsPerTexture = new Dictionary<string, List<WorldVertex>>(StringComparer.Ordinal);
|
||||
Dictionary<string, List<int>> vertexOffsets = new Dictionary<string, List<int>>(StringComparer.Ordinal);
|
||||
bool useskins = false;
|
||||
|
||||
for(int c = 0; c < numSurfaces; c++)
|
||||
{
|
||||
|
@ -277,8 +283,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
return result;
|
||||
}
|
||||
|
||||
if(useSkins)
|
||||
// Pick a skin to use
|
||||
if(skins == null)
|
||||
{
|
||||
// skins is null when Skin MODELDEF property is set
|
||||
skin = string.Empty;
|
||||
}
|
||||
else if(skins.ContainsKey(c))
|
||||
{
|
||||
// Overrtide surface skin with SurfaceSkin MODELDEF property
|
||||
skin = skins[c];
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(skin))
|
||||
{
|
||||
useskins = true;
|
||||
|
||||
if(polyIndecesListsPerTexture.ContainsKey(skin))
|
||||
{
|
||||
polyIndecesListsPerTexture[skin].Add(polyIndecesList);
|
||||
|
@ -298,8 +318,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
}
|
||||
}
|
||||
|
||||
if(!useSkins)
|
||||
{
|
||||
if(!useskins)
|
||||
{
|
||||
//create mesh
|
||||
CreateMesh(device, ref result, vertList, polyIndecesList);
|
||||
result.Skins.Add("");
|
||||
|
|
19
Source/Core/Windows/PreferencesForm.Designer.cs
generated
19
Source/Core/Windows/PreferencesForm.Designer.cs
generated
|
@ -602,7 +602,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// label1
|
||||
//
|
||||
label1.AutoSize = true;
|
||||
label1.Location = new System.Drawing.Point(41, 171);
|
||||
label1.Location = new System.Drawing.Point(43, 171);
|
||||
label1.Name = "label1";
|
||||
label1.Size = new System.Drawing.Size(145, 13);
|
||||
label1.TabIndex = 20;
|
||||
|
@ -612,11 +612,11 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// label18
|
||||
//
|
||||
label18.AutoSize = true;
|
||||
label18.Location = new System.Drawing.Point(41, 208);
|
||||
label18.Location = new System.Drawing.Point(80, 208);
|
||||
label18.Name = "label18";
|
||||
label18.Size = new System.Drawing.Size(147, 13);
|
||||
label18.Size = new System.Drawing.Size(108, 13);
|
||||
label18.TabIndex = 25;
|
||||
label18.Text = "Max. dynamic lights to render:";
|
||||
label18.Text = "Dynamic lights count:";
|
||||
label18.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
this.toolTip1.SetToolTip(label18, "Controls how many dynamic lights could be \r\nrendered simultaneously in Visual mod" +
|
||||
"e ");
|
||||
|
@ -654,7 +654,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// label29
|
||||
//
|
||||
label29.AutoSize = true;
|
||||
label29.Location = new System.Drawing.Point(90, 356);
|
||||
label29.Location = new System.Drawing.Point(96, 356);
|
||||
label29.Name = "label29";
|
||||
label29.Size = new System.Drawing.Size(93, 13);
|
||||
label29.TabIndex = 38;
|
||||
|
@ -1704,7 +1704,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// label32
|
||||
//
|
||||
this.label32.AutoSize = true;
|
||||
this.label32.Location = new System.Drawing.Point(44, 134);
|
||||
this.label32.Location = new System.Drawing.Point(49, 134);
|
||||
this.label32.Name = "label32";
|
||||
this.label32.Size = new System.Drawing.Size(139, 13);
|
||||
this.label32.TabIndex = 44;
|
||||
|
@ -1724,7 +1724,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// label30
|
||||
//
|
||||
this.label30.AutoSize = true;
|
||||
this.label30.Location = new System.Drawing.Point(16, 97);
|
||||
this.label30.Location = new System.Drawing.Point(15, 97);
|
||||
this.label30.Name = "label30";
|
||||
this.label30.Size = new System.Drawing.Size(173, 13);
|
||||
this.label30.TabIndex = 41;
|
||||
|
@ -1845,14 +1845,13 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// tbDynLightCount
|
||||
//
|
||||
this.tbDynLightCount.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.tbDynLightCount.LargeChange = 3;
|
||||
this.tbDynLightCount.LargeChange = 1;
|
||||
this.tbDynLightCount.Location = new System.Drawing.Point(199, 197);
|
||||
this.tbDynLightCount.Maximum = 32;
|
||||
this.tbDynLightCount.Maximum = 8;
|
||||
this.tbDynLightCount.Minimum = 1;
|
||||
this.tbDynLightCount.Name = "tbDynLightCount";
|
||||
this.tbDynLightCount.Size = new System.Drawing.Size(154, 45);
|
||||
this.tbDynLightCount.TabIndex = 5;
|
||||
this.tbDynLightCount.TickFrequency = 4;
|
||||
this.tbDynLightCount.TickStyle = System.Windows.Forms.TickStyle.TopLeft;
|
||||
this.tbDynLightCount.Value = 1;
|
||||
this.tbDynLightCount.ValueChanged += new System.EventHandler(this.tbDynLightCount_ValueChanged);
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
checkforupdates.Checked = General.Settings.CheckForUpdates;
|
||||
toolbar_gzdoom.Checked = General.Settings.GZToolbarGZDoom;
|
||||
cbSynchCameras.Checked = General.Settings.GZSynchCameras;
|
||||
tbDynLightCount.Value = General.Clamp(General.Settings.GZMaxDynamicLights, tbDynLightCount.Minimum, tbDynLightCount.Maximum);
|
||||
tbDynLightCount.Value = General.Clamp(General.Settings.GZMaxDynamicLights / 8, tbDynLightCount.Minimum, tbDynLightCount.Maximum);
|
||||
labelDynLightCount.Text = General.Settings.GZMaxDynamicLights.ToString();
|
||||
tbDynLightSize.Value = General.Clamp((int)(General.Settings.GZDynamicLightRadius * 10), tbDynLightSize.Minimum, tbDynLightSize.Maximum);
|
||||
labelDynLightSize.Text = General.Settings.GZDynamicLightRadius.ToString();
|
||||
|
@ -409,7 +409,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
|
||||
//mxd
|
||||
General.Settings.GZSynchCameras = cbSynchCameras.Checked;
|
||||
General.Settings.GZMaxDynamicLights = tbDynLightCount.Value;
|
||||
General.Settings.GZMaxDynamicLights = tbDynLightCount.Value * 8;
|
||||
General.Settings.GZDynamicLightRadius = (tbDynLightSize.Value / 10.0f);
|
||||
General.Settings.GZDynamicLightIntensity = (tbDynLightIntensity.Value / 10.0f);
|
||||
General.Settings.FilterAnisotropy = D3DDevice.AF_STEPS[anisotropicfiltering.Value];
|
||||
|
@ -1006,7 +1006,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
//mxd
|
||||
private void tbDynLightCount_ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
labelDynLightCount.Text = tbDynLightCount.Value.ToString();
|
||||
labelDynLightCount.Text = (tbDynLightCount.Value * 8).ToString();
|
||||
}
|
||||
|
||||
//mxd
|
||||
|
|
|
@ -118,9 +118,10 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
}
|
||||
|
||||
// Texture name will be empty when skin path is embedded in the model
|
||||
string texturename = (!string.IsNullOrEmpty(mds.TextureNames[fs.ModelIndex]) ? mds.TextureNames[fs.ModelIndex].ToLowerInvariant() : string.Empty);
|
||||
string skinname = (!string.IsNullOrEmpty(mds.SkinNames[fs.ModelIndex]) ? mds.SkinNames[fs.ModelIndex].ToLowerInvariant() : string.Empty);
|
||||
|
||||
md.TextureNames.Add(texturename);
|
||||
md.SkinNames.Add(skinname);
|
||||
md.SurfaceSkinNames.Add(mds.SurfaceSkinNames[fs.ModelIndex]);
|
||||
md.ModelNames.Add(mds.ModelNames[fs.ModelIndex].ToLowerInvariant());
|
||||
md.FrameNames.Add(fs.FrameName);
|
||||
md.FrameIndices.Add(fs.FrameIndex);
|
||||
|
|
|
@ -33,7 +33,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
#region ================== Variables
|
||||
|
||||
private string[] texturenames;
|
||||
private string[] skinnames;
|
||||
private Dictionary<int, string>[] surfaceskinenames;
|
||||
private string[] modelnames;
|
||||
private string path;
|
||||
private Vector3 scale;
|
||||
|
@ -51,7 +52,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
#region ================== Properties
|
||||
|
||||
public string[] TextureNames { get { return texturenames; } }
|
||||
public string[] SkinNames { get { return skinnames; } }
|
||||
public Dictionary<int, string>[] SurfaceSkinNames { get { return surfaceskinenames; } }
|
||||
public string[] ModelNames { get { return modelnames; } }
|
||||
public Vector3 Scale { get { return scale; } }
|
||||
public Vector3 Offset { get { return offset; } }
|
||||
|
@ -70,10 +72,15 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
internal ModeldefStructure()
|
||||
{
|
||||
texturenames = new string[MAX_MODELS];
|
||||
skinnames = new string[MAX_MODELS];
|
||||
modelnames = new string[MAX_MODELS];
|
||||
frames = new Dictionary<string, HashSet<FrameStructure>>(StringComparer.OrdinalIgnoreCase);
|
||||
scale = new Vector3(1.0f, 1.0f, 1.0f);
|
||||
surfaceskinenames = new Dictionary<int, string>[MAX_MODELS];
|
||||
for(int i = 0; i < MAX_MODELS; i++)
|
||||
{
|
||||
surfaceskinenames[i] = new Dictionary<int, string>();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -194,7 +201,72 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
}
|
||||
|
||||
// GZDoom allows skins with identical index, it uses the last one encountered
|
||||
texturenames[skinindex] = Path.Combine(path, token);
|
||||
skinnames[skinindex] = Path.Combine(path, token);
|
||||
break;
|
||||
|
||||
// SurfaceSkin <int modelindex> <int surfaceindex> <string skinfile>
|
||||
case "surfaceskin":
|
||||
parser.SkipWhitespace(true);
|
||||
|
||||
// Model index
|
||||
int modelindex = 0;
|
||||
token = parser.ReadToken();
|
||||
if(!parser.ReadSignedInt(token, ref modelindex))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("Expected model index, but got \"" + token + "\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(modelindex < 0 || modelindex >= MAX_MODELS)
|
||||
{
|
||||
// Out of bounds
|
||||
parser.ReportError("Model index must be in [0.." + (MAX_MODELS - 1) + "] range");
|
||||
return false;
|
||||
}
|
||||
|
||||
parser.SkipWhitespace(true);
|
||||
|
||||
// Surfaceindex index
|
||||
int surfaceindex = 0;
|
||||
token = parser.ReadToken();
|
||||
if(!parser.ReadSignedInt(token, ref surfaceindex))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("Expected surface index, but got \"" + token + "\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(surfaceindex < 0)
|
||||
{
|
||||
// Out of bounds
|
||||
parser.ReportError("Surface index must be positive integer");
|
||||
return false;
|
||||
}
|
||||
|
||||
parser.SkipWhitespace(true);
|
||||
|
||||
// Skin path
|
||||
token = parser.StripTokenQuotes(parser.ReadToken(false)).ToLowerInvariant(); // Don't skip newline
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
parser.ReportError("Expected skin path");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check invalid path chars
|
||||
if(!parser.CheckInvalidPathChars(token)) return false;
|
||||
|
||||
// Check extension
|
||||
string skinext = Path.GetExtension(token);
|
||||
if(Array.IndexOf(ModelData.SUPPORTED_TEXTURE_EXTENSIONS, skinext) == -1)
|
||||
{
|
||||
parser.ReportError("Image format \"" + skinext + "\" is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store
|
||||
surfaceskinenames[modelindex][surfaceindex] = Path.Combine(path, token);
|
||||
break;
|
||||
|
||||
case "scale":
|
||||
|
@ -511,11 +583,21 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
}
|
||||
|
||||
// Check skin-model associations
|
||||
for(int i = 0; i < texturenames.Length; i++)
|
||||
for(int i = 0; i < skinnames.Length; i++)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(texturenames[i]) && string.IsNullOrEmpty(modelnames[i]))
|
||||
if(!string.IsNullOrEmpty(skinnames[i]) && string.IsNullOrEmpty(modelnames[i]))
|
||||
{
|
||||
parser.ReportError("No model is defined for skin " + i + ":\"" + texturenames[i] + "\"");
|
||||
parser.ReportError("No model is defined for skin " + i + ":\"" + skinnames[i] + "\"");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check surfaceskin-model associations
|
||||
for(int i = 0; i < surfaceskinenames.Length; i++)
|
||||
{
|
||||
if(surfaceskinenames[i].Count > 0 && string.IsNullOrEmpty(modelnames[i]))
|
||||
{
|
||||
parser.ReportError("No model is defined for surface skin " + i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue