@ work on (G)ZDoom Editing plugin

This commit is contained in:
codeimp 2010-09-08 06:09:03 +00:00
parent 1830eee6c9
commit a0b87ebd06
8 changed files with 224 additions and 96 deletions

View file

@ -119,6 +119,12 @@ namespace CodeImp.DoomBuilder.Geometry
return new Vector3D(a.x / s, a.y / s, a.z / s);
}
// This scales a vector
public static Vector3D operator /(Vector3D a, Vector3D b)
{
return new Vector3D(a.x / b.x, a.y / b.y, a.z / b.z);
}
// This compares a vector
public static bool operator ==(Vector3D a, Vector3D b)
{

View file

@ -58,6 +58,7 @@
<Compile Include="VisualModes\SectorData.cs" />
<Compile Include="VisualModes\SectorLevel.cs" />
<Compile Include="VisualModes\SectorLevelType.cs" />
<Compile Include="VisualModes\TexturePlane.cs" />
<Compile Include="VisualModes\VisualActionResult.cs" />
<Compile Include="VisualModes\VisualCeiling.cs" />
<Compile Include="VisualModes\VisualFloor.cs" />

View file

@ -108,7 +108,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
u_ray = pickrayu;
return true;
}
#endregion
#region ================== Events

View file

@ -538,13 +538,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
SectorData sd = GetSectorData(General.Map.VisualCamera.Sector);
if(!sd.Built) sd.BuildLevels(this);
Vector3D feetposition = General.Map.VisualCamera.Position - new Vector3D(0, 0, cameraflooroffset - 7.0f);
SectorLevel floorlevel = sd.GetLevelBelow(feetposition);
SectorLevel ceillevel = sd.GetLevelAbove(feetposition);
if(floorlevel == null) floorlevel = sd.Levels[0];
if(ceillevel == null) ceillevel = sd.Levels[sd.Levels.Count - 1];
// Camera below floor level?
Vector3D feetposition = General.Map.VisualCamera.Position - new Vector3D(0, 0, cameraflooroffset - 7.0f);
SectorLevel floorlevel = sd.GetFloorBelow(feetposition) ?? sd.Levels[0];
float floorheight = floorlevel.plane.GetZ(General.Map.VisualCamera.Position);
if(General.Map.VisualCamera.Position.z < (floorheight + cameraflooroffset + 0.01f))
{
@ -559,20 +555,35 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// Fall down
gravity.z += (float)(GRAVITY * deltatime);
if(gravity.z > 3.0f) gravity.z = 3.0f;
General.Map.VisualCamera.Position += gravity;
// Test if we don't go through a floor
SectorLevel newfloorlevel = sd.GetFloorBelow(feetposition + gravity) ?? sd.Levels[0];
if(newfloorlevel != floorlevel)
{
// Stay above floor
gravity = new Vector3D(0.0f, 0.0f, 0.0f);
General.Map.VisualCamera.Position = new Vector3D(General.Map.VisualCamera.Position.x,
General.Map.VisualCamera.Position.y,
floorheight + cameraflooroffset);
}
else
{
// Apply gravity vector
General.Map.VisualCamera.Position += gravity;
}
}
/*
// Camera above ceiling level?
// Camera above ceiling?
feetposition = General.Map.VisualCamera.Position - new Vector3D(0, 0, cameraflooroffset - 7.0f);
SectorLevel ceillevel = sd.GetCeilingAbove(feetposition) ?? sd.Levels[sd.Levels.Count - 1];
float ceilheight = ceillevel.plane.GetZ(General.Map.VisualCamera.Position);
if(General.Map.VisualCamera.Position.z > (ceilheight - cameraceilingoffset))
if(General.Map.VisualCamera.Position.z > (ceilheight - cameraceilingoffset - 0.01f))
{
// Stay below ceiling
General.Map.VisualCamera.Position = new Vector3D(General.Map.VisualCamera.Position.x,
General.Map.VisualCamera.Position.y,
ceilheight - cameraceilingoffset);
}
*/
}
else
{

View file

@ -288,6 +288,28 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
return found;
}
// This returns the level above the given point
public SectorLevel GetCeilingAbove(Vector3D pos)
{
SectorLevel found = null;
float dist = float.MaxValue;
foreach(SectorLevel l in levels)
{
if(l.type == SectorLevelType.Ceiling)
{
float d = l.plane.GetZ(pos) - pos.z;
if((d > 0.0f) && (d < dist))
{
dist = d;
found = l;
}
}
}
return found;
}
// This returns the level below the given point
public SectorLevel GetLevelBelow(Vector3D pos)
{
@ -307,6 +329,28 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
return found;
}
// This returns the floor below the given point
public SectorLevel GetFloorBelow(Vector3D pos)
{
SectorLevel found = null;
float dist = float.MaxValue;
foreach(SectorLevel l in levels)
{
if(l.type == SectorLevelType.Floor)
{
float d = pos.z - l.plane.GetZ(pos);
if((d > 0.0f) && (d < dist))
{
dist = d;
found = l;
}
}
}
return found;
}
#endregion
}

