2014-11-19 00:45:57 +00:00
|
|
|
// Emacs style mode select -*- C++ -*-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Copyright(C) 2004 Stephen McGranahan
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
//
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// DESCRIPTION:
|
|
|
|
// Slopes
|
|
|
|
// SoM created 05/10/09
|
|
|
|
// ZDoom + Eternity Engine Slopes, ported and enhanced by Kalaron
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "r_defs.h"
|
|
|
|
#include "r_state.h"
|
|
|
|
#include "m_bbox.h"
|
|
|
|
#include "z_zone.h"
|
|
|
|
#include "p_spec.h"
|
|
|
|
#include "p_slopes.h"
|
|
|
|
#include "r_main.h"
|
|
|
|
#include "p_maputl.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
|
|
|
|
#ifdef ESLOPE
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_MakeSlope
|
|
|
|
//
|
|
|
|
// Alocates and fill the contents of a slope structure.
|
|
|
|
//
|
|
|
|
static pslope_t *P_MakeSlope(const v3float_t *o, const v2float_t *d,
|
|
|
|
const float zdelta, boolean isceiling)
|
|
|
|
{
|
|
|
|
pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
|
|
|
|
memset(ret, 0, sizeof(*ret));
|
|
|
|
|
|
|
|
ret->o.x = FLOAT_TO_FIXED(ret->of.x = o->x);
|
|
|
|
ret->o.y = FLOAT_TO_FIXED(ret->of.y = o->y);
|
|
|
|
ret->o.z = FLOAT_TO_FIXED(ret->of.z = o->z);
|
|
|
|
|
|
|
|
ret->d.x = FLOAT_TO_FIXED(ret->df.x = d->x);
|
|
|
|
ret->d.y = FLOAT_TO_FIXED(ret->df.y = d->y);
|
|
|
|
|
|
|
|
ret->zdelta = FLOAT_TO_FIXED(ret->zdeltaf = zdelta);
|
|
|
|
|
|
|
|
// d = direction (v2float_t)
|
|
|
|
//
|
|
|
|
// direction.x = line->nx;
|
|
|
|
// direction.y = line->ny;
|
|
|
|
//
|
|
|
|
// o = origin (v3float_t)
|
|
|
|
// origin.x = (FIXED_TO_FLOAT(line->v2->x) + FIXED_TO_FLOAT(line->v1->x)) * 0.5f;
|
|
|
|
// origin.y = (FIXED_TO_FLOAT(line->v2->y) + FIXED_TO_FLOAT(line->v1->y)) * 0.5f;
|
|
|
|
|
|
|
|
{
|
|
|
|
// Now calculate the normal of the plane!
|
|
|
|
v3float_t v1, v2, v3, d1, d2;
|
|
|
|
float len;
|
|
|
|
|
|
|
|
v1.x = o->x;
|
|
|
|
v1.y = o->y;
|
|
|
|
v1.z = o->z;
|
|
|
|
|
|
|
|
v2.x = v1.x;
|
|
|
|
v2.y = v1.y + 10.0f;
|
|
|
|
v2.z = P_GetZAtf(ret, v2.x, v2.y);
|
|
|
|
|
|
|
|
v3.x = v1.x + 10.0f;
|
|
|
|
v3.y = v1.y;
|
|
|
|
v3.z = P_GetZAtf(ret, v3.x, v3.y);
|
|
|
|
|
|
|
|
if (isceiling)
|
|
|
|
{
|
|
|
|
M_SubVec3f(&d1, &v1, &v3);
|
|
|
|
M_SubVec3f(&d2, &v2, &v3);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
M_SubVec3f(&d1, &v1, &v2);
|
|
|
|
M_SubVec3f(&d2, &v3, &v2);
|
|
|
|
}
|
|
|
|
|
|
|
|
M_CrossProduct3f(&ret->normalf, &d1, &d2);
|
|
|
|
|
|
|
|
// Cross product length
|
|
|
|
len = (float)sqrt(ret->normalf.x * ret->normalf.x +
|
|
|
|
ret->normalf.y * ret->normalf.y +
|
|
|
|
ret->normalf.z * ret->normalf.z);
|
|
|
|
|
|
|
|
#ifdef SLOPETHINGS
|
|
|
|
if (len == 0)
|
|
|
|
{
|
|
|
|
// Only happens when all vertices in this sector are on the same line.
|
|
|
|
// Let's just ignore this case.
|
|
|
|
CONS_Printf("Slope thing at (%d,%d) lies directly on its target line.\n", int(x>>16), int(y>>16));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ret->normalf.x /= len;
|
|
|
|
ret->normalf.y /= len;
|
|
|
|
ret->normalf.z /= len;
|
|
|
|
|
|
|
|
// ZDoom
|
|
|
|
// cross = ret->normalf
|
|
|
|
|
|
|
|
// Fix backward normals
|
|
|
|
if ((ret->normalf.z < 0 && !isceiling) || (ret->normalf.z > 0 && isceiling))
|
|
|
|
{
|
|
|
|
ret->normalf.x = -ret->normalf.x;
|
|
|
|
ret->normalf.y = -ret->normalf.x;
|
|
|
|
ret->normalf.z = -ret->normalf.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_CopySlope
|
|
|
|
//
|
|
|
|
// Allocates and returns a copy of the given slope structure.
|
|
|
|
//
|
|
|
|
static pslope_t *P_CopySlope(const pslope_t *src)
|
|
|
|
{
|
|
|
|
pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
|
|
|
|
memcpy(ret, src, sizeof(*ret));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_MakeLineNormal
|
|
|
|
//
|
|
|
|
// Calculates a 2D normal for the given line and stores it in the line
|
|
|
|
//
|
|
|
|
void P_MakeLineNormal(line_t *line)
|
|
|
|
{
|
|
|
|
float linedx, linedy, length;
|
|
|
|
|
|
|
|
// SRB2CBTODO: Give linedefs an fx+fy(float xy coords)?
|
|
|
|
// May cause slow downs since the float would always have to be converted/updated
|
|
|
|
linedx = FIXED_TO_FLOAT(line->v2->x) - FIXED_TO_FLOAT(line->v1->x);
|
|
|
|
linedy = FIXED_TO_FLOAT(line->v2->y) - FIXED_TO_FLOAT(line->v1->y);
|
|
|
|
|
|
|
|
length = (float)sqrt(linedx * linedx + linedy * linedy);
|
|
|
|
line->nx = linedy / length;
|
|
|
|
line->ny = -linedx / length;
|
|
|
|
line->len = length;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_GetExtent
|
|
|
|
//
|
|
|
|
// Returns the distance to the first line within the sector that
|
|
|
|
// is intersected by a line parallel to the plane normal with the point (ox, oy)
|
|
|
|
//
|
|
|
|
static float P_GetExtent(sector_t *sector, line_t *line, v3float_t *o, v2float_t *d)
|
|
|
|
{
|
|
|
|
// ZDoom code reference: v3float_t = vertex_t
|
|
|
|
float fardist = -1.0f;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
// Find furthest vertex from the reference line. It, along with the two ends
|
|
|
|
// of the line, will define the plane.
|
|
|
|
// SRB2CBTODO: Use a formula to get the slope to slide objects depending on how steep
|
|
|
|
for(i = 0; i < sector->linecount; i++)
|
|
|
|
{
|
|
|
|
line_t *li = sector->lines[i];
|
2015-04-19 21:54:20 +00:00
|
|
|
vertex_t tempv;
|
2014-11-19 00:45:57 +00:00
|
|
|
float dist;
|
2015-04-19 21:54:20 +00:00
|
|
|
|
2014-11-19 00:45:57 +00:00
|
|
|
// Don't compare to the slope line.
|
|
|
|
if(li == line)
|
|
|
|
continue;
|
2015-04-19 21:54:20 +00:00
|
|
|
|
2014-11-19 00:45:57 +00:00
|
|
|
// ZDoom code in P_AlignPlane
|
|
|
|
// dist = fabs((double(line->v1->y) - vert->y) * line->dx - (double(line->v1->x) - vert->x) * line->dy);
|
2015-04-19 21:54:20 +00:00
|
|
|
//dist = (float)fabs((FIXED_TO_FLOAT(li->v1->x) - o->x) * d->x + (FIXED_TO_FLOAT(li->v1->y) - o->y) * d->y);
|
|
|
|
P_ClosestPointOnLine(li->v1->x, li->v1->y, line, &tempv);
|
2015-04-20 17:18:56 +00:00
|
|
|
dist = FIXED_TO_FLOAT(R_PointToDist2(tempv.x, tempv.y, li->v1->x, li->v1->y));
|
2014-11-19 00:45:57 +00:00
|
|
|
if(dist > fardist)
|
|
|
|
fardist = dist;
|
|
|
|
|
2015-04-19 21:54:20 +00:00
|
|
|
// We shouldn't have to do this for v2... -Red
|
|
|
|
/*dist = (float)fabs((FIXED_TO_FLOAT(li->v2->x) - o->x) * d->x + (FIXED_TO_FLOAT(li->v2->y) - o->y) * d->y);
|
2014-11-19 00:45:57 +00:00
|
|
|
if(dist > fardist)
|
2015-04-19 21:54:20 +00:00
|
|
|
fardist = dist;*/
|
2014-11-19 00:45:57 +00:00
|
|
|
}
|
2015-04-19 21:54:20 +00:00
|
|
|
|
2014-11-19 00:45:57 +00:00
|
|
|
return fardist;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_SpawnSlope_Line
|
|
|
|
//
|
|
|
|
// Creates one or more slopes based on the given line type and front/back
|
|
|
|
// sectors.
|
|
|
|
// Kalaron: Check if dynamic slopes need recalculation
|
|
|
|
//
|
|
|
|
void P_SpawnSlope_Line(int linenum)
|
|
|
|
{
|
|
|
|
// With dynamic slopes, it's fine to just leave this function as normal,
|
|
|
|
// because checking to see if a slope had changed will waste more memory than
|
|
|
|
// if the slope was just updated when called
|
|
|
|
line_t *line = lines + linenum;
|
|
|
|
int special = line->special;
|
|
|
|
pslope_t *fslope = NULL, *cslope = NULL;
|
|
|
|
v3float_t origin, point;
|
|
|
|
v2float_t direction;
|
|
|
|
float dz, extent;
|
|
|
|
|
|
|
|
boolean frontfloor = (special == 386 || special == 388 || special == 393);
|
|
|
|
boolean backfloor = (special == 389 || special == 391 || special == 392);
|
|
|
|
boolean frontceil = (special == 387 || special == 388 || special == 392);
|
|
|
|
boolean backceil = (special == 390 || special == 391 || special == 393);
|
|
|
|
|
|
|
|
if(!frontfloor && !backfloor && !frontceil && !backceil)
|
|
|
|
{
|
|
|
|
CONS_Printf("P_SpawnSlope_Line called with non-slope line special.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!line->frontsector || !line->backsector)
|
|
|
|
{
|
|
|
|
CONS_Printf("P_SpawnSlope_Line used on a line without two sides.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// SRB2CBTODO: Transform origin relative to the bounds of an individual FOF
|
|
|
|
origin.x = (FIXED_TO_FLOAT(line->v2->x) + FIXED_TO_FLOAT(line->v1->x)) * 0.5f;
|
|
|
|
origin.y = (FIXED_TO_FLOAT(line->v2->y) + FIXED_TO_FLOAT(line->v1->y)) * 0.5f;
|
|
|
|
|
|
|
|
// For FOF slopes, make a special function to copy to the xy origin & direction relative to the position of the FOF on the map!
|
|
|
|
if(frontfloor || frontceil)
|
|
|
|
{
|
|
|
|
origin.z = FIXED_TO_FLOAT(line->backsector->floorheight);
|
|
|
|
direction.x = line->nx;
|
|
|
|
direction.y = line->ny;
|
|
|
|
|
|
|
|
extent = P_GetExtent(line->frontsector, line, &origin, &direction);
|
|
|
|
|
|
|
|
if(extent < 0.0f)
|
|
|
|
{
|
|
|
|
CONS_Printf("P_SpawnSlope_Line failed to get frontsector extent on line number %i\n", linenum);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// reposition the origin according to the extent
|
|
|
|
point.x = origin.x + direction.x * extent;
|
|
|
|
point.y = origin.y + direction.y * extent;
|
|
|
|
direction.x = -direction.x;
|
|
|
|
direction.y = -direction.y;
|
|
|
|
|
|
|
|
// TODO: We take origin and point 's xy values and translate them to the center of an FOF!
|
|
|
|
|
|
|
|
if(frontfloor)
|
|
|
|
{
|
|
|
|
|
|
|
|
point.z = FIXED_TO_FLOAT(line->frontsector->floorheight); // Startz
|
|
|
|
dz = (FIXED_TO_FLOAT(line->backsector->floorheight) - point.z) / extent; // Destinationz
|
|
|
|
|
|
|
|
// In P_SpawnSlopeLine the origin is the centerpoint of the sourcelinedef
|
|
|
|
|
|
|
|
int slopeangle = 0; // All floors by default have no slope (an angle of 0, completely flat)
|
|
|
|
|
|
|
|
v3float_t A = origin; // = line source
|
|
|
|
v3float_t B = point; // destination's value
|
|
|
|
v3float_t C = origin; // Point used to make a right triangle from A & B
|
|
|
|
|
|
|
|
C.z = point.z;
|
|
|
|
|
|
|
|
// To find the "angle" of a slope, we make a right triangle out of the points we have,
|
|
|
|
// point A - is point 1 of the hypotenuse,
|
|
|
|
// point B - is point 2 of the hypotenuse
|
|
|
|
// point C - has the same Z value as point b, and the same XY value as A
|
|
|
|
//
|
|
|
|
// We want to find the angle accross from the right angle
|
|
|
|
// so we use some triginometry to find the angle(fun, right?)
|
|
|
|
// We want to find the tanjent of this angle, this is:
|
|
|
|
// Opposite
|
|
|
|
// ------- = tan(x)
|
|
|
|
// Adjecent
|
|
|
|
// But actually tan doesn't do want we really want, we have to use atan to find the actual angle of the triangle's corner
|
|
|
|
float triangopplength = abs(B.z - A.z);
|
|
|
|
float triangadjlength = sqrt((B.x-C.x)*(B.x-C.x) + (B.y - C.y)*(B.y - C.y));
|
|
|
|
//float trianghyplength = sqrt(triangopplength*triangopplength + triangadjlength*triangadjlength); // This is the hypotenuse
|
|
|
|
|
|
|
|
// So tanjent = opposite divided by adjecent
|
|
|
|
float tanrelat = triangopplength/ triangadjlength; // tanjent = opposite / adjecent
|
|
|
|
slopeangle = atan(tanrelat)* 180 / M_PI; // Now we use atan: *180 /M_PI is needed to convert the value into degrees
|
|
|
|
|
|
|
|
fslope = line->frontsector->f_slope =
|
|
|
|
P_MakeSlope(&point, &direction, dz, false);
|
|
|
|
|
|
|
|
// Now remember that f_slope IS a vector
|
|
|
|
// fslope->o = origin 3D point 1 of the vector
|
|
|
|
// fslope->d = destination 3D point 2 of the vector
|
|
|
|
// fslope->normal is a 3D line perpendicular to the 3D vector
|
|
|
|
|
|
|
|
// Sync the linedata of the line that started this slope
|
|
|
|
// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
|
|
|
|
line->frontsector->f_slope->sourceline = line;
|
|
|
|
|
|
|
|
// To find the real highz/lowz of a slope, you need to check all the vertexes
|
|
|
|
// in the slope's sector with P_GetZAt to get the REAL lowz & highz
|
|
|
|
// Although these slopes are set by floorheights the ANGLE is what a slope is,
|
|
|
|
// so technically any slope can extend on forever (they are just bound by sectors)
|
|
|
|
// *You can use sourceline as a reference to see if two slopes really are the same
|
|
|
|
|
|
|
|
// Default points for high and low
|
|
|
|
fixed_t highest = point.z > origin.z ? point.z : origin.z;
|
|
|
|
fixed_t lowest = point.z < origin.z ? point.z : origin.z;
|
|
|
|
highest = FLOAT_TO_FIXED(highest);
|
|
|
|
lowest = FLOAT_TO_FIXED(lowest);
|
|
|
|
|
|
|
|
// Now check to see what the REAL high and low points of the slope inside the sector
|
|
|
|
size_t l;
|
|
|
|
|
|
|
|
for (l = 0; l < line->frontsector->linecount; l++)
|
|
|
|
{
|
|
|
|
if (P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y) > highest)
|
|
|
|
highest = P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
|
|
|
|
|
|
|
|
if (P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y) < lowest)
|
|
|
|
lowest = P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sets extra clipping data for the frontsector's slope
|
|
|
|
fslope->highz = line->frontsector->f_slope->highz = highest;
|
|
|
|
fslope->lowz = line->frontsector->f_slope->lowz = lowest;
|
|
|
|
|
|
|
|
fslope->zangle = slopeangle;
|
|
|
|
fslope->xydirection = R_PointToAngle2(FLOAT_TO_FIXED(A.x), FLOAT_TO_FIXED(A.y), FLOAT_TO_FIXED(B.x), FLOAT_TO_FIXED(B.y))/(ANGLE_45/45);
|
|
|
|
|
|
|
|
secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
|
|
|
|
// ZDoom secplane port! YAY
|
|
|
|
// ret = f_slope or c_slope
|
|
|
|
srcplane->a = FLOAT_TO_FIXED (fslope->normalf.x); // cross[0]
|
|
|
|
srcplane->b = FLOAT_TO_FIXED (fslope->normalf.y); // cross[1]
|
|
|
|
srcplane->c = FLOAT_TO_FIXED (fslope->normalf.z); // cross[2]
|
|
|
|
srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c) or FLOAT_TO_FIXED(1.0f/cross[2]);
|
|
|
|
|
|
|
|
// destheight takes the destination height used in dz
|
|
|
|
srcplane->d = -TMulScale16 (srcplane->a, line->v1->x, // x
|
|
|
|
srcplane->b, line->v1->y, // y
|
|
|
|
srcplane->c, line->backsector->floorheight); // z
|
|
|
|
|
|
|
|
// Sync the secplane!
|
|
|
|
fslope->secplane = line->frontsector->f_slope->secplane = *srcplane;
|
|
|
|
|
|
|
|
}
|
|
|
|
if(frontceil)
|
|
|
|
{
|
|
|
|
point.z = FIXED_TO_FLOAT(line->frontsector->ceilingheight);
|
|
|
|
dz = (FIXED_TO_FLOAT(line->backsector->ceilingheight) - point.z) / extent;
|
|
|
|
|
|
|
|
cslope = line->frontsector->c_slope =
|
|
|
|
P_MakeSlope(&point, &direction, dz, true);
|
|
|
|
|
|
|
|
// Sync the linedata of the line that started this slope
|
|
|
|
// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
|
|
|
|
line->frontsector->c_slope->sourceline = line;
|
|
|
|
|
|
|
|
// Remember the way the slope is formed
|
|
|
|
fixed_t highest = point.z > origin.z ? point.z : origin.z;
|
|
|
|
fixed_t lowest = point.z < origin.z ? point.z : origin.z;
|
|
|
|
highest = FLOAT_TO_FIXED(highest);
|
|
|
|
lowest = FLOAT_TO_FIXED(lowest);
|
|
|
|
size_t l;
|
|
|
|
|
|
|
|
for (l = 0; l < line->frontsector->linecount; l++)
|
|
|
|
{
|
|
|
|
if (P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y) > highest)
|
|
|
|
highest = P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
|
|
|
|
|
|
|
|
if (P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y) < lowest)
|
|
|
|
lowest = P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This line special sets extra clipping data for the frontsector's slope
|
|
|
|
cslope->highz = line->frontsector->c_slope->highz = highest;
|
|
|
|
cslope->lowz = line->frontsector->c_slope->lowz = lowest;
|
|
|
|
|
|
|
|
// SRB2CBTODO: Get XY angle of a slope and then awesome physics! // ESLOPE:
|
|
|
|
//cslope->zangle = line->frontsector->c_slope->zangle = P_GetSlopezangle(line->frontsector, highvert, lowvert);
|
|
|
|
//100*(ANG45/45);//R_PointToAngle2(direction.x, direction.y, origin.x, origin.y);
|
|
|
|
// Get slope XY angle with secplane_t
|
|
|
|
secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
|
|
|
|
// ZDoom secplane port!
|
|
|
|
// secplane_t! woot!
|
|
|
|
// ret = f_slope or c_slope
|
|
|
|
srcplane->a = FLOAT_TO_FIXED (cslope->normalf.x); // cross[0]
|
|
|
|
srcplane->b = FLOAT_TO_FIXED (cslope->normalf.y); // cross[1]
|
|
|
|
srcplane->c = FLOAT_TO_FIXED (cslope->normalf.z); // cross[2]
|
|
|
|
//plane->ic = FLOAT_TO_FIXED (1.f/cross[2]);
|
|
|
|
srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c)
|
|
|
|
#ifdef SLOPETHINGS // For setting thing-based slopes
|
|
|
|
srcplane->d = -TMulScale16 (plane->a, x,
|
|
|
|
plane->b, y,
|
|
|
|
plane->c, z);
|
|
|
|
#endif
|
|
|
|
//srcheight = isceiling ? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
|
|
|
|
//destheight = isceiling ? refsec->GetPlaneTexZ(sector_t::floor) : refsec->GetPlaneTexZ(sector_t::ceiling);
|
|
|
|
//P_GetZAtf(ret, v2.x, v2.y)
|
|
|
|
// destheight takes the destination height used in dz
|
|
|
|
srcplane->d = -TMulScale16 (srcplane->a, line->v1->x,
|
|
|
|
srcplane->b, line->v1->y,
|
|
|
|
srcplane->c, line->backsector->ceilingheight);
|
|
|
|
|
|
|
|
// Sync the secplane!
|
|
|
|
cslope->secplane = line->frontsector->c_slope->secplane = *srcplane;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(backfloor || backceil)
|
|
|
|
{
|
|
|
|
origin.z = FIXED_TO_FLOAT(line->frontsector->floorheight);
|
|
|
|
// Backsector
|
|
|
|
direction.x = -line->nx;
|
|
|
|
direction.y = -line->ny;
|
|
|
|
|
|
|
|
extent = P_GetExtent(line->backsector, line, &origin, &direction);
|
|
|
|
|
|
|
|
if(extent < 0.0f)
|
|
|
|
{
|
|
|
|
CONS_Printf("P_SpawnSlope_Line failed to get backsector extent on line number %i\n", linenum);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// reposition the origin according to the extent
|
|
|
|
point.x = origin.x + direction.x * extent;
|
|
|
|
point.y = origin.y + direction.y * extent;
|
|
|
|
direction.x = -direction.x;
|
|
|
|
direction.y = -direction.y;
|
|
|
|
|
|
|
|
if(backfloor)
|
|
|
|
{
|
|
|
|
point.z = FIXED_TO_FLOAT(line->backsector->floorheight);
|
|
|
|
dz = (FIXED_TO_FLOAT(line->frontsector->floorheight) - point.z) / extent;
|
|
|
|
|
|
|
|
fslope = line->backsector->f_slope =
|
|
|
|
P_MakeSlope(&point, &direction, dz, false);
|
|
|
|
|
|
|
|
// Sync the linedata of the line that started this slope
|
|
|
|
// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
|
|
|
|
line->backsector->f_slope->sourceline = line;
|
|
|
|
|
|
|
|
int slopeangle = 0; // All floors by default have no slope (an angle of 0)
|
|
|
|
|
|
|
|
v3float_t A = origin; // = line source
|
|
|
|
v3float_t B = point; // destination's value
|
|
|
|
v3float_t C = origin;
|
|
|
|
|
|
|
|
C.z = point.z;
|
|
|
|
|
|
|
|
// To find the "angle" of a slope, we make a right triangle out of the points we have,
|
|
|
|
// point A - is point 1 of the hypotenuse,
|
|
|
|
// point B - is point 2 of the hypotenuse
|
|
|
|
// point C - has the same Z value as point b, and the same XY value as A
|
|
|
|
//
|
|
|
|
// We want to find the angle accross from the right angle
|
|
|
|
// so we use some triginometry to find the angle(fun, right?)
|
|
|
|
// We want to find the tanjent of this angle, this is:
|
|
|
|
// Opposite
|
|
|
|
// ------- = tan(x)
|
|
|
|
// Adjecent
|
|
|
|
// But actually tan doesn't do want we really want, we have to use atan to find the actual angle of the triangle's corner
|
|
|
|
float triangopplength = abs(B.z - A.z);
|
|
|
|
float triangadjlength = sqrt((B.x-C.x)*(B.x-C.x) + (B.y - C.y)*(B.y - C.y));
|
|
|
|
//float trianghyplength = sqrt(triangopplength*triangopplength + triangadjlength*triangadjlength); // This is the hypotenuse
|
|
|
|
|
|
|
|
// So tanjent = opposite divided by adjecent
|
|
|
|
float tanrelat = triangopplength/ triangadjlength; // tanjent = opposite / adjecent
|
|
|
|
slopeangle = atan(tanrelat)* 180 / M_PI; // Now we use atan - *180 /M_PI is needed to convert the value into degrees
|
|
|
|
|
|
|
|
// Remember the way the slope is formed
|
|
|
|
fixed_t highest = point.z > origin.z ? point.z : origin.z;
|
|
|
|
fixed_t lowest = point.z < origin.z ? point.z : origin.z;
|
|
|
|
highest = FLOAT_TO_FIXED(highest);
|
|
|
|
lowest = FLOAT_TO_FIXED(lowest);
|
|
|
|
size_t l;
|
|
|
|
|
|
|
|
for (l = 0; l < line->backsector->linecount; l++)
|
|
|
|
{
|
|
|
|
if (P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y) > highest)
|
|
|
|
highest = P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
|
|
|
|
|
|
|
|
if (P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y) < lowest)
|
|
|
|
lowest = P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This line special sets extra clipping data for the frontsector's slope
|
|
|
|
fslope->highz = line->backsector->f_slope->highz = highest;
|
|
|
|
fslope->lowz = line->backsector->f_slope->lowz = lowest;
|
|
|
|
|
|
|
|
fslope->zangle = slopeangle;
|
|
|
|
// Get slope XY angle with secplane_t
|
|
|
|
secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
|
|
|
|
// ZDoom secplane port!
|
|
|
|
// secplane_t! woot!
|
|
|
|
// ret = f_slope or c_slope
|
|
|
|
srcplane->a = FLOAT_TO_FIXED (fslope->normalf.x); // cross[0]
|
|
|
|
srcplane->b = FLOAT_TO_FIXED (fslope->normalf.y); // cross[1]
|
|
|
|
srcplane->c = FLOAT_TO_FIXED (fslope->normalf.z); // cross[2]
|
|
|
|
//plane->ic = FLOAT_TO_FIXED (1.f/cross[2]);
|
|
|
|
srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c)
|
|
|
|
#ifdef SLOPETHINGS // For setting thing-based slopes
|
|
|
|
srcplane->d = -TMulScale16 (plane->a, x,
|
|
|
|
plane->b, y,
|
|
|
|
plane->c, z);
|
|
|
|
#endif
|
|
|
|
//srcheight = isceiling ? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
|
|
|
|
//destheight = isceiling ? refsec->GetPlaneTexZ(sector_t::floor) : refsec->GetPlaneTexZ(sector_t::ceiling);
|
|
|
|
//P_GetZAtf(ret, v2.x, v2.y)
|
|
|
|
// destheight takes the destination height used in dz
|
|
|
|
srcplane->d = -TMulScale16 (srcplane->a, line->v1->x,
|
|
|
|
srcplane->b, line->v1->y,
|
|
|
|
srcplane->c, line->frontsector->floorheight);
|
|
|
|
|
|
|
|
// Sync the secplane!
|
|
|
|
fslope->secplane = line->backsector->f_slope->secplane = *srcplane;
|
|
|
|
}
|
|
|
|
if(backceil)
|
|
|
|
{
|
|
|
|
point.z = FIXED_TO_FLOAT(line->backsector->ceilingheight);
|
|
|
|
dz = (FIXED_TO_FLOAT(line->frontsector->ceilingheight) - point.z) / extent;
|
|
|
|
|
|
|
|
cslope = line->backsector->c_slope =
|
|
|
|
P_MakeSlope(&point, &direction, dz, true);
|
|
|
|
|
|
|
|
// Sync the linedata of the line that started this slope
|
|
|
|
// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
|
|
|
|
line->backsector->c_slope->sourceline = line;
|
|
|
|
|
|
|
|
// Remember the way the slope is formed
|
|
|
|
fixed_t highest = point.z > origin.z ? point.z : origin.z;
|
|
|
|
fixed_t lowest = point.z < origin.z ? point.z : origin.z;
|
|
|
|
highest = FLOAT_TO_FIXED(highest);
|
|
|
|
lowest = FLOAT_TO_FIXED(lowest);
|
|
|
|
|
|
|
|
size_t l;
|
|
|
|
|
|
|
|
for (l = 0; l < line->backsector->linecount; l++)
|
|
|
|
{
|
|
|
|
if (P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y) > highest)
|
|
|
|
highest = P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
|
|
|
|
|
|
|
|
if (P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y) < lowest)
|
|
|
|
lowest = P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This line special sets extra clipping data for the backsector's slope
|
|
|
|
cslope->highz = line->backsector->c_slope->highz = highest;
|
|
|
|
cslope->lowz = line->backsector->c_slope->lowz = lowest;
|
|
|
|
|
|
|
|
// SRB2CBTODO: Get XY angle of a slope and then awesome physics! // ESLOPE:
|
|
|
|
//cslope->zangle = line->backsector->c_slope->zangle = P_GetSlopezangle(line->backsector, highvert, lowvert);
|
|
|
|
//100*(ANG45/45);//R_PointToAngle2(direction.x, direction.y, origin.x, origin.y);
|
|
|
|
// Get slope XY angle with secplane_t
|
|
|
|
secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
|
|
|
|
// ZDoom secplane port!
|
|
|
|
// secplane_t! woot!
|
|
|
|
// ret = f_slope or c_slope
|
|
|
|
srcplane->a = FLOAT_TO_FIXED (cslope->normalf.x); // cross[0]
|
|
|
|
srcplane->b = FLOAT_TO_FIXED (cslope->normalf.y); // cross[1]
|
|
|
|
srcplane->c = FLOAT_TO_FIXED (cslope->normalf.z); // cross[2]
|
|
|
|
//plane->ic = FLOAT_TO_FIXED (1.f/cross[2]);
|
|
|
|
srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c)
|
|
|
|
#ifdef SLOPETHINGS // For setting thing-based slopes
|
|
|
|
srcplane->d = -TMulScale16 (plane->a, x,
|
|
|
|
plane->b, y,
|
|
|
|
plane->c, z);
|
|
|
|
#endif
|
|
|
|
//srcheight = isceiling ? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
|
|
|
|
//destheight = isceiling ? refsec->GetPlaneTexZ(sector_t::floor) : refsec->GetPlaneTexZ(sector_t::ceiling);
|
|
|
|
//P_GetZAtf(ret, v2.x, v2.y)
|
|
|
|
// destheight takes the destination height used in dz
|
|
|
|
srcplane->d = -TMulScale16 (srcplane->a, line->v1->x,
|
|
|
|
srcplane->b, line->v1->y,
|
|
|
|
srcplane->c, line->frontsector->ceilingheight);
|
|
|
|
|
|
|
|
// Sync the secplane!
|
|
|
|
cslope->secplane = line->backsector->c_slope->secplane = *srcplane;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!line->tag)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_CopySectorSlope
|
|
|
|
//
|
|
|
|
// Searches through tagged sectors and copies
|
|
|
|
//
|
|
|
|
void P_CopySectorSlope(line_t *line)
|
|
|
|
{
|
|
|
|
sector_t *fsec = line->frontsector;
|
|
|
|
int i, special = line->special;
|
|
|
|
|
|
|
|
// Check for copy linedefs
|
|
|
|
for(i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;)
|
|
|
|
{
|
|
|
|
sector_t *srcsec = sectors + i;
|
|
|
|
|
|
|
|
if((special - 393) & 1 && !fsec->f_slope && srcsec->f_slope)
|
|
|
|
fsec->f_slope = P_CopySlope(srcsec->f_slope);
|
|
|
|
if((special - 393) & 2 && !fsec->c_slope && srcsec->c_slope)
|
|
|
|
fsec->c_slope = P_CopySlope(srcsec->c_slope);
|
|
|
|
}
|
|
|
|
|
|
|
|
//SRB2CBTODO: ESLOPE: Maybe we do need it for another to check for a plane slope?
|
|
|
|
line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "byteptr.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
fixed_t z1;
|
|
|
|
fixed_t z2;
|
|
|
|
} mapvert_t;*/
|
|
|
|
|
|
|
|
#include "p_setup.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// P_SetSlopesFromVertexHeights
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
void P_SetSlopesFromVertexHeights(lumpnum_t lumpnum)
|
|
|
|
{
|
|
|
|
mapthing_t *mt;
|
|
|
|
boolean vt_found = false;
|
|
|
|
size_t i, j, k, l, q;
|
|
|
|
|
|
|
|
//size_t i;
|
|
|
|
//mapthing_t *mt;
|
|
|
|
char *data;
|
|
|
|
char *datastart;
|
|
|
|
|
|
|
|
// SRB2CBTODO: WHAT IS (5 * sizeof (short))?! It = 10
|
|
|
|
// anything else seems to make a map not load properly,
|
|
|
|
// but this hard-coded value MUST have some reason for being what it is
|
|
|
|
size_t snummapthings = W_LumpLength(lumpnum) / (5 * sizeof (short));
|
|
|
|
mapthing_t *smapthings = Z_Calloc(snummapthings * sizeof (*smapthings), PU_LEVEL, NULL);
|
|
|
|
fixed_t x, y;
|
|
|
|
sector_t *sector;
|
|
|
|
// Spawn axis points first so they are
|
|
|
|
// at the front of the list for fast searching.
|
|
|
|
data = datastart = W_CacheLumpNum(lumpnum, PU_LEVEL);
|
|
|
|
mt = smapthings;
|
|
|
|
for (i = 0; i < snummapthings; i++, mt++)
|
|
|
|
{
|
|
|
|
mt->x = READINT16(data);
|
|
|
|
mt->y = READINT16(data);
|
|
|
|
mt->angle = READINT16(data);
|
|
|
|
mt->type = READINT16(data);
|
|
|
|
mt->options = READINT16(data);
|
|
|
|
// mt->z hasn't been set yet!
|
|
|
|
//mt->extrainfo = (byte)(mt->type >> 12); // slope things are special, they have a bigger range of types
|
|
|
|
|
|
|
|
//mt->type &= 4095; // SRB2CBTODO: WHAT IS THIS???? Mobj type limits?!!!!
|
|
|
|
x = mt->x*FRACUNIT;
|
|
|
|
y = mt->y*FRACUNIT;
|
|
|
|
sector = R_PointInSubsector(x, y)->sector;
|
|
|
|
// Z for objects
|
|
|
|
#ifdef ESLOPE
|
|
|
|
if (sector->f_slope)
|
|
|
|
mt->z = (short)(P_GetZAt(sector->f_slope, x, y)>>FRACBITS);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
mt->z = (short)(sector->floorheight>>FRACBITS);
|
|
|
|
|
|
|
|
mt->z = mt->z + (mt->options >> ZSHIFT);
|
|
|
|
|
|
|
|
if (mt->type == THING_VertexFloorZ || mt->type == THING_VertexCeilingZ) // THING_VertexFloorZ
|
|
|
|
{
|
|
|
|
for(l = 0; l < numvertexes; l++)
|
|
|
|
{
|
|
|
|
if (vertexes[l].x == mt->x*FRACUNIT && vertexes[l].y == mt->y*FRACUNIT)
|
|
|
|
{
|
|
|
|
if (mt->type == THING_VertexFloorZ)
|
|
|
|
{
|
|
|
|
vertexes[l].z = mt->z*FRACUNIT;
|
|
|
|
//I_Error("Z value: %i", vertexes[l].z/FRACUNIT);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vertexes[l].z = mt->z*FRACUNIT; // celing floor
|
|
|
|
}
|
|
|
|
vt_found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//mt->type = 0; // VPHYSICS: Dynamic slopes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (vt_found)
|
|
|
|
{
|
|
|
|
for (k = 0; k < numsectors; k++)
|
|
|
|
{
|
|
|
|
sector_t *sec = §ors[k];
|
|
|
|
if (sec->linecount != 3) continue; // only works with triangular sectors
|
|
|
|
|
|
|
|
v3float_t vt1, vt2, vt3; // cross = ret->normalf
|
|
|
|
v3float_t vec1, vec2;
|
|
|
|
|
|
|
|
int vi1, vi2, vi3;
|
|
|
|
|
|
|
|
vi1 = (int)(sec->lines[0]->v1 - vertexes);
|
|
|
|
vi2 = (int)(sec->lines[0]->v2 - vertexes);
|
|
|
|
vi3 = (sec->lines[1]->v1 == sec->lines[0]->v1 || sec->lines[1]->v1 == sec->lines[0]->v2)?
|
|
|
|
(int)(sec->lines[1]->v2 - vertexes) : (int)(sec->lines[1]->v1 - vertexes);
|
|
|
|
|
|
|
|
//if (vertexes[vi1].z)
|
|
|
|
// I_Error("OSNAP %i", vertexes[vi1].z/FRACUNIT);
|
|
|
|
//if (vertexes[vi2].z)
|
|
|
|
// I_Error("OSNAP %i", vertexes[vi2].z/FRACUNIT);
|
|
|
|
//if (vertexes[vi3].z)
|
|
|
|
// I_Error("OSNAP %i", vertexes[vi3].z/FRACUNIT);
|
|
|
|
|
|
|
|
//I_Error("%i, %i", mt->z*FRACUNIT, vertexes[vi1].z);
|
|
|
|
|
|
|
|
//I_Error("%i, %i, %i", mt->x, mt->y, mt->z);
|
|
|
|
//P_SpawnMobj(mt->x*FRACUNIT, mt->y*FRACUNIT, mt->z*FRACUNIT, MT_RING);
|
|
|
|
|
|
|
|
// TODO: Make sure not to spawn in the same place 2x! (we need an object in every vertex of the
|
|
|
|
// triangle sector to setup the real vertex slopes
|
|
|
|
// Check for the vertexes of all sectors
|
|
|
|
for(q = 0; q < numvertexes; q++)
|
|
|
|
{
|
|
|
|
if (vertexes[q].x == mt->x*FRACUNIT && vertexes[q].y == mt->y*FRACUNIT)
|
|
|
|
{
|
|
|
|
//I_Error("yeah %i", vertexes[q].z);
|
|
|
|
P_SpawnMobj(vertexes[q].x, vertexes[q].y, vertexes[q].z, MT_RING);
|
|
|
|
#if 0
|
|
|
|
if ((mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z)
|
|
|
|
&& !(mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
|
|
|
|
&& !(mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z))
|
|
|
|
P_SpawnMobj(vertexes[vi1].x, vertexes[vi1].y, vertexes[vi1].z, MT_RING);
|
|
|
|
else if ((mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
|
|
|
|
&& !(mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z)
|
|
|
|
&& !(mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z))
|
|
|
|
P_SpawnMobj(vertexes[vi2].x, vertexes[vi2].y, vertexes[vi2].z, MT_BOUNCETV);
|
|
|
|
else if ((mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z)
|
|
|
|
&& !(mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
|
|
|
|
&& !(mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z))
|
|
|
|
P_SpawnMobj(vertexes[vi3].x, vertexes[vi3].y, vertexes[vi3].z, MT_GFZFLOWER1);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vt1.x = FIXED_TO_FLOAT(vertexes[vi1].x);
|
|
|
|
vt1.y = FIXED_TO_FLOAT(vertexes[vi1].y);
|
|
|
|
vt2.x = FIXED_TO_FLOAT(vertexes[vi2].x);
|
|
|
|
vt2.y = FIXED_TO_FLOAT(vertexes[vi2].y);
|
|
|
|
vt3.x = FIXED_TO_FLOAT(vertexes[vi3].x);
|
|
|
|
vt3.y = FIXED_TO_FLOAT(vertexes[vi3].y);
|
|
|
|
|
|
|
|
for(j = 0; j < 2; j++)
|
|
|
|
{
|
|
|
|
|
|
|
|
fixed_t z3;
|
|
|
|
//I_Error("Lo hicimos");
|
|
|
|
|
|
|
|
vt1.z = mt->z;//FIXED_TO_FLOAT(j==0 ? sec->floorheight : sec->ceilingheight);
|
|
|
|
vt2.z = mt->z;//FIXED_TO_FLOAT(j==0? sec->floorheight : sec->ceilingheight);
|
|
|
|
z3 = mt->z;//j==0? sec->floorheight : sec->ceilingheight; // Destination height
|
|
|
|
vt3.z = FIXED_TO_FLOAT(z3);
|
|
|
|
|
|
|
|
if (P_PointOnLineSide(vertexes[vi3].x, vertexes[vi3].y, sec->lines[0]) == 0)
|
|
|
|
{
|
|
|
|
vec1.x = vt2.x - vt3.x;
|
|
|
|
vec1.y = vt2.y - vt3.y;
|
|
|
|
vec1.z = vt2.z - vt3.z;
|
|
|
|
|
|
|
|
vec2.x = vt1.x - vt3.x;
|
|
|
|
vec2.y = vt1.y - vt3.y;
|
|
|
|
vec2.z = vt1.z - vt3.z;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vec1.x = vt1.x - vt3.x;
|
|
|
|
vec1.y = vt1.y - vt3.y;
|
|
|
|
vec1.z = vt1.z - vt3.z;
|
|
|
|
|
|
|
|
vec2.x = vt2.x - vt3.x;
|
|
|
|
vec2.y = vt2.y - vt3.y;
|
|
|
|
vec2.z = vt2.z - vt3.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
|
|
|
|
memset(ret, 0, sizeof(*ret));
|
|
|
|
|
|
|
|
{
|
|
|
|
M_CrossProduct3f(&ret->normalf, &vec1, &vec2);
|
|
|
|
|
|
|
|
// Cross product length
|
|
|
|
float len = (float)sqrt(ret->normalf.x * ret->normalf.x +
|
|
|
|
ret->normalf.y * ret->normalf.y +
|
|
|
|
ret->normalf.z * ret->normalf.z);
|
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
{
|
|
|
|
// Only happens when all vertices in this sector are on the same line.
|
|
|
|
// Let's just ignore this case.
|
|
|
|
//CONS_Printf("Slope thing at (%d,%d) lies directly on its target line.\n", (int)(x>>16), (int)(y>>16));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// cross/len
|
|
|
|
ret->normalf.x /= len;
|
|
|
|
ret->normalf.y /= len;
|
|
|
|
ret->normalf.z /= len;
|
|
|
|
|
|
|
|
// ZDoom cross = ret->normalf
|
|
|
|
// Fix backward normals
|
|
|
|
if ((ret->normalf.z < 0 && j == 0) || (ret->normalf.z > 0 && j == 1))
|
|
|
|
{
|
|
|
|
// cross = -cross
|
|
|
|
ret->normalf.x = -ret->normalf.x;
|
|
|
|
ret->normalf.y = -ret->normalf.x;
|
|
|
|
ret->normalf.z = -ret->normalf.x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
|
|
|
|
|
|
|
|
srcplane->a = FLOAT_TO_FIXED (ret->normalf.x);
|
|
|
|
srcplane->b = FLOAT_TO_FIXED (ret->normalf.y);
|
|
|
|
srcplane->c = FLOAT_TO_FIXED (ret->normalf.z);
|
|
|
|
//srcplane->ic = DivScale32 (1, srcplane->c);
|
|
|
|
srcplane->d = -TMulScale16 (srcplane->a, vertexes[vi3].x,
|
|
|
|
srcplane->b, vertexes[vi3].y,
|
|
|
|
srcplane->c, z3);
|
|
|
|
|
|
|
|
if (j == 0)
|
|
|
|
{
|
|
|
|
sec->f_slope = ret;
|
|
|
|
sec->f_slope->secplane = *srcplane;
|
|
|
|
}
|
|
|
|
else if (j == 1)
|
|
|
|
{
|
|
|
|
sec->c_slope = ret;
|
|
|
|
sec->c_slope->secplane = *srcplane;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Z_Free(datastart);
|
|
|
|
|
|
|
|
#if 0 // UDMF support
|
|
|
|
for(i = 0; i < numvertexdatas; i++)
|
|
|
|
{
|
|
|
|
if (vertexdatas[i].flags & VERTEXFLAG_ZCeilingEnabled)
|
|
|
|
{
|
|
|
|
vt_heights[1][i] = vertexdatas[i].zCeiling;
|
|
|
|
vt_found = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vertexdatas[i].flags & VERTEXFLAG_ZFloorEnabled)
|
|
|
|
{
|
|
|
|
vt_heights[0][i] = vertexdatas[i].zFloor;
|
|
|
|
vt_found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If vertexdata_t is ever extended for non-slope usage, this will obviously have to be deferred or removed.
|
|
|
|
delete[] vertexdatas;
|
|
|
|
vertexdatas = NULL;
|
|
|
|
numvertexdatas = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "p_maputl.h"
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
static void P_SlopeLineToPointo (int lineid, fixed_t x, fixed_t y, fixed_t z, boolean slopeCeil)
|
|
|
|
{
|
|
|
|
int linenum = -1;
|
|
|
|
|
|
|
|
while ((linenum = P_FindLineFromID (lineid, linenum)) != -1)
|
|
|
|
{
|
|
|
|
const line_t *line = &lines[linenum];
|
|
|
|
sector_t *sec;
|
|
|
|
secplane_t *plane;
|
|
|
|
|
|
|
|
if (P_PointOnLineSide (x, y, line) == 0)
|
|
|
|
{
|
|
|
|
sec = line->frontsector;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sec = line->backsector;
|
|
|
|
}
|
|
|
|
if (sec == NULL)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (slopeCeil)
|
|
|
|
{
|
|
|
|
plane = &sec->ceilingplane;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
plane = &sec->floorplane;
|
|
|
|
}
|
|
|
|
|
|
|
|
FVector3 p, v1, v2, cross;
|
|
|
|
|
|
|
|
p[0] = FIXED2FLOAT (line->v1->x);
|
|
|
|
p[1] = FIXED2FLOAT (line->v1->y);
|
|
|
|
p[2] = FIXED2FLOAT (plane->ZatPoint (line->v1->x, line->v1->y));
|
|
|
|
v1[0] = FIXED2FLOAT (line->dx);
|
|
|
|
v1[1] = FIXED2FLOAT (line->dy);
|
|
|
|
v1[2] = FIXED2FLOAT (plane->ZatPoint (line->v2->x, line->v2->y)) - p[2];
|
|
|
|
v2[0] = FIXED2FLOAT (x - line->v1->x);
|
|
|
|
v2[1] = FIXED2FLOAT (y - line->v1->y);
|
|
|
|
v2[2] = FIXED2FLOAT (z) - p[2];
|
|
|
|
|
|
|
|
cross = v1 ^ v2;
|
|
|
|
double len = cross.Length();
|
|
|
|
if (len == 0)
|
|
|
|
{
|
|
|
|
Printf ("Slope thing at (%d,%d) lies directly on its target line.\n", int(x>>16), int(y>>16));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cross /= len;
|
|
|
|
// Fix backward normals
|
|
|
|
if ((cross.Z < 0 && !slopeCeil) || (cross.Z > 0 && slopeCeil))
|
|
|
|
{
|
|
|
|
cross = -cross;
|
|
|
|
}
|
|
|
|
|
|
|
|
plane->a = FLOAT2FIXED (cross[0]);
|
|
|
|
plane->b = FLOAT2FIXED (cross[1]);
|
|
|
|
plane->c = FLOAT2FIXED (cross[2]);
|
|
|
|
//plane->ic = FLOAT2FIXED (1.f/cross[2]);
|
|
|
|
plane->ic = DivScale32 (1, plane->c);
|
|
|
|
plane->d = -TMulScale16 (plane->a, x,
|
|
|
|
plane->b, y,
|
|
|
|
plane->c, z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#if 0
|
|
|
|
// P_SlopeLineToPoint, start from a specific linedef number(not tag) and slope to a mapthing with the angle of the linedef
|
|
|
|
static void P_SlopeLineToPoint(int linenum)
|
|
|
|
{
|
|
|
|
line_t *line = lines + linenum;
|
|
|
|
int special = line->special;
|
|
|
|
pslope_t *fslope = NULL, *cslope = NULL;
|
|
|
|
v3float_t origin, point;
|
|
|
|
v2float_t direction;
|
|
|
|
float dz, extent;
|
|
|
|
|
|
|
|
boolean frontfloor = (special == 386 || special == 388 || special == 393);
|
|
|
|
boolean backfloor = (special == 389 || special == 391 || special == 392);
|
|
|
|
boolean frontceil = (special == 387 || special == 388 || special == 392);
|
|
|
|
boolean backceil = (special == 390 || special == 391 || special == 393);
|
|
|
|
|
|
|
|
// SoM: We don't need the line to retain its special type
|
|
|
|
line->special = 0; //SRB2CBTODO: ESLOPE: Maybe we do need it for another to check for a plane slope?
|
|
|
|
|
|
|
|
if(!frontfloor && !backfloor && !frontceil && !backceil)
|
|
|
|
{
|
|
|
|
CONS_Printf("P_SpawnSlope_Line called with non-slope line special.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!line->frontsector || !line->backsector)
|
|
|
|
{
|
|
|
|
CONS_Printf("P_SpawnSlope_Line used on a line without two sides.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
origin.x = (FIXED_TO_FLOAT(line->v2->x) + FIXED_TO_FLOAT(line->v1->x)) * 0.5f;
|
|
|
|
origin.y = (FIXED_TO_FLOAT(line->v2->y) + FIXED_TO_FLOAT(line->v1->y)) * 0.5f;
|
|
|
|
|
|
|
|
if(frontfloor || frontceil)
|
|
|
|
{
|
|
|
|
// Do the front sector
|
|
|
|
direction.x = line->nx;
|
|
|
|
direction.y = line->ny;
|
|
|
|
|
|
|
|
extent = P_GetExtent(line->frontsector, line, &origin, &direction);
|
|
|
|
|
|
|
|
if(extent < 0.0f)
|
|
|
|
{
|
|
|
|
CONS_Printf("P_SpawnSlope_Line failed to get frontsector extent on line number %i\n", linenum);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// reposition the origin according to the extent
|
|
|
|
point.x = origin.x + direction.x * extent;
|
|
|
|
point.y = origin.y + direction.y * extent;
|
|
|
|
direction.x = -direction.x;
|
|
|
|
direction.y = -direction.y;
|
|
|
|
|
|
|
|
// CONS_Printf("Test: X: %f, Y: %f\n", origin.x, origin.y);
|
|
|
|
|
|
|
|
if(frontfloor)
|
|
|
|
{
|
|
|
|
point.z = FIXED_TO_FLOAT(line->frontsector->floorheight); // Startz
|
|
|
|
dz = (FIXED_TO_FLOAT(line->backsector->floorheight) - point.z) / extent; // Destinationz
|
|
|
|
|
|
|
|
fslope = line->frontsector->f_slope =
|
|
|
|
P_MakeSlope(&point, &direction, dz, false);
|
|
|
|
|
|
|
|
// Sync the linedata of the line that started this slope
|
|
|
|
// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
|
|
|
|
line->frontsector->f_slope->sourceline = line;
|
|
|
|
|
|
|
|
// Remember the way the slope is formed
|
|
|
|
fixed_t highest = line->frontsector->floorheight > line->backsector->floorheight ?
|
|
|
|
line->frontsector->floorheight : line->backsector->floorheight;
|
|
|
|
fixed_t lowest = line->frontsector->floorheight < line->backsector->floorheight ?
|
|
|
|
line->frontsector->floorheight : line->backsector->floorheight;
|
|
|
|
// This line special sets extra clipping data for the frontsector's slope
|
|
|
|
fslope->highz = line->frontsector->f_slope->highz = highest;
|
|
|
|
fslope->lowz = line->frontsector->f_slope->lowz = lowest;
|
|
|
|
|
|
|
|
// SRB2CBTODO: Get XY angle of a slope and then awesome physics! // ESLOPE:
|
|
|
|
//fslope->zangle = line->frontsector->f_slope->zangle = P_GetSlopezangle(line->frontsector, highvert, lowvert);
|
|
|
|
//100*(ANG45/45);//R_PointToAngle2(direction.x, direction.y, origin.x, origin.y);
|
|
|
|
// Get slope XY angle with secplane_t
|
|
|
|
secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
|
|
|
|
// ZDoom secplane port!
|
|
|
|
// secplane_t! woot!
|
|
|
|
// ret = f_slope or c_slope
|
|
|
|
srcplane->a = FLOAT_TO_FIXED (fslope->normalf.x); // cross[0]
|
|
|
|
srcplane->b = FLOAT_TO_FIXED (fslope->normalf.y); // cross[1]
|
|
|
|
srcplane->c = FLOAT_TO_FIXED (fslope->normalf.z); // cross[2]
|
|
|
|
//plane->ic = FLOAT_TO_FIXED (1.f/cross[2]);
|
|
|
|
srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c)
|
|
|
|
#ifdef SLOPETHINGS // For setting thing-based slopes
|
|
|
|
srcplane->d = -TMulScale16 (plane->a, x,
|
|
|
|
plane->b, y,
|
|
|
|
plane->c, z);
|
|
|
|
#endif
|
|
|
|
//srcheight = isceiling ? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
|
|
|
|
//destheight = isceiling ? refsec->GetPlaneTexZ(sector_t::floor) : refsec->GetPlaneTexZ(sector_t::ceiling);
|
|
|
|
//P_GetZAtf(ret, v2.x, v2.y)
|
|
|
|
// destheight takes the destination height used in dz
|
|
|
|
srcplane->d = -TMulScale16 (srcplane->a, line->v1->x,
|
|
|
|
srcplane->b, line->v1->y,
|
|
|
|
srcplane->c, line->backsector->floorheight);
|
|
|
|
|
|
|
|
// Sync the secplane!
|
|
|
|
fslope->secplane = line->frontsector->f_slope->secplane = *srcplane;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// P_SpawnSlopeMakers
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
#if 0
|
|
|
|
void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt)
|
|
|
|
{
|
|
|
|
FMapThing *mt;
|
|
|
|
|
|
|
|
for (mt = firstmt; mt < lastmt; ++mt)
|
|
|
|
{
|
|
|
|
if ((mt->type >= THING_SlopeFloorPointLine &&
|
|
|
|
mt->type <= THING_SetCeilingSlope) ||
|
|
|
|
mt->type==THING_VavoomFloor || mt->type==THING_VavoomCeiling)
|
|
|
|
{
|
|
|
|
fixed_t x, y, z;
|
|
|
|
secplane_t *refplane;
|
|
|
|
sector_t *sec;
|
|
|
|
|
|
|
|
x = mt->x;
|
|
|
|
y = mt->y;
|
|
|
|
sec = P_PointInSector (x, y);
|
|
|
|
if (mt->type & 1)
|
|
|
|
{
|
|
|
|
refplane = &sec->ceilingplane;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
refplane = &sec->floorplane;
|
|
|
|
}
|
|
|
|
z = refplane->ZatPoint (x, y) + (mt->z);
|
|
|
|
if (mt->type==THING_VavoomFloor || mt->type==THING_VavoomCeiling)
|
|
|
|
{
|
|
|
|
P_VavoomSlope(sec, mt->thingid, x, y, mt->z, mt->type & 1);
|
|
|
|
}
|
|
|
|
else if (mt->type <= THING_SlopeCeilingPointLine)
|
|
|
|
{
|
|
|
|
P_SlopeLineToPoint (mt->args[0], x, y, z, mt->type & 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
P_SetSlope (refplane, mt->type & 1, mt->angle, mt->args[0], x, y, z);
|
|
|
|
}
|
|
|
|
mt->type = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (mt = firstmt; mt < lastmt; ++mt)
|
|
|
|
{
|
|
|
|
if (mt->type == THING_CopyFloorPlane ||
|
|
|
|
mt->type == THING_CopyCeilingPlane)
|
|
|
|
{
|
|
|
|
P_CopyPlane (mt->args[0], mt->x, mt->y, mt->type & 1);
|
|
|
|
mt->type = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
P_SetSlopesFromVertexHeights(firstmt, lastmt);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
//
|
|
|
|
// Various utilities related to slopes
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_GetZAt
|
|
|
|
//
|
|
|
|
// Returns the height of the sloped plane at (x, y) as a fixed_t
|
|
|
|
//
|
|
|
|
fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
|
|
|
|
{
|
|
|
|
fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) +
|
|
|
|
FixedMul(y - slope->o.y, slope->d.y);
|
|
|
|
|
|
|
|
return slope->o.z + FixedMul(dist, slope->zdelta);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_GetZAtf
|
|
|
|
//
|
|
|
|
// Returns the height of the sloped plane at (x, y) as a float
|
|
|
|
//
|
|
|
|
float P_GetZAtf(pslope_t *slope, float x, float y)
|
|
|
|
{
|
|
|
|
//if (!slope) // SRB2CBTODO: keep this when done with debugging
|
|
|
|
// I_Error("P_GetZAtf: slope parameter is NULL");
|
|
|
|
|
|
|
|
float dist = (x - slope->of.x) * slope->df.x + (y - slope->of.y) * slope->df.y;
|
|
|
|
return slope->of.z + (dist * slope->zdeltaf);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_DistFromPlanef
|
|
|
|
//
|
|
|
|
float P_DistFromPlanef(const v3float_t *point, const v3float_t *pori,
|
|
|
|
const v3float_t *pnormal)
|
|
|
|
{
|
|
|
|
return (point->x - pori->x) * pnormal->x +
|
|
|
|
(point->y - pori->y) * pnormal->y +
|
|
|
|
(point->z - pori->z) * pnormal->z;
|
|
|
|
}
|
|
|
|
|
|
|
|
// EOF
|
|
|
|
#endif // #ifdef ESLOPE
|
|
|
|
|