示例#1
0
void TextureProjection::emitTextureCoordinates (std::size_t width, std::size_t height, Winding& w,
		const Vector3& normal, const Matrix4& localToWorld)
{
	if (w.size() < 3) {
		return;
	}

	Matrix4 local2tex = m_texdef.getTransform((float) width, (float) height);

	{
		Matrix4 xyz2st;
		// we don't care if it's not normalised...
		basisForNormal(matrix4_transformed_direction(localToWorld, normal), xyz2st);
		matrix4_multiply_by_matrix4(local2tex, xyz2st);
	}

	Vector3 tangent(local2tex.getTransposed().x().getVector3().getNormalised());
	Vector3 bitangent(local2tex.getTransposed().y().getVector3().getNormalised());

	matrix4_multiply_by_matrix4(local2tex, localToWorld);

	for (Winding::iterator i = w.begin(); i != w.end(); ++i) {
		Vector3 texcoord = matrix4_transformed_point(local2tex, (*i).vertex);
		(*i).texcoord[0] = texcoord[0];
		(*i).texcoord[1] = texcoord[1];

		(*i).tangent = tangent;
		(*i).bitangent = bitangent;
	}
}
示例#2
0
static Winding* NewWindingFromPlane(const brushhull_t* const hull, const int planenum)
{
    Winding*        winding;
    Winding*        front;
    Winding*        back;
    bface_t*        face;
    plane_t*        plane;

    plane = &g_mapplanes[planenum];
    winding = new Winding(plane->normal, plane->dist);

    for (face = hull->faces; face; face = face->next)
    {
        plane = &g_mapplanes[face->planenum];
        winding->Clip(plane->normal, plane->dist, &front, &back);
        delete winding;

        if (front)
        {
            delete front;
        }
        if (back)
        {
            winding = back;
        }
        else
        {
            Developer(DEVELOPER_LEVEL_ERROR, "NewFaceFromPlane returning NULL");
            return NULL;
        }
    }

    return winding;
}
示例#3
0
static void     WritePortalFile_r(const node_t* const node)
{
    int             i;
    portal_t*       p;
    Winding*        w;
    dplane_t        plane2;

    if (!node->contents)
    {
        WritePortalFile_r(node->children[0]);
        WritePortalFile_r(node->children[1]);
        return;
    }

    if (node->contents == CONTENTS_SOLID)
    {
        return;
    }

    for (p = node->portals; p;)
    {
        w = p->winding;
        if (w && p->nodes[0] == node)
        {
            if (p->nodes[0]->contents == p->nodes[1]->contents)
            {
                // write out to the file

                // sometimes planes get turned around when they are very near
                // the changeover point between different axis.  interpret the
                // plane the same way vis will, and flip the side orders if needed
                w->getPlane(plane2);
                if (DotProduct(p->plane.normal, plane2.normal) < 1.0 - ON_EPSILON)
                {                                          // backwards...
                    fprintf(pf, "%u %i %i ", w->m_NumPoints, p->nodes[1]->visleafnum, p->nodes[0]->visleafnum);
                }
                else
                {
                    fprintf(pf, "%u %i %i ", w->m_NumPoints, p->nodes[0]->visleafnum, p->nodes[1]->visleafnum);
                }

                for (i = 0; i < w->m_NumPoints; i++)
                {
                    fprintf(pf, "(%f %f %f) ", w->m_Points[i][0], w->m_Points[i][1], w->m_Points[i][2]);
                }
                fprintf(pf, "\n");
            }
        }

        if (p->nodes[0] == node)
        {
            p = p->next[0];
        }
        else
        {
            p = p->next[1];
        }
    }

}
示例#4
0
brushsplit_t Winding_ClassifyPlane(const Winding& winding, const Plane3& plane) 
{
  brushsplit_t split;
  for(Winding::const_iterator i = winding.begin(); i != winding.end(); ++i)
  {
    ++split.counts[Winding_ClassifyDistance(plane3_distance_to_point(plane, (*i).vertex), ON_EPSILON)];
  }
  return split;
}
示例#5
0
/// \brief Returns true if
/// !flipped && winding is completely BACK or ON
/// or flipped && winding is completely FRONT or ON
bool Winding_TestPlane(const Winding& winding, const Plane3& plane, bool flipped) 
{
  const int test = (flipped) ? ePlaneBack : ePlaneFront;
  for(Winding::const_iterator i = winding.begin(); i != winding.end(); ++i)
  {
    if(test == Winding_ClassifyDistance(plane3_distance_to_point(plane, (*i).vertex), ON_EPSILON))
    {
      return false;
    }
  }
  return true;
}
示例#6
0
void TextureProjection::fitTexture (std::size_t width, std::size_t height, const Vector3& normal, const Winding& w,
		float s_repeat, float t_repeat)
{
	if (w.size() < 3) {
		return;
	}

	Matrix4 st2tex = m_texdef.getTransform((float) width, (float) height);

	// the current texture transform
	Matrix4 local2tex = st2tex;
	{
		Matrix4 xyz2st;
		basisForNormal(normal, xyz2st);
		matrix4_multiply_by_matrix4(local2tex, xyz2st);
	}

	// the bounds of the current texture transform
	AABB bounds;
	for (Winding::const_iterator i = w.begin(); i != w.end(); ++i) {
		Vector3 texcoord = matrix4_transformed_point(local2tex, (*i).vertex);
		aabb_extend_by_point_safe(bounds, texcoord);
	}
	bounds.origin.z() = 0;
	bounds.extents.z() = 1;

	// the bounds of a perfectly fitted texture transform
	AABB perfect(Vector3(s_repeat * 0.5, t_repeat * 0.5, 0), Vector3(s_repeat * 0.5, t_repeat * 0.5, 1));

	// the difference between the current texture transform and the perfectly fitted transform
	Matrix4 matrix(Matrix4::getTranslation(bounds.origin - perfect.origin));
	matrix4_pivoted_scale_by_vec3(matrix, bounds.extents / perfect.extents, perfect.origin);
	matrix4_affine_invert(matrix);

	// apply the difference to the current texture transform
	matrix4_premultiply_by_matrix4(st2tex, matrix);

	setTransform((float) width, (float) height, st2tex);
	m_texdef.normalise((float) width, (float) height);
}
示例#7
0
文件: flow.cpp 项目: emileb/XashXT
// AJM: MVD
// =====================================================================================
//  ClipWindingsToBounds
//      clips all the windings with all the planes (including original face) and outputs 
//      what's left int "out"
// =====================================================================================
static void			ClipWindingsToBounds(winding_t *windings, int numwindings, plane_t *bounds, int numbounds, plane_t &original_plane, winding_t **out, int &num_out)
{
	hlassert(windings);
	hlassert(bounds);

	winding_t out_windings[MAX_PORTALS_ON_LEAF];
	num_out = 0;

	int h, i;

	*out = NULL;

	Winding wind;

	for(h = 0; h < numwindings; h++)
	{					
		// For each winding...
		// Create a winding with CWinding

		wind.initFromPoints(windings[h].points, windings[h].numpoints);

		// Clip winding to original plane
		wind.Chop(original_plane.normal, original_plane.dist);

		for(i = 0; i < numbounds, wind.Valid(); i++)
		{
			// For each bound...
			// Chop the winding to the bounds
			wind.Chop(bounds[i].normal, bounds[i].dist);
		}
		
		if(wind.Valid())
		{
			// We have a valid winding, copy to array
			wind.CopyPoints(&out_windings[num_out].points[0], out_windings[num_out].numpoints);

			num_out++;
		}
	}

	if(!num_out)		// Everything was clipped away
		return;

	// Otherwise, create out
	*out = new winding_t[num_out];

	memcpy(*out, out_windings, num_out * sizeof(winding_t));
}
示例#8
0
bool Winding::planesConcave(const Winding& w1, const Winding& w2, const Plane3& plane1, const Plane3& plane2)
{
	return !w1.testPlane(plane2, false) || !w2.testPlane(plane1, false);
}
示例#9
0
// =====================================================================================
//  GetAlternateOrigin
// =====================================================================================
void GetAlternateOrigin (const vec3_t pos, const vec3_t normal, const patch_t *patch, vec3_t &origin)
{
    const dplane_t *faceplane;
    const vec_t *faceplaneoffset;
    const vec_t *facenormal;
    dplane_t clipplane;
    Winding w;

    faceplane = getPlaneFromFaceNumber (patch->faceNumber);
    faceplaneoffset = g_face_offset[patch->faceNumber];
    facenormal = faceplane->normal;
    VectorCopy (normal, clipplane.normal);
    clipplane.dist = DotProduct (pos, clipplane.normal);

    w = *patch->winding;
    if (w.WindingOnPlaneSide (clipplane.normal, clipplane.dist) != SIDE_CROSS)
    {
        VectorCopy (patch->origin, origin);
    }
    else
    {
        w.Clip (clipplane, false);
        if (w.m_NumPoints == 0)
        {
            VectorCopy (patch->origin, origin);
        }
        else
        {
            vec3_t center;
            bool found;
            vec3_t bestpoint;
            vec_t bestdist = -1.0;
            vec3_t point;
            vec_t dist;
            vec3_t v;

            w.getCenter (center);
            found = false;

            VectorMA (center, PATCH_HUNT_OFFSET, facenormal, point);
            if (HuntForWorld (point, faceplaneoffset, faceplane, 2, 1.0, PATCH_HUNT_OFFSET))
            {
                VectorSubtract (point, center, v);
                dist = VectorLength (v);
                if (!found || dist < bestdist)
                {
                    found = true;
                    VectorCopy (point, bestpoint);
                    bestdist = dist;
                }
            }
            if (!found)
            {
                for (int i = 0; i < w.m_NumPoints; i++)
                {
                    const vec_t *p1;
                    const vec_t *p2;
                    p1 = w.m_Points[i];
                    p2 = w.m_Points[(i + 1) % w.m_NumPoints];
                    VectorAdd (p1, p2, point);
                    VectorAdd (point, center, point);
                    VectorScale (point, 1.0/3.0, point);
                    VectorMA (point, PATCH_HUNT_OFFSET, facenormal, point);
                    if (HuntForWorld (point, faceplaneoffset, faceplane, 1, 0.0, PATCH_HUNT_OFFSET))
                    {
                        VectorSubtract (point, center, v);
                        dist = VectorLength (v);
                        if (!found || dist < bestdist)
                        {
                            found = true;
                            VectorCopy (point, bestpoint);
                            bestdist = dist;
                        }
                    }
                }
            }

            if (found)
            {
                VectorCopy (bestpoint, origin);
            }
            else
            {
                VectorCopy (patch->origin, origin);
            }
        }
    }
}
示例#10
0
// =====================================================================================
//  snap_to_winding_noedge
//      first snaps the point into the winding
//      then moves the point towards the inside for at most certain distance until:
//        either 1) the point is not close to any of the edges
//        or     2) the point can not be moved any more
//      returns the maximal distance that the point can be kept away from all the edges
//      in most of the cases, the maximal distance = width; in other cases, the maximal distance < width
// =====================================================================================
vec_t			snap_to_winding_noedge(const Winding& w, const dplane_t& plane, vec_t* const point, vec_t width, vec_t maxmove)
{
    int pass;
    int numplanes;
    dplane_t *planes;
    int x;
    vec3_t v;
    vec_t newwidth;
    vec_t bestwidth;
    vec3_t bestpoint;

    snap_to_winding (w, plane, point);

    planes = (dplane_t *)malloc (w.m_NumPoints * sizeof (dplane_t));
    hlassume (planes != NULL, assume_NoMemory);
    numplanes = 0;
    for (x = 0; x < w.m_NumPoints; x++)
    {
        VectorSubtract (w.m_Points[(x + 1) % w.m_NumPoints], w.m_Points[x], v);
        CrossProduct (v, plane.normal, planes[numplanes].normal);
        if (!VectorNormalize (planes[numplanes].normal))
        {
            continue;
        }
        planes[numplanes].dist = DotProduct (w.m_Points[x], planes[numplanes].normal);
        numplanes++;
    }

    bestwidth = 0;
    VectorCopy (point, bestpoint);
    newwidth = width;

    for (pass = 0; pass < 5; pass++) // apply binary search method for 5 iterations to find the maximal distance that the point can be kept away from all the edges
    {
        bool failed;
        vec3_t newpoint;
        Winding *newwinding;

        failed = true;

        newwinding = new Winding (w);
        for (x = 0; x < numplanes && newwinding->m_NumPoints > 0; x++)
        {
            dplane_t clipplane = planes[x];
            clipplane.dist += newwidth;
            newwinding->Clip (clipplane, false);
        }

        if (newwinding->m_NumPoints > 0)
        {
            VectorCopy (point, newpoint);
            snap_to_winding (*newwinding, plane, newpoint);

            VectorSubtract (newpoint, point, v);
            if (VectorLength (v) <= maxmove + ON_EPSILON)
            {
                failed = false;
            }
        }

        delete newwinding;

        if (!failed)
        {
            bestwidth = newwidth;
            VectorCopy (newpoint, bestpoint);
            if (pass == 0)
            {
                break;
            }
            newwidth += width * pow (0.5, pass + 1);
        }
        else
        {
            newwidth -= width * pow (0.5, pass + 1);
        }
    }

    free (planes);

    VectorCopy (bestpoint, point);
    return bestwidth;
}
示例#11
0
void Winding::Divide(const dplane_t& split, Winding** front, Winding** back)
{
    vec_t           dists[MAX_POINTS_ON_WINDING];
    int             sides[MAX_POINTS_ON_WINDING];
    int             counts[3];
    vec_t           dot;
    int             i, j;
    int             maxpts;

    counts[0] = counts[1] = counts[2] = 0;

    // determine sides for each point
    for (i = 0; i < m_NumPoints; i++)
    {
        dot = DotProduct(m_Points[i], split.normal);
        dot -= split.dist;
        dists[i] = dot;
        if (dot > ON_EPSILON)
        {
            sides[i] = SIDE_FRONT;
        }
        else if (dot < -ON_EPSILON)
        {
            sides[i] = SIDE_BACK;
        }
        else
        {
            sides[i] = SIDE_ON;
        }
        counts[sides[i]]++;
    }
    sides[i] = sides[0];
    dists[i] = dists[0];

    *front = *back = NULL;

    if (!counts[0])
    {
        *back = this;   // Makes this function non-const
        return;
    }
    if (!counts[1])
    {
        *front = this;  // Makes this function non-const
        return;
    }

    maxpts = m_NumPoints + 4;                            // can't use counts[0]+2 because
    // of fp grouping errors

    Winding* f = new Winding(maxpts);
    Winding* b = new Winding(maxpts);

    *front = f;
    *back = b;

    f->m_NumPoints = 0;
    b->m_NumPoints = 0;

    for (i = 0; i < m_NumPoints; i++)
    {
        vec_t* p1 = m_Points[i];

        if (sides[i] == SIDE_ON)
        {
            VectorCopy(p1, f->m_Points[f->m_NumPoints]);
            VectorCopy(p1, b->m_Points[b->m_NumPoints]);
            f->m_NumPoints++;
            b->m_NumPoints++;
            continue;
        }
        else if (sides[i] == SIDE_FRONT)
        {
            VectorCopy(p1, f->m_Points[f->m_NumPoints]);
            f->m_NumPoints++;
        }
        else if (sides[i] == SIDE_BACK)
        {
            VectorCopy(p1, b->m_Points[b->m_NumPoints]);
            b->m_NumPoints++;
        }

        if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i])
        {
            continue;
        }

        // generate a split point
        vec3_t mid;
        unsigned int tmp = i + 1;
        if (tmp >= m_NumPoints)
        {
            tmp = 0;
        }
        vec_t* p2 = m_Points[tmp];
        dot = dists[i] / (dists[i] - dists[i + 1]);
        for (j = 0; j < 3; j++)
        {   // avoid round off error when possible
            if (split.normal[j] < 1.0 - NORMAL_EPSILON)
            {
                if (split.normal[j] > -1.0 + NORMAL_EPSILON)
                {
                    mid[j] = p1[j] + dot * (p2[j] - p1[j]);
                }
                else
                {
                    mid[j] = -split.dist;
                }
            }
            else
            {
                mid[j] = split.dist;
            }
        }

        VectorCopy(mid, f->m_Points[f->m_NumPoints]);
        VectorCopy(mid, b->m_Points[b->m_NumPoints]);
        f->m_NumPoints++;
        b->m_NumPoints++;
    }

    if (f->m_NumPoints > maxpts || b->m_NumPoints > maxpts)
    {
        Error("Winding::Divide : points exceeded estimate");
    }

    f->RemoveColinearPoints();
    b->RemoveColinearPoints();
}
示例#12
0
void            Winding::Clip(const vec3_t normal, const vec_t dist, Winding** front, Winding** back)
{
    vec_t           dists[MAX_POINTS_ON_WINDING + 4];
    int             sides[MAX_POINTS_ON_WINDING + 4];
    int             counts[3];
    vec_t           dot;
    unsigned int    i, j;
    unsigned int    maxpts;

    counts[0] = counts[1] = counts[2] = 0;

    // determine sides for each point
    for (i = 0; i < m_NumPoints; i++)
    {
        dot = DotProduct(m_Points[i], normal);
        dot -= dist;
        dists[i] = dot;
        if (dot > ON_EPSILON)
        {
            sides[i] = SIDE_FRONT;
        }
        else if (dot < -ON_EPSILON)
        {
            sides[i] = SIDE_BACK;
        }
        else
        {
            sides[i] = SIDE_ON;
        }
        counts[sides[i]]++;
    }
    sides[i] = sides[0];
    dists[i] = dists[0];

    if (!counts[0])
    {
        *front = NULL;
        *back = new Winding(*this);
        return;
    }
    if (!counts[1])
    {
        *front = new Winding(*this);
        *back = NULL;
        return;
    }

    maxpts = m_NumPoints + 4;                            // can't use counts[0]+2 because
    // of fp grouping errors

    Winding* f = new Winding(maxpts);
    Winding* b = new Winding(maxpts);

    *front = f;
    *back = b;

    f->m_NumPoints = 0;
    b->m_NumPoints = 0;

    for (i = 0; i < m_NumPoints; i++)
    {
        vec_t* p1 = m_Points[i];

        if (sides[i] == SIDE_ON)
        {
            VectorCopy(p1, f->m_Points[f->m_NumPoints]);
            VectorCopy(p1, b->m_Points[b->m_NumPoints]);
            f->m_NumPoints++;
            b->m_NumPoints++;
            continue;
        }
        else if (sides[i] == SIDE_FRONT)
        {
            VectorCopy(p1, f->m_Points[f->m_NumPoints]);
            f->m_NumPoints++;
        }
        else if (sides[i] == SIDE_BACK)
        {
            VectorCopy(p1, b->m_Points[b->m_NumPoints]);
            b->m_NumPoints++;
        }

        if ((sides[i + 1] == SIDE_ON) | (sides[i + 1] == sides[i]))  // | instead of || for branch optimization
        {
            continue;
        }

        // generate a split point
        vec3_t mid;
        unsigned int tmp = i + 1;
        if (tmp >= m_NumPoints)
        {
            tmp = 0;
        }
        vec_t* p2 = m_Points[tmp];
        dot = dists[i] / (dists[i] - dists[i + 1]);
#if 0
        for (j = 0; j < 3; j++)
        {   // avoid round off error when possible
            if (normal[j] < 1.0 - NORMAL_EPSILON)
            {
                if (normal[j] > -1.0 + NORMAL_EPSILON)
                {
                    mid[j] = p1[j] + dot * (p2[j] - p1[j]);
                }
                else
                {
                    mid[j] = -dist;
                }
            }
            else
            {
                mid[j] = dist;
            }
        }
#else
        for (j = 0; j < 3; j++)
        {   // avoid round off error when possible
            if (normal[j] == 1)
                mid[j] = dist;
            else if (normal[j] == -1)
                mid[j] = -dist;
            else
                mid[j] = p1[j] + dot * (p2[j] - p1[j]);
        }
#endif

        VectorCopy(mid, f->m_Points[f->m_NumPoints]);
        VectorCopy(mid, b->m_Points[b->m_NumPoints]);
        f->m_NumPoints++;
        b->m_NumPoints++;
    }

    if ((f->m_NumPoints > maxpts) | (b->m_NumPoints > maxpts)) // | instead of || for branch optimization
    {
        Error("Winding::Clip : points exceeded estimate");
    }
    if ((f->m_NumPoints > MAX_POINTS_ON_WINDING) | (b->m_NumPoints > MAX_POINTS_ON_WINDING)) // | instead of || for branch optimization
    {
        Error("Winding::Clip : MAX_POINTS_ON_WINDING");
    }
    f->RemoveColinearPoints();
    b->RemoveColinearPoints();
}