View file

@ -0,0 +1,56 @@
#region === Copyright (c) 2010 Pascal van der Heiden ===
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.GZDoomEditing
{
internal struct TexturePlane
{
// Geometry coordinates (left-top, right-top and right-bottom)
public Vector3D vlt;
public Vector3D vrt;
public Vector3D vrb;
// Texture coordinates on the points above
public Vector2D tlt;
public Vector2D trt;
public Vector2D trb;
// This returns interpolated texture coordinates for the point p on the plane defined by vlt, vrt and vrb
public Vector2D GetTextureCoordsAt(Vector3D p)
{
// Delta vectors
Vector3D v31 = vrb - vlt;
Vector3D v21 = vrt - vlt;
Vector3D vp1 = p - vlt;
// Compute dot products
float d00 = Vector3D.DotProduct(v31, v31);
float d01 = Vector3D.DotProduct(v31, v21);
float d02 = Vector3D.DotProduct(v31, vp1);
float d11 = Vector3D.DotProduct(v21, v21);
float d12 = Vector3D.DotProduct(v21, vp1);
// Compute barycentric coordinates
float invd = 1.0f / (d00 * d11 - d01 * d01);
float u = (d11 * d02 - d01 * d12) * invd;
float v = (d00 * d12 - d01 * d02) * invd;
// Delta texture coordinates
Vector2D t21 = trt - tlt;
Vector2D t31 = trb - tlt;
// Lerp
return tlt + t31 * u + t21 * v;
}
}
}

View file

