summaryrefslogtreecommitdiff
path: root/hammer/clipcode.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/clipcode.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'hammer/clipcode.cpp')
-rw-r--r--hammer/clipcode.cpp348
1 files changed, 348 insertions, 0 deletions
diff --git a/hammer/clipcode.cpp b/hammer/clipcode.cpp
new file mode 100644
index 0000000..d3bcc14
--- /dev/null
+++ b/hammer/clipcode.cpp
@@ -0,0 +1,348 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#include "stdafx.h"
+#include "IEditorTexture.h"
+#include "MapFace.h"
+#include "clipcode.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+static float g_vert[MAX_CLIPVERT][VERTEXSIZE];
+static int g_outCount;
+
+
+// Quick and dirty sutherland Hodgman clipper
+// Clip polygon to decal in texture space
+// JAY: This code is lame, change it later. It does way too much work per frame
+// It can be made to recursively call the clipping code and only copy the vertex list once
+int Inside( float *vert, int edge )
+{
+ switch( edge ) {
+ case 0: // left
+ if ( vert[3] > 0.0 )
+ return 1;
+ return 0;
+ case 1: // right
+ if ( vert[3] < 1.0 )
+ return 1;
+ return 0;
+
+ case 2: // top
+ if ( vert[4] > 0.0 )
+ return 1;
+ return 0;
+
+ case 3:
+ if ( vert[4] < 1.0 )
+ return 1;
+ return 0;
+ }
+ return 0;
+}
+
+
+void Intersect( float *one, float *two, int edge, float *out )
+{
+ float t;
+
+ // t is the parameter of the line between one and two clipped to the edge
+ // or the fraction of the clipped point between one & two
+ // vert[3] is u
+ // vert[4] is v
+ // vert[0], vert[1], vert[2] is X, Y, Z
+ if ( edge < 2 ) {
+ if ( edge == 0 ) { // left
+ t = ( (one[3] - 0) / (one[3] - two[3]) );
+ out[3] = 0;
+ }
+ else { // right
+ t = ( (one[3] - 1) / (one[3] - two[3]) );
+ out[3] = 1;
+ }
+ out[4] = one[4] + (two[4] - one[4]) * t;
+ }
+ else {
+ if ( edge == 2 ) { // top
+ t = ( (one[4] - 0) / (one[4] - two[4]) );
+ out[4] = 0;
+ }
+ else { // bottom
+ t = ( (one[4] - 1) / (one[4] - two[4]) );
+ out[4] = 1;
+ }
+ out[3] = one[3] + (two[3] - one[3]) * t;
+ }
+ out[0] = one[0] + (two[0] - one[0]) * t;
+ out[1] = one[1] + (two[1] - one[1]) * t;
+ out[2] = one[2] + (two[2] - one[2]) * t;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *vert -
+// vertCount -
+// *out -
+// outSize -
+// edge -
+// Output : int
+//-----------------------------------------------------------------------------
+int SHClip( float *vert, int vertCount, float *out, int outSize, int edge )
+{
+ int j, outCount;
+ float *s, *p;
+
+ outCount = 0;
+
+ s = &vert[ (vertCount-1) * VERTEXSIZE ];
+ for ( j = 0; j < vertCount; j++ ) {
+ p = &vert[ j * VERTEXSIZE ];
+ if ( Inside( p, edge ) ) {
+ if ( Inside( s, edge ) ) {
+ // Add a vertex and advance out to next vertex
+ memcpy( out, p, sizeof(float)*VERTEXSIZE );
+ outCount++;
+ out += VERTEXSIZE;
+ }
+ else {
+ Intersect( s, p, edge, out );
+ out += VERTEXSIZE;
+ outCount++;
+ memcpy( out, p, sizeof(float)*VERTEXSIZE );
+ outCount++;
+ out += VERTEXSIZE;
+ }
+ }
+ else {
+ if ( Inside( s, edge ) ) {
+ Intersect( p, s, edge, out );
+ out += VERTEXSIZE;
+ outCount++;
+ }
+ }
+
+ if (outCount >= outSize)
+ {
+ Assert(FALSE);
+ break;
+ }
+
+ s = p;
+ }
+
+ return outCount;
+}
+
+
+#define SIN_45_DEGREES ( 0.70710678118654752440084436210485f )
+
+// The world coordinate system is right handed with Z up.
+//
+// ^ Z
+// |
+// |
+// |
+//X<----|
+// \
+// \
+// \ Y
+
+//-----------------------------------------------------------------------------
+// compute the decal basis based on surface normal, and preferred saxis
+//-----------------------------------------------------------------------------
+
+static void R_DecalComputeBasis( Vector const& surfaceNormal, Vector const* pSAxis,
+ bool flipNormal, Vector* textureSpaceBasis )
+{
+ // s, t, textureSpaceNormal (T cross S = textureSpaceNormal(N))
+ // N
+ // \
+ // \
+ // \
+ // |---->S
+ // |
+ // |
+ // |T
+ // S = textureSpaceBasis[0]
+ // T = textureSpaceBasis[1]
+ // N = textureSpaceBasis[2]
+
+ // Get the surface normal.
+ textureSpaceBasis[2] = surfaceNormal;
+ if (flipNormal)
+ VectorNegate( textureSpaceBasis[2] );
+
+ if (pSAxis)
+ {
+ // T = S cross N
+ CrossProduct( *pSAxis, textureSpaceBasis[2], textureSpaceBasis[1] );
+
+ // Name sure they aren't parallel or antiparallel
+ // In that case, fall back to the normal algorithm.
+ if ( DotProduct( textureSpaceBasis[1], textureSpaceBasis[1] ) > 1e-6 )
+ {
+ // S = N cross T
+ CrossProduct( textureSpaceBasis[2], textureSpaceBasis[1], textureSpaceBasis[0] );
+
+ VectorNormalize( textureSpaceBasis[0] );
+ VectorNormalize( textureSpaceBasis[1] );
+ return;
+ }
+
+ // Fall through to the standard algorithm for parallel or antiparallel
+ }
+
+ // floor/ceiling?
+ if( fabs( surfaceNormal[2] ) > SIN_45_DEGREES )
+ {
+ textureSpaceBasis[0][0] = 1.0f;
+ textureSpaceBasis[0][1] = 0.0f;
+ textureSpaceBasis[0][2] = 0.0f;
+
+ // T = S cross N
+ CrossProduct( textureSpaceBasis[0], textureSpaceBasis[2], textureSpaceBasis[1] );
+
+ // S = N cross T
+ CrossProduct( textureSpaceBasis[2], textureSpaceBasis[1], textureSpaceBasis[0] );
+ }
+ // wall
+ else
+ {
+ textureSpaceBasis[1][0] = 0.0f;
+ textureSpaceBasis[1][1] = 0.0f;
+ textureSpaceBasis[1][2] = -1.0f;
+
+ // S = N cross T
+ CrossProduct( textureSpaceBasis[2], textureSpaceBasis[1], textureSpaceBasis[0] );
+ // T = S cross N
+ CrossProduct( textureSpaceBasis[0], textureSpaceBasis[2], textureSpaceBasis[1] );
+ }
+
+ VectorNormalize( textureSpaceBasis[0] );
+ VectorNormalize( textureSpaceBasis[1] );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Clips a texture to a face. Used for decal application.
+// NOTE : HL and HL2 generate texcoords for decals differently!!!
+// Input : pFace -
+// pDecalTex -
+// org -
+// pOutPoints -
+// Output : Returns the number of points places in the pOutPoints array.
+//-----------------------------------------------------------------------------
+int CreateClippedPoly(CMapFace *pFace, IEditorTexture *pDecalTex, Vector& org, vec5_t *pOutPoints, int nOutSize)
+{
+ float outvert[MAX_CLIPVERT][VERTEXSIZE];
+ Assert(nOutSize <= MAX_CLIPVERT); // This code uses temp buffers of this size.
+
+/*#ifdef SDK_BUILD
+ BUG: THIS IS THE HL1 VERSION! SWITCH BETWEEN THESE ALGORITHMS AT RUNTIME
+ Vector vecOrg, vecSAxis, vecTAxis;
+
+ // Copy the origin.
+ vecOrg = org;
+
+ // Get the U/V axes for this face.
+ vecSAxis = pFace->texture.UAxis;
+ vecTAxis = pFace->texture.VAxis;
+
+ float decalwidth = pDecalTex->GetWidth();
+ float decalheight = pDecalTex->GetHeight();
+
+ float scale = 1.0f;
+ IEditorTexture *pFaceTex = pFace->GetTexture();
+ float scalex = scale * (float)pFaceTex->GetWidth() / decalwidth;
+ float scaley = scale * (float)pFaceTex->GetHeight() / decalheight;
+
+ float u = DotProduct(vecSAxis, vecOrg);
+ float v = DotProduct(vecTAxis, vecOrg);
+
+ u -= decalwidth / 2;
+ v -= decalheight / 2;
+
+ u /= pFaceTex->GetWidth();
+ v /= pFaceTex->GetHeight();
+
+ // Generate texture coordinates for each vertex in decal s,t space
+ Vector *pVertex = pFace->Points;
+ float curU, curV;
+ for (int j = 0; j < pFace->nPoints; j++, pVertex++)
+ {
+ // Copy X, Y, & Z
+ g_vert[j][0] = pVertex[0][0];
+ g_vert[j][1] = pVertex[0][1];
+ g_vert[j][2] = pVertex[0][2];
+
+ // Get u, v coordinates of vertex in DECAL SPACE
+ curU = DotProduct(vecSAxis, *pVertex) / pFaceTex->GetWidth();
+ curV = DotProduct(vecTAxis, *pVertex) / pFaceTex->GetHeight();
+
+ // Generate U & V
+ g_vert[j][3] = (curU - u) * scalex; // Decal relative texture coordinates
+ g_vert[j][4] = (curV - v) * scaley;
+ }
+#else */
+ // THIS IS THE HL2 VERSION!
+ float decalScale = pDecalTex->GetDecalScale();
+ float decalWidth = pDecalTex->GetWidth();
+ float decalHeight = pDecalTex->GetHeight();
+
+ Vector textureSpaceBasis[3];
+
+ R_DecalComputeBasis( pFace->plane.normal, NULL,
+ false, textureSpaceBasis );
+
+ float u = DotProduct(textureSpaceBasis[0], org);
+ float v = DotProduct(textureSpaceBasis[1], org);
+
+ // subtract the world space dist from the center of the
+ // decal to the origin of the decal
+ u -= decalWidth * decalScale / 2.0f;
+ v -= decalHeight * decalScale / 2.0f;
+
+ float scalex = 1.0f / ( decalScale * decalWidth );
+ float scaley = 1.0f / ( decalScale * decalHeight );
+
+ // Generate texture coordinates for each vertex in decal s,t space
+ Vector *pVertex = pFace->Points;
+ float curU, curV;
+ for (int j = 0; j < pFace->nPoints; j++, pVertex++)
+ {
+ // Copy X, Y, & Z
+ g_vert[j][0] = pVertex[0][0];
+ g_vert[j][1] = pVertex[0][1];
+ g_vert[j][2] = pVertex[0][2];
+
+ // Get u, v coordinates of vertex in DECAL SPACE
+ curU = DotProduct(textureSpaceBasis[0], *pVertex);
+ curV = DotProduct(textureSpaceBasis[1], *pVertex);
+
+ // Generate U & V
+ g_vert[j][3] = (curU - u) * scalex; // Decal relative texture coordinates
+ g_vert[j][4] = (curV - v) * scaley;
+ }
+// #endif
+
+ // Clip the polygon to the decal texture space
+ // FIXME: Yes this realy copies the vertex list 4 times !!
+ int nMaxVerts = min(nOutSize, MAX_CLIPVERT);
+ g_outCount = SHClip( g_vert[0], pFace->nPoints, outvert[0], nMaxVerts, 0 ); // clip left
+ g_outCount = SHClip( outvert[0], g_outCount, g_vert[0], nMaxVerts, 1 ); // clip right
+ g_outCount = SHClip( g_vert[0], g_outCount, outvert[0], nMaxVerts, 2 ); // clip top
+ g_outCount = SHClip( outvert[0], g_outCount, g_vert[0], nMaxVerts, 3 ); // clip bottom
+
+ memcpy(pOutPoints, g_vert, sizeof(vec5_t) * g_outCount);
+
+ return(g_outCount);
+}
+