//----------------------------------------------------------------------------
bool ConvexPolyhedron::ComputeSilhouette (vector<Vector3>& rkTerminator,
        const Vector3& rkEye, const Plane& rkPlane, const Vector3& rkU,
        const Vector3& rkV, vector<Vector2>& rkSilhouette)
{
    Real fEDist = rkPlane.DistanceTo(rkEye);  // assert:  fEDist > 0

    // closest planar point to E is K = E-dist*N
    Vector3 kClosest = rkEye - fEDist*rkPlane.Normal();

    // project polyhedron points onto plane
    for (int i = 0; i < (int)rkTerminator.size(); i++)
    {
        Vector3& rkPoint = rkTerminator[i];

        Real fVDist = rkPlane.DistanceTo(rkPoint);
        if ( fVDist >= fEDist )
        {
            // cannot project vertex onto plane
            return false;
        }

        // compute projected point Q
        Real fRatio = fEDist/(fEDist-fVDist);
        Vector3 kProjected = rkEye + fRatio*(rkPoint - rkEye);

        // compute (x,y) so that Q = K+x*U+y*V+z*N
        Vector3 kDiff = kProjected - kClosest;
        rkSilhouette.push_back(Vector2(rkU.Dot(kDiff),rkV.Dot(kDiff)));
    }

    return true;
}
Example #2
0
bool Plane::PlanePlaneIntersection(const Plane &P1, const Plane &P2, Line3D &L)
{
    float Denominator = P1.a * P2.b - P1.b * P2.a;
    if(Denominator == 0.0f)
    {
        // this case should be handled by switching axes...
        return false;
    }
    L.P0 = Vec3f((P2.d * P1.b - P1.d * P2.b) / Denominator, (P1.d * P2.a - P2.d * P1.a) / Denominator, 0.0f);

    L.D = Vec3f::Cross(P1.Normal(), P2.Normal());
    if(L.D.Length() == 0.0f)
    {
        return false;
    }
    L.D = Vec3f::Normalize(L.D);

    return true;
}
Example #3
0
//----------------------------------------------------------------------------
bool Mgc::TestIntersection (const Plane& rkPlane, const Sphere& rkSphere,
    bool bUnitNormal)
{
    Vector3 kNormal = rkPlane.Normal();
    Real fConstant = rkPlane.Constant();
    if ( !bUnitNormal )
    {
        Real fLength = kNormal.Unitize();
        fConstant /= fLength;
    }

    Real fPseudoDistance = kNormal.Dot(rkSphere.Center()) - fConstant;
    return Math::FAbs(fPseudoDistance) <= rkSphere.Radius();
}
Example #4
0
//----------------------------------------------------------------------------
bool Mgc::Culled (const Plane& rkPlane, const Sphere& rkSphere,
    bool bUnitNormal)
{
    Vector3 kNormal = rkPlane.Normal();
    Real fConstant = rkPlane.Constant();
    if ( !bUnitNormal )
    {
        Real fLength = kNormal.Unitize();
        fConstant /= fLength;
    }

    Real fTmp = kNormal.Dot(rkSphere.Center()) - fConstant;
    return fTmp <= -rkSphere.Radius();
}
//----------------------------------------------------------------------------
bool Mgc::Culled (const Plane& rkPlane, const Ellipsoid& rkEllipsoid,
    bool bUnitNormal)
{
    Vector3 kNormal = rkPlane.Normal();
    Real fConstant = rkPlane.Constant();
    if ( !bUnitNormal )
    {
        Real fLength = kNormal.Unitize();
        fConstant /= fLength;
    }

    Real fDiscr = kNormal.Dot(rkEllipsoid.InverseA()*kNormal);
    Real fRoot = Math::Sqrt(Math::FAbs(fDiscr));
    Real fSDist = kNormal.Dot(rkEllipsoid.Center()) - fConstant;
    return fSDist <= -fRoot;
}
//----------------------------------------------------------------------------
bool Mgc::Culled (const Plane& rkPlane, const Lozenge& rkLozenge,
    bool bUnitNormal)
{
    Vector3 kNormal = rkPlane.Normal();
    Real fConstant = rkPlane.Constant();
    if ( !bUnitNormal )
    {
        Real fLength = kNormal.Unitize();
        fConstant /= fLength;
    }

    Real fTmp00 = kNormal.Dot(rkLozenge.Origin()) - fConstant;
    if ( fTmp00 < 0.0f )
    {
        Real fDotNE0 = kNormal.Dot(rkLozenge.Edge0());
        Real fTmp10 = fTmp00 + fDotNE0;
        if ( fTmp10 < 0.0f )
        {
            Real fDotNE1 = kNormal.Dot(rkLozenge.Edge1());
            Real fTmp01 = fTmp00 + fDotNE1;
            if ( fTmp01 < 0.0f )
            {
                Real fTmp11 = fTmp10 + fDotNE1;
                if ( fTmp11 < 0.0f )
                {
                    // all four lozenge corners on negative side of plane
                    if ( fTmp00 <= fTmp10 )
                    {
                        if ( fTmp00 <= fTmp01 )
                            return fTmp00 <= -rkLozenge.Radius();
                        else
                            return fTmp01 <= -rkLozenge.Radius();
                    }
                    else
                    {
                        if ( fTmp10 <= fTmp11 )
                            return fTmp10 <= -rkLozenge.Radius();
                        else
                            return fTmp11 <= -rkLozenge.Radius();
                    }
                }
            }
        }
    }

    return false;
}
//----------------------------------------------------------------------------
bool Mgc::TestIntersection (const Plane& rkPlane, const Lozenge& rkLozenge,
    bool bUnitNormal)
{
    Vector3 kNormal = rkPlane.Normal();
    Real fConstant = rkPlane.Constant();
    if ( !bUnitNormal )
    {
        Real fLength = kNormal.Unitize();
        fConstant /= fLength;
    }

    Vector3 kC10 = rkLozenge.Origin() + rkLozenge.Edge0();
    Vector3 kC01 = rkLozenge.Origin() + rkLozenge.Edge1();
    Vector3 kC11 = kC10 + rkLozenge.Edge1();

    Real fTmp00 = kNormal.Dot(rkLozenge.Origin()) - fConstant;
    Real fTmp10 = kNormal.Dot(kC10) - fConstant;
    if ( fTmp00*fTmp10 <= 0.0f )
    {
        // two lozenge ends on opposite sides of the plane
        return true;
    }

    Real fTmp01 = kNormal.Dot(kC01) - fConstant;
    if ( fTmp00*fTmp01 <= 0.0f )
    {
        // two lozenge ends on opposite sides of the plane
        return true;
    }

    Real fTmp11 = kNormal.Dot(kC11) - fConstant;
    if ( fTmp10*fTmp11 <= 0.0f )
    {
        // two lozenge ends on opposite sides of the plane
        return true;
    }

    return Math::FAbs(fTmp00) <= rkLozenge.Radius()
        || Math::FAbs(fTmp10) <= rkLozenge.Radius()
        || Math::FAbs(fTmp01) <= rkLozenge.Radius()
        || Math::FAbs(fTmp11) <= rkLozenge.Radius();
}
//----------------------------------------------------------------------------
bool Mgc::FindIntersection (const Plane& rkPlane0, const Plane& rkPlane1,
    Line3& rkLine)
{
    // If Cross(N0,N1) is zero, then either planes are parallel and separated
    // or the same plane.  In both cases, 'false' is returned.  Otherwise,
    // the intersection line is
    //
    //   L(t) = t*Cross(N0,N1) + c0*N0 + c1*N1
    //
    // for some coefficients c0 and c1 and for t any real number (the line
    // parameter).  Taking dot products with the normals,
    //
    //   d0 = Dot(N0,L) = c0*Dot(N0,N0) + c1*Dot(N0,N1)
    //   d1 = Dot(N1,L) = c0*Dot(N0,N1) + c1*Dot(N1,N1)
    //
    // which are two equations in two unknowns.  The solution is
    //
    //   c0 = (Dot(N1,N1)*d0 - Dot(N0,N1)*d1)/det
    //   c1 = (Dot(N0,N0)*d1 - Dot(N0,N1)*d0)/det
    //
    // where det = Dot(N0,N0)*Dot(N1,N1)-Dot(N0,N1)^2.

    Real fN00 = rkPlane0.Normal().SquaredLength();
    Real fN01 = rkPlane0.Normal().Dot(rkPlane1.Normal());
    Real fN11 = rkPlane1.Normal().SquaredLength();
    Real fDet = fN00*fN11 - fN01*fN01;

    if ( Math::FAbs(fDet) < gs_fEpsilon )
        return false;

    Real fInvDet = 1.0f/fDet;
    Real fC0 = (fN11*rkPlane0.Constant() - fN01*rkPlane1.Constant())*fInvDet;
    Real fC1 = (fN00*rkPlane1.Constant() - fN01*rkPlane0.Constant())*fInvDet;

    rkLine.Direction() = rkPlane0.Normal().Cross(rkPlane1.Normal());
    rkLine.Origin() = fC0*rkPlane0.Normal() + fC1*rkPlane1.Normal();
    return true;
}
//----------------------------------------------------------------------------
void Mgc::PerspProjEllipsoid (const GeneralEllipsoid& rkEllipsoid,
                              const Vector3& rkEye, const Plane& rkPlane, GeneralEllipse& rkEllipse)
{
    // compute matrix M
    Vector3 kAE = rkEllipsoid.m_kA*rkEye;
    Real fEAE = rkEye.Dot(kAE);
    Real fBE = rkEllipsoid.m_kB.Dot(rkEye);
    Real fTmp = 4.0f*(fEAE + fBE + rkEllipsoid.m_fC);
    Vector3 kTmp = rkEllipsoid.m_kB + 2.0f*kAE;

    Matrix3 kMat;
    kMat[0][0] = kTmp.x*kTmp.x - fTmp*rkEllipsoid.m_kA[0][0];
    kMat[0][1] = kTmp.x*kTmp.y - fTmp*rkEllipsoid.m_kA[0][1];
    kMat[0][2] = kTmp.x*kTmp.z - fTmp*rkEllipsoid.m_kA[0][2];
    kMat[1][1] = kTmp.y*kTmp.y - fTmp*rkEllipsoid.m_kA[1][1];
    kMat[1][2] = kTmp.y*kTmp.z - fTmp*rkEllipsoid.m_kA[1][2];
    kMat[2][2] = kTmp.z*kTmp.z - fTmp*rkEllipsoid.m_kA[2][2];
    kMat[1][0] = kMat[0][1];
    kMat[2][0] = kMat[0][2];
    kMat[2][1] = kMat[1][2];

    // Normalize N and construct U and V so that {U,V,N} forms a
    // right-handed, orthonormal basis.
    Vector3 kU, kV, kN = rkPlane.Normal();
    Vector3::GenerateOrthonormalBasis(kU,kV,kN,false);

    // compute coefficients for projected ellipse
    Vector3 kMU = kMat*kU, kMV = kMat*kV, kMN = kMat*kN;
    Real fDmNE = rkPlane.Constant() - kN.Dot(rkEye);

    rkEllipse.m_kA[0][0] = kU.Dot(kMU);
    rkEllipse.m_kA[0][1] = kU.Dot(kMV);
    rkEllipse.m_kA[1][1] = kV.Dot(kMV);
    rkEllipse.m_kA[1][0] = rkEllipse.m_kA[0][1];
    rkEllipse.m_kB.x = 2.0f*fDmNE*(kU.Dot(kMN));
    rkEllipse.m_kB.y = 2.0f*fDmNE*(kV.Dot(kMN));
    rkEllipse.m_fC = fDmNE*fDmNE*(kN.Dot(kMN));
}
Example #10
0
  APlot Camera::GetPlot(int x, int y, const Plane & plane) const
  {
    real tx = real(fScreenWidth)/2;
    real ty = real(fScreenHeight)/2;
    real f = real( min(tx,ty))*fZoom;
    real sx = (x-tx)/f;
    real sy = (y-ty)/f;
    Vector3 origin(0,0,-fFocal);
    origin = origin+fTranslation;
    origin = (!fRotation)*origin;
    Vector3 pointed(sx, sy, 0);
    pointed = pointed+fTranslation;
    pointed = (!fRotation)*pointed;
    Vector3 director = pointed-origin;
    Vector3 normal = plane.Normal();

    real denom = director*normal;
    if (abs(denom) < zero) return APlot();
    real t = (plane.GetDist() - real(origin*normal))/denom;

    Vector3 result = origin + director*t;
    return result;
  }