@ -65,111 +65,121 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// This builds the geometry. Returns false when no geometry created.
public override bool Setup()
{
SectorData sd = mode.GetSectorData(Sidedef.Sector);
int brightness = mode.CalculateBrightness(Sidedef.Sector.Brightness);
// Calculate size of this wall part
float geotop = (float)Sidedef.Sector.CeilHeight;
float geobottom = (float)Sidedef.Sector.FloorHeight;
float geoheight = geotop - geobottom;
if(geoheight > 0.001f)
// Texture given?
if((Sidedef.MiddleTexture.Length > 0) && (Sidedef.MiddleTexture[0] != '-'))
{
Vector2D t1 = new Vector2D();
Vector2D t2 = new Vector2D();
// Texture given?
if((Sidedef.MiddleTexture.Length > 0) && (Sidedef.MiddleTexture[0] != '-'))
// Load texture
base.Texture = General.Map.Data.GetTextureImage(Sidedef.LongMiddleTexture);
if(base.Texture == null)
{
// Load texture
base.Texture = General.Map.Data.GetTextureImage(Sidedef.LongMiddleTexture);
if(base.Texture == null)
{
base.Texture = General.Map.Data.MissingTexture3D;
setuponloadedtexture = Sidedef.LongMiddleTexture;
}
else
{
if(!base.Texture.IsImageLoaded)
setuponloadedtexture = Sidedef.LongMiddleTexture;
}
}
else
{
// Use missing texture
base.Texture = General.Map.Data.MissingTexture3D;
setuponloadedtexture = 0;
}
// Get texture scaled size
Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);
// Determine texture coordinates
// See http://doom.wikia.com/wiki/Texture_alignment
// We just use pixels for coordinates for now
if(Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
{
// When lower unpegged is set, the middle texture is bound to the bottom
t1.y = tsz.y - geoheight;
}
t2.x = t1.x + Sidedef.Line.Length;
t2.y = t1.y + geoheight;
// Apply texture offset
if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
{
t1 += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
t2 += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
setuponloadedtexture = Sidedef.LongMiddleTexture;
}
else
{
t1 += new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
t2 += new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
if(!base.Texture.IsImageLoaded)
setuponloadedtexture = Sidedef.LongMiddleTexture;
}
}
else
{
// Use missing texture
base.Texture = General.Map.Data.MissingTexture3D;
setuponloadedtexture = 0;
}
// Transform pixel coordinates to texture coordinates
t1 /= tsz;
t2 /= tsz;
// Get texture scaled size
Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);
// Determine texture coordinates plane as they would be in normal circumstances.
// We can then use this plane to find any texture coordinate we need.
// The logic here is the same as in the original VisualMiddleSingle (except that
// the values are stored in a TexturePlane)
TexturePlane tp = new TexturePlane();
if(Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
{
// When lower unpegged is set, the middle texture is bound to the bottom
tp.tlt.y = tsz.y - (Sidedef.Sector.CeilHeight - Sidedef.Sector.FloorHeight);
}
tp.trb.x = tp.tlt.x + Sidedef.Line.Length;
tp.trb.y = tp.tlt.y + (Sidedef.Sector.CeilHeight - Sidedef.Sector.FloorHeight);
// Get world coordinates for geometry
Vector2D v1, v2;
if(Sidedef.IsFront)
// Apply texture offset
if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
{
tp.tlt += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
tp.trb += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
}
else
{
tp.tlt += new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
tp.trb += new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
}
// Transform pixel coordinates to texture coordinates
tp.tlt /= tsz;
tp.trb /= tsz;
// Left top and right bottom of the geometry that
if(Sidedef.IsFront)
{
tp.vlt = new Vector3D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y, Sidedef.Sector.CeilHeight);
tp.vrb = new Vector3D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y, Sidedef.Sector.FloorHeight);
}
else
{
tp.vlt = new Vector3D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y, Sidedef.Sector.CeilHeight);
tp.vrb = new Vector3D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y, Sidedef.Sector.FloorHeight);
}
// Make the right-top coordinates
tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);
// Go for all levels to build geometry
List<WorldVertex> verts = new List<WorldVertex>();
for(int i = 0; i < (sd.Levels.Count - 1); i++)
{
SectorLevel lb = sd.Levels[i];
SectorLevel lt = sd.Levels[i + 1];
if(lt.type != SectorLevelType.Floor)
{
v1 = Sidedef.Line.Start.Position;
v2 = Sidedef.Line.End.Position;
}
else
{
v1 = Sidedef.Line.End.Position;
v2 = Sidedef.Line.Start.Position;
}
PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lt.brightnessbelow));
PixelColor wallcolor = PixelColor.Modulate(lt.colorbelow, wallbrightness);
int c = wallcolor.WithAlpha(255).ToInt();
// Make vertices
WorldVertex[] verts = new WorldVertex[6];
verts[0] = new WorldVertex(v1.x, v1.y, geobottom, brightness, t1.x, t2.y);
verts[1] = new WorldVertex(v1.x, v1.y, geotop, brightness, t1.x, t1.y);
verts[2] = new WorldVertex(v2.x, v2.y, geotop, brightness, t2.x, t1.y);
verts[3] = verts[0];
verts[4] = verts[2];
verts[5] = new WorldVertex(v2.x, v2.y, geobottom, brightness, t2.x, t2.y);
Vector3D vlb = new Vector3D(tp.vlt.x, tp.vlt.y, lb.plane.GetZ(tp.vlt));
Vector3D vlt = new Vector3D(tp.vlt.x, tp.vlt.y, lt.plane.GetZ(tp.vlt));
Vector3D vrb = new Vector3D(tp.vrb.x, tp.vrb.y, lb.plane.GetZ(tp.vrb));
Vector3D vrt = new Vector3D(tp.vrt.x, tp.vrt.y, lt.plane.GetZ(tp.vrt));
Vector2D tlb = tp.GetTextureCoordsAt(vlb);
Vector2D tlt = tp.GetTextureCoordsAt(vlt);
Vector2D trb = tp.GetTextureCoordsAt(vrb);
Vector2D trt = tp.GetTextureCoordsAt(vrt);
// Keep properties
base.top = geotop;
base.bottom = geobottom;
// Apply vertices
verts.Add(new WorldVertex(vlb.x, vlb.y, vlb.z, c, tlb.x, tlb.y));
verts.Add(new WorldVertex(vlt.x, vlt.y, vlt.z, c, tlt.x, tlt.y));
verts.Add(new WorldVertex(vrt.x, vrt.y, vrt.z, c, trt.x, trt.y));
verts.Add(new WorldVertex(vlb.x, vlb.y, vlb.z, c, tlb.x, tlb.y));
verts.Add(new WorldVertex(vrt.x, vrt.y, vrt.z, c, trt.x, trt.y));
verts.Add(new WorldVertex(vrb.x, vrb.y, vrb.z, c, trb.x, trb.y));
}
}
if(verts.Count > 0)
{
base.SetVertices(verts);
return true;
}
else
{
// No geometry for invisible wall
base.top = geotop;
base.bottom = geobottom;
WorldVertex[] verts = new WorldVertex[0];
base.SetVertices(verts);
return false;
}
}
#endregion
#region ================== Methods

Binary file not shown.