mirror of
https://github.com/ZDoom/zdbsp.git
synced 2024-11-24 12:51:24 +00:00
6858d9b1c7
SVN r229 (trunk)
167 lines
3.5 KiB
C++
167 lines
3.5 KiB
C++
/*
|
|
Determine what side of a splitter a seg lies on. (SSE2 version)
|
|
Copyright (C) 2002-2006 Randy Heit
|
|
|
|
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
#ifndef DISABLE_SSE
|
|
|
|
#include "zdbsp.h"
|
|
#include "nodebuild.h"
|
|
|
|
#define FAR_ENOUGH 17179869184.f // 4<<32
|
|
|
|
// You may notice that this function is identical to ClassifyLine2.
|
|
// The reason it is SSE is because this file is explicitly compiled
|
|
// with SSE math enabled, but the other files are not.
|
|
|
|
int FNodeBuilder::ClassifyLineSSE1 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2)
|
|
{
|
|
const FPrivVert *v1 = &Vertices[seg->v1];
|
|
const FPrivVert *v2 = &Vertices[seg->v2];
|
|
|
|
double d_x1 = double(node.x);
|
|
double d_y1 = double(node.y);
|
|
double d_dx = double(node.dx);
|
|
double d_dy = double(node.dy);
|
|
double d_xv1 = double(v1->x);
|
|
double d_xv2 = double(v2->x);
|
|
double d_yv1 = double(v1->y);
|
|
double d_yv2 = double(v2->y);
|
|
|
|
double s_num1 = (d_y1 - d_yv1) * d_dx - (d_x1 - d_xv1) * d_dy;
|
|
double s_num2 = (d_y1 - d_yv2) * d_dx - (d_x1 - d_xv2) * d_dy;
|
|
|
|
int nears = 0;
|
|
|
|
if (s_num1 <= -FAR_ENOUGH)
|
|
{
|
|
if (s_num2 <= -FAR_ENOUGH)
|
|
{
|
|
sidev1 = sidev2 = 1;
|
|
return 1;
|
|
}
|
|
if (s_num2 >= FAR_ENOUGH)
|
|
{
|
|
sidev1 = 1;
|
|
sidev2 = -1;
|
|
return -1;
|
|
}
|
|
nears = 1;
|
|
}
|
|
else if (s_num1 >= FAR_ENOUGH)
|
|
{
|
|
if (s_num2 >= FAR_ENOUGH)
|
|
{
|
|
sidev1 = sidev2 = -1;
|
|
return 0;
|
|
}
|
|
if (s_num2 <= -FAR_ENOUGH)
|
|
{
|
|
sidev1 = -1;
|
|
sidev2 = 1;
|
|
return -1;
|
|
}
|
|
nears = 1;
|
|
}
|
|
else
|
|
{
|
|
nears = 2 | int(fabs(s_num2) < FAR_ENOUGH);
|
|
}
|
|
|
|
if (nears)
|
|
{
|
|
double l = 1.f / (d_dx*d_dx + d_dy*d_dy);
|
|
if (nears & 2)
|
|
{
|
|
double dist = s_num1 * s_num1 * l;
|
|
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
|
{
|
|
sidev1 = 0;
|
|
}
|
|
else
|
|
{
|
|
sidev1 = s_num1 > 0.0 ? -1 : 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sidev1 = s_num1 > 0.0 ? -1 : 1;
|
|
}
|
|
if (nears & 1)
|
|
{
|
|
double dist = s_num2 * s_num2 * l;
|
|
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
|
{
|
|
sidev2 = 0;
|
|
}
|
|
else
|
|
{
|
|
sidev2 = s_num2 > 0.0 ? -1 : 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sidev2 = s_num2 > 0.0 ? -1 : 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sidev1 = s_num1 > 0.0 ? -1 : 1;
|
|
sidev2 = s_num2 > 0.0 ? -1 : 1;
|
|
}
|
|
|
|
if ((sidev1 | sidev2) == 0)
|
|
{ // seg is coplanar with the splitter, so use its orientation to determine
|
|
// which child it ends up in. If it faces the same direction as the splitter,
|
|
// it goes in front. Otherwise, it goes in back.
|
|
|
|
if (node.dx != 0)
|
|
{
|
|
if ((node.dx > 0 && v2->x > v1->x) || (node.dx < 0 && v2->x < v1->x))
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((node.dy > 0 && v2->y > v1->y) || (node.dy < 0 && v2->y < v1->y))
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
else if (sidev1 <= 0 && sidev2 <= 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (sidev1 >= 0 && sidev2 >= 0)
|
|
{
|
|
return 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#endif
|