Example #11
0
void GLWall::SetupLights()
{
	float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2};
	Plane p;

	lightdata.Clear();
	p.Init(vtx,4);

	if (!p.ValidNormal()) 
	{
		return;
	}
	for(int i=0;i<2;i++)
	{
		FLightNode *node;
		if (!seg->bPolySeg)
		{
			// Iterate through all dynamic lights which touch this wall and render them
			if (seg->sidedef)
			{
				node = seg->sidedef->lighthead[i];
			}
			else node = NULL;
		}
		else if (sub)
		{
			// To avoid constant rechecking for polyobjects use the subsector's lightlist instead
			node = sub->lighthead[i];
		}
		else node = NULL;

		while (node)
		{
			if (!(node->lightsource->flags2&MF2_DORMANT))
			{
				iter_dlight++;

				Vector fn, pos;

				float x = FIXED2FLOAT(node->lightsource->x);
				float y = FIXED2FLOAT(node->lightsource->y);
				float z = FIXED2FLOAT(node->lightsource->z);
				float dist = fabsf(p.DistToPoint(x, z, y));
				float radius = (node->lightsource->GetRadius() * gl_lights_size);
				float scale = 1.0f / ((2.f * radius) - dist);

				if (radius > 0.f && dist < radius)
				{
					Vector nearPt, up, right;

					pos.Set(x,z,y);
					fn=p.Normal();
					fn.GetRightUp(right, up);

					Vector tmpVec = fn * dist;
					nearPt = pos + tmpVec;

					Vector t1;
					int outcnt[4]={0,0,0,0};
					texcoord tcs[4];

					// do a quick check whether the light touches this polygon
					for(int i=0;i<4;i++)
					{
						t1.Set(&vtx[i*3]);
						Vector nearToVert = t1 - nearPt;
						tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
						tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f;

						if (tcs[i].u<0) outcnt[0]++;
						if (tcs[i].u>1) outcnt[1]++;
						if (tcs[i].v<0) outcnt[2]++;
						if (tcs[i].v>1) outcnt[3]++;

					}
					if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) 
					{
						gl_GetLight(p, node->lightsource, Colormap.colormap, true, false, lightdata);
					}
				}
			}
			node = node->nextLight;
		}
	}
	int numlights[3];

	lightdata.Combine(numlights, gl.MaxLights());
	if (numlights[2] > 0)
	{
		draw_dlight+=numlights[2]/2;
		gl_RenderState.EnableLight(true);
		gl_RenderState.SetLights(numlights, &lightdata.arrays[0][0]);
	}
}
Example #12
0
void BaseMesh::ClosedPlaneSplit(const Plane &P, BaseMesh &M1, BaseMesh &M2)
{
    UINT VC = VertexCount(), IC = IndexCount();
    MeshVertex *V = Vertices();
    DWORD *I = Indices();

    Vector<Vec3f> NewVertices[2];
    Vector<TriMeshFace> NewFaces[2];
    Vector<Vec2f> BoundaryVertices;
    Vector<UINT> BoundaryIndices[2];

    Vec3f OrthogonalBasis1, OrthogonalBasis2;
    Vec3f::CompleteOrthonormalBasis(P.Normal(), OrthogonalBasis1, OrthogonalBasis2);

    PerfectSplitVMapper *VMap = new PerfectSplitVMapper[VC];
    
    for(UINT VertexIndex = 0; VertexIndex < VC; VertexIndex++)
    {
        Vec3f Pos = V[VertexIndex].Pos;
        float Value = Plane::DotCoord(P, Pos);
        if(Value < 0.0f)
        {
            VMap[VertexIndex].Side = 0;
            VMap[VertexIndex].NVMap = NewVertices[0].Length();
            NewVertices[0].PushEnd(Pos);
        }
        else
        {
            VMap[VertexIndex].Side = 1;
            VMap[VertexIndex].NVMap = NewVertices[1].Length();
            NewVertices[1].PushEnd(Pos);
        }
    }

    for(UINT IndexIndex = 0; IndexIndex < IC; IndexIndex += 3)
    {
        int TSide[3];
        TSide[0] = VMap[I[IndexIndex + 0]].Side;
        TSide[1] = VMap[I[IndexIndex + 1]].Side;
        TSide[2] = VMap[I[IndexIndex + 2]].Side;

        DWORD LocalTriangleM1[6], LocalTriangleM2[6];
        LocalTriangleM2[0] = LocalTriangleM1[0] = VMap[I[IndexIndex + 0]].NVMap;
        LocalTriangleM2[1] = LocalTriangleM1[1] = VMap[I[IndexIndex + 1]].NVMap;
        LocalTriangleM2[2] = LocalTriangleM1[2] = VMap[I[IndexIndex + 2]].NVMap;

        UINT TriangleType = TSide[0] * 4 + TSide[1] * 2 + TSide[2] * 1;

        for(UINT EdgeIndex = 0; EdgeIndex < 3; EdgeIndex++)
        {
            if(PerfectEdges[TriangleType][EdgeIndex])
            {
                Vec3f Vtx1 = V[I[IndexIndex + PerfectEdgeList[EdgeIndex][0]]].Pos;
                Vec3f Vtx2 = V[I[IndexIndex + PerfectEdgeList[EdgeIndex][1]]].Pos;
                Vec3f VtxIntersect = P.IntersectLine(Vtx1, Vtx2);
                
                if(!Vec3f::WithinRect(VtxIntersect, Rectangle3f::ConstructFromTwoPoints(Vtx1, Vtx2)))
                {
                    VtxIntersect = (Vtx1 + Vtx2) * 0.5f;
                }
                
                BoundaryVertices.PushEnd(Vec2f(Vec3f::Dot(VtxIntersect, OrthogonalBasis1), Vec3f::Dot(VtxIntersect, OrthogonalBasis2)));

                LocalTriangleM1[3 + EdgeIndex] = NewVertices[0].Length();
                BoundaryIndices[0].PushEnd(NewVertices[0].Length());
                NewVertices[0].PushEnd(VtxIntersect);

                LocalTriangleM2[3 + EdgeIndex] = NewVertices[1].Length();
                BoundaryIndices[1].PushEnd(NewVertices[1].Length());
                NewVertices[1].PushEnd(VtxIntersect);
            }
        }

        for(UINT LocalTriangleIndex = 0; LocalTriangleIndex < 6; LocalTriangleIndex += 3)
        {
            if(M1Indices[TriangleType][LocalTriangleIndex] != -1)
            {
                TriMeshFace Tri;
                Tri.I[0] = LocalTriangleM1[M1Indices[TriangleType][LocalTriangleIndex + 0]];
                Tri.I[1] = LocalTriangleM1[M1Indices[TriangleType][LocalTriangleIndex + 1]];
                Tri.I[2] = LocalTriangleM1[M1Indices[TriangleType][LocalTriangleIndex + 2]];
                NewFaces[0].PushEnd(Tri);
            }
            if(M2Indices[TriangleType][LocalTriangleIndex] != -1)
            {
                TriMeshFace Tri;
                Tri.I[0] = LocalTriangleM2[M2Indices[TriangleType][LocalTriangleIndex + 0]];
                Tri.I[1] = LocalTriangleM2[M2Indices[TriangleType][LocalTriangleIndex + 1]];
                Tri.I[2] = LocalTriangleM2[M2Indices[TriangleType][LocalTriangleIndex + 2]];
                NewFaces[1].PushEnd(Tri);
            }
        }
    }

#ifdef DELAUNAY_TRIANGULATOR
    if(BoundaryVertices.Length() > 0)
    {
        Vector<DWORD> BoundaryTriangulation;
        DelaunayTriangulator::Triangulate(BoundaryVertices, BoundaryTriangulation);
        for(UINT TriangleIndex = 0; TriangleIndex < BoundaryTriangulation.Length() / 3; TriangleIndex++)
        {
            for(UINT MeshIndex = 0; MeshIndex < 2; MeshIndex++)
            {
                TriMeshFace Tri;
                Vec3f V[3];
                for(UINT LocalVertexIndex = 0; LocalVertexIndex < 3; LocalVertexIndex++)
                {
                    Tri.I[LocalVertexIndex] = BoundaryIndices[MeshIndex][UINT(BoundaryTriangulation[TriangleIndex * 3 + LocalVertexIndex])];
                    V[LocalVertexIndex] = NewVertices[MeshIndex][UINT(Tri.I[LocalVertexIndex])];
                }
                //Utility::Swap(Tri.I[0], Tri.I[1]);
                //if(Math::TriangleArea(V[0], V[1], V[2]) > 1e-5f)
                {
                    NewFaces[MeshIndex].PushEnd(Tri);
                }
            }
        }
    }
#endif

    delete[] VMap;

    M1.SetGD(GetGD());
    M2.SetGD(GetGD());
    M1.Allocate(NewVertices[0].Length(), NewFaces[0].Length());
    M2.Allocate(NewVertices[1].Length(), NewFaces[1].Length());
    
    for(UINT VertexIndex = 0; VertexIndex < NewVertices[0].Length(); VertexIndex++)
    {
        M1.Vertices()[VertexIndex].Pos = NewVertices[0][VertexIndex];
    }
    for(UINT VertexIndex = 0; VertexIndex < NewVertices[1].Length(); VertexIndex++)
    {
        M2.Vertices()[VertexIndex].Pos = NewVertices[1][VertexIndex];
    }
    
    if(NewFaces[0].Length() > 0)
    {
        memcpy(M1.Indices(), NewFaces[0].CArray(), M1.IndexCount() * sizeof(DWORD));
    }
    if(NewFaces[1].Length() > 0)
    {
        memcpy(M2.Indices(), NewFaces[1].CArray(), M2.IndexCount() * sizeof(DWORD));
    }
}
Example #13
0
void BaseMesh::CreatePlane(const Plane &P, float Length, UINT Slices, const Vec3f &Center)
{
    CreatePlane(Length, Slices, Slices);
    ApplyMatrix(Matrix4::Face(Vec3f(0.0f, 0.0f, 1.0f), P.Normal()) * Matrix4::Translation(Center));
}
//----------------------------------------------------------------------------
bool Mgc::TestIntersection (const Plane& rkPlane0, const Plane& rkPlane1)
{
    Vector3 kCross = rkPlane0.Normal().Cross(rkPlane1.Normal());
    Real fSqrLength = kCross.SquaredLength();
    return fSqrLength > gs_fEpsilon;
}
Example #15
0
void GLWall::SetupLights()
{
	if (RenderStyle == STYLE_Add && !glset.lightadditivesurfaces) return;	// no lights on additively blended surfaces.

	// check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.)
	switch (type)
	{
	case RENDERWALL_FOGBOUNDARY:
	case RENDERWALL_MIRRORSURFACE:
	case RENDERWALL_COLOR:
		return;
	}

	float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2};
	Plane p;

	lightdata.Clear();
	p.Set(&glseg);

	/*
	if (!p.ValidNormal()) 
	{
		return;
	}
	*/
	FLightNode *node;
	if (seg->sidedef == NULL)
	{
		node = NULL;
	}
	else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
	{
		node = seg->sidedef->lighthead;
	}
	else if (sub)
	{
		// Polobject segs cannot be checked per sidedef so use the subsector instead.
		node = sub->lighthead;
	}
	else node = NULL;

	// Iterate through all dynamic lights which touch this wall and render them
	while (node)
	{
		if (!(node->lightsource->flags2&MF2_DORMANT))
		{
			iter_dlight++;

			DVector3 posrel = node->lightsource->PosRelative(seg->frontsector);
			float x = posrel.X;
			float y = posrel.Y;
			float z = posrel.Z;
			float dist = fabsf(p.DistToPoint(x, z, y));
			float radius = node->lightsource->GetRadius();
			float scale = 1.0f / ((2.f * radius) - dist);
			FVector3 fn, pos;

			if (radius > 0.f && dist < radius)
			{
				FVector3 nearPt, up, right;

				pos = { x, z, y };
				fn = p.Normal();

				fn.GetRightUp(right, up);

				FVector3 tmpVec = fn * dist;
				nearPt = pos + tmpVec;

				FVector3 t1;
				int outcnt[4]={0,0,0,0};
				texcoord tcs[4];

				// do a quick check whether the light touches this polygon
				for(int i=0;i<4;i++)
				{
					t1 = FVector3(&vtx[i*3]);
					FVector3 nearToVert = t1 - nearPt;
					tcs[i].u = ((nearToVert | right) * scale) + 0.5f;
					tcs[i].v = ((nearToVert | up) * scale) + 0.5f;

					if (tcs[i].u<0) outcnt[0]++;
					if (tcs[i].u>1) outcnt[1]++;
					if (tcs[i].v<0) outcnt[2]++;
					if (tcs[i].v>1) outcnt[3]++;

				}
				if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) 
				{
					gl_GetLight(seg->frontsector->PortalGroup, p, node->lightsource, true, lightdata);
				}
			}
		}
		node = node->nextLight;
	}

	dynlightindex = GLRenderer->mLights->UploadLights(lightdata);
}
Example #16
0
void BaseMesh::CreatePlane(const Plane &p, float length, UINT slices)
{
    CreatePlane(p, length, slices, p.Normal()*-p.d);
}
void GLWall::SetupLights()
{
	// check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.)
	switch (type)
	{
	case RENDERWALL_FOGBOUNDARY:
	case RENDERWALL_MIRRORSURFACE:
	case RENDERWALL_COLOR:
	case RENDERWALL_COLORLAYER:
		return;
	}

	float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2};
	Plane p;

	lightdata.Clear();
	p.Init(vtx,4);

	if (!p.ValidNormal()) 
	{
		return;
	}
	FLightNode *node;
	if (seg->sidedef == NULL)
	{
		node = NULL;
	}
	else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
	{
		node = seg->sidedef->lighthead;
	}
	else if (sub)
	{
		// Polobject segs cannot be checked per sidedef so use the subsector instead.
		node = sub->lighthead;
	}
	else node = NULL;

	// Iterate through all dynamic lights which touch this wall and render them
	while (node)
	{
		if (!(node->lightsource->flags2&MF2_DORMANT))
		{
			iter_dlight++;

			Vector fn, pos;

			float x = FIXED2FLOAT(node->lightsource->X());
			float y = FIXED2FLOAT(node->lightsource->Y());
			float z = FIXED2FLOAT(node->lightsource->Z());
			float dist = fabsf(p.DistToPoint(x, z, y));
			float radius = (node->lightsource->GetRadius() * gl_lights_size);
			float scale = 1.0f / ((2.f * radius) - dist);

			if (radius > 0.f && dist < radius)
			{
				Vector nearPt, up, right;

				pos.Set(x,z,y);
				fn=p.Normal();
				fn.GetRightUp(right, up);

				Vector tmpVec = fn * dist;
				nearPt = pos + tmpVec;

				Vector t1;
				int outcnt[4]={0,0,0,0};
				texcoord tcs[4];

				// do a quick check whether the light touches this polygon
				for(int i=0;i<4;i++)
				{
					t1.Set(&vtx[i*3]);
					Vector nearToVert = t1 - nearPt;
					tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
					tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f;

					if (tcs[i].u<0) outcnt[0]++;
					if (tcs[i].u>1) outcnt[1]++;
					if (tcs[i].v<0) outcnt[2]++;
					if (tcs[i].v>1) outcnt[3]++;

				}
				if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) 
				{
					gl_GetLight(p, node->lightsource, true, false, lightdata);
				}
			}
		}
		node = node->nextLight;
	}

	dynlightindex = GLRenderer->mLights->UploadLights(lightdata);
}