Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

portal.cpp

Go to the documentation of this file.
00001 #include <windows.h>
00002 #include "portal.h"
00003 #include "locmath.h"
00004 #include "listnode.h"
00005 #include "collision.h"
00006 #include "general.h"
00007 #include "bsp.h"
00008 #include "tll.h"
00009 #include "mmgr.h"
00010 
00011 extern float Min_X, Min_Y, Min_Z, Max_X, Max_Y, Max_Z; // The bounding box variables
00012 extern int numpartitions;
00013 extern ListNode* listnode;
00014 extern LinkedList<ListNode> LeafList;
00015 extern LinkedList<ListNode> PartitionList;
00016 extern LinkedList<PORTAL> PortalList;
00017 extern int numportals;
00018 extern PORTAL* portal;
00019 extern BSP_node* root;
00020 
00021 PORTAL::PORTAL()
00022 {
00023 }
00024 
00025 PORTAL::~PORTAL()
00026 {
00027 }
00028 
00029 int PORTAL::Compare(const PORTAL& Portal)
00030 {
00031     if (linkPosition < Portal.linkPosition)
00032             return smaller;
00033       if (linkPosition > Portal.linkPosition)
00034             return bigger;
00035       else
00036             return same;
00037 }
00038 
00039 VECTOR PORTAL::GetNormal()
00040 {
00041         VECTOR temp;
00042         float ux;
00043         float uy;
00044         float uz;
00045         float vx;
00046         float vy;
00047         float vz;
00048           ux = Vertex[1].x - Vertex[0].x;
00049           uy = Vertex[1].y - Vertex[0].y;
00050           uz = Vertex[1].z - Vertex[0].z;
00051           vx = Vertex[2].x - Vertex[0].x;
00052           vy = Vertex[2].y - Vertex[0].y;
00053           vz = Vertex[2].z - Vertex[0].z;
00054           temp.x = (uy*vz)-(vy*uz);
00055           temp.y = (uz*vx)-(vz*ux);
00056           temp.z = (ux*vy)-(vx*uy);
00057         return temp;
00058 }
00059 
00060 void PORTAL::SetNormal()
00061 {
00062         float ux;
00063         float uy;
00064         float uz;
00065         float vx;
00066         float vy;
00067         float vz;
00068           ux = Vertex[1].x - Vertex[0].x;
00069           uy = Vertex[1].y - Vertex[0].y;
00070           uz = Vertex[1].z - Vertex[0].z;
00071           vx = Vertex[2].x - Vertex[0].x;
00072           vy = Vertex[2].y - Vertex[0].y;
00073           vz = Vertex[2].z - Vertex[0].z;
00074           Vertex[0].nx = (uy*vz)-(vy*uz);
00075           Vertex[0].ny = (uz*vx)-(vz*ux);
00076           Vertex[0].nz = (ux*vy)-(vx*uy);
00077         Vertex[1].nx = Vertex[0].nx;
00078           Vertex[1].ny = Vertex[0].ny;
00079           Vertex[1].nz = Vertex[0].nz;
00080           Vertex[2].nx = Vertex[0].nx;
00081           Vertex[2].ny = Vertex[0].ny;
00082           Vertex[2].nz = Vertex[0].nz;
00083 }
00084 
00085 PORTAL* CopyPortal(PORTAL* portal)
00086 {
00087     PORTAL* tempportal = new PORTAL;
00088     *tempportal = *portal;
00089     tempportal->Vertex = new VERTEX[portal->numVertices];
00090     for (int loop = 0; loop < portal->numVertices; loop++)
00091         tempportal->Vertex[loop] = portal->Vertex[loop];
00092     return tempportal;
00093 }
00094 
00095 void CreateLargePortal(POLYGON splittingPolygon, PORTAL* largePortal)
00096 {
00097 // Make large portal using planar mapping
00098     largePortal->numVertices = 4;
00099     largePortal->Vertex = new VERTEX[4];
00100     // find the primary axis plane
00101     int flag = 0;
00102     VECTOR poly_normal = splittingPolygon.GetNormal();
00103     poly_normal.Normalize();
00104 
00105     if (fabs(poly_normal.x) > fabs(poly_normal.y) && fabs(poly_normal.x) > fabs(poly_normal.z))
00106     {
00107         flag = 1;
00108         largePortal->Vertex[0].y = Min_Y;
00109         largePortal->Vertex[0].z = Max_Z;
00110         largePortal->Vertex[1].y = Min_Y;
00111         largePortal->Vertex[1].z = Min_Z;
00112         largePortal->Vertex[2].y = Max_Y;
00113         largePortal->Vertex[2].z = Min_Z;
00114         largePortal->Vertex[3].y = Max_Y;
00115         largePortal->Vertex[3].z = Max_Z;
00116     }
00117     else if (fabs(poly_normal.y) > fabs(poly_normal.x) && fabs(poly_normal.y) > fabs(poly_normal.z))
00118     {
00119         flag = 2;
00120         largePortal->Vertex[0].x = Min_X;
00121         largePortal->Vertex[0].z = Max_Z;
00122         largePortal->Vertex[1].x = Max_X;
00123         largePortal->Vertex[1].z = Max_Z;
00124         largePortal->Vertex[2].x = Max_X;
00125         largePortal->Vertex[2].z = Min_Z;
00126         largePortal->Vertex[3].x = Min_X;
00127         largePortal->Vertex[3].z = Min_Z;
00128     }
00129     else
00130     {
00131         flag = 3;
00132         largePortal->Vertex[0].x = Min_X;
00133         largePortal->Vertex[0].y = Min_Y;
00134         largePortal->Vertex[1].x = Max_X;
00135         largePortal->Vertex[1].y = Min_Y;
00136         largePortal->Vertex[2].x = Max_X;
00137         largePortal->Vertex[2].y = Max_Y;
00138         largePortal->Vertex[3].x = Min_X;
00139         largePortal->Vertex[3].y = Max_Y;
00140     }
00141 
00142     float X, Y, Z;
00143     float Distance = - (poly_normal.x * splittingPolygon.Vertex[0].x + poly_normal.y * splittingPolygon.Vertex[0].y + poly_normal.z * splittingPolygon.Vertex[0].z);
00144     switch (flag)
00145     {
00146         case 1: //YZ Plane
00147             X = - ( poly_normal.y * Min_Y + poly_normal.z * Max_Z + Distance ) / poly_normal.x;
00148             largePortal->Vertex[0].x = X;
00149             X = - ( poly_normal.y * Min_Y + poly_normal.z * Min_Z + Distance ) / poly_normal.x;
00150             largePortal->Vertex[1].x = X;
00151             X = - ( poly_normal.y * Max_Y + poly_normal.z * Min_Z + Distance ) / poly_normal.x;
00152             largePortal->Vertex[2].x = X;
00153             X = - ( poly_normal.y * Max_Y + poly_normal.z * Max_Z + Distance ) / poly_normal.x;
00154             largePortal->Vertex[3].x = X;
00155         break;
00156         case 2: //XZ Plane
00157             Y = - ( poly_normal.x * Min_X + poly_normal.z * Max_Z + Distance ) / poly_normal.y;
00158             largePortal->Vertex[0].y = Y;
00159             Y = - ( poly_normal.x * Max_X + poly_normal.z * Max_Z + Distance ) / poly_normal.y;
00160             largePortal->Vertex[1].y = Y;
00161             Y = - ( poly_normal.x * Max_X + poly_normal.z * Min_Z + Distance ) / poly_normal.y;
00162             largePortal->Vertex[2].y = Y;
00163             Y = - ( poly_normal.x * Min_X + poly_normal.z * Min_Z + Distance ) / poly_normal.y;
00164             largePortal->Vertex[3].y = Y;
00165         break;
00166         case 3: //XY Plane
00167             Z = - ( poly_normal.x * Min_X + poly_normal.y * Min_Y + Distance ) / poly_normal.z;
00168             largePortal->Vertex[0].z = Z;
00169             Z = - ( poly_normal.x * Max_X + poly_normal.y * Min_Y + Distance ) / poly_normal.z;
00170             largePortal->Vertex[1].z = Z;
00171             Z = - ( poly_normal.x * Max_X + poly_normal.y * Max_Y + Distance ) / poly_normal.z;
00172             largePortal->Vertex[2].z = Z;
00173             Z = - ( poly_normal.x * Min_X + poly_normal.y * Max_Y + Distance ) / poly_normal.z;
00174             largePortal->Vertex[3].z = Z;
00175         break;
00176     }
00177     largePortal->SetNormal();
00178 }
00179 
00180 int SplitPortal(PORTAL* portalToSplit, POLYGON planePolygon, PORTAL* front, PORTAL* back)
00181 {
00182     const int MaxVerts = 100;
00183     int numVerts = portalToSplit->numVertices;
00184     int count = 0, out_c = 0, in_c = 0, sideA, sideB, loop;
00185     VECTOR planeNormal, polysNormal, pointOnPlane, edge1, edge2, temp;
00186     VERTEX ptA, ptB, intersection, outpts[MaxVerts], inpts[MaxVerts];
00187 
00188     // get a point on the plane
00189     pointOnPlane.x = planePolygon.Vertex[0].x;
00190     pointOnPlane.y = planePolygon.Vertex[0].y;
00191     pointOnPlane.z = planePolygon.Vertex[0].z;
00192 
00193     // get the splitting planes normal
00194     edge1.x = planePolygon.Vertex[1].x - planePolygon.Vertex[0].x;
00195     edge1.y = planePolygon.Vertex[1].y - planePolygon.Vertex[0].y;
00196     edge1.z = planePolygon.Vertex[1].z - planePolygon.Vertex[0].z;
00197     edge2.x = planePolygon.Vertex[2].x - planePolygon.Vertex[0].x;
00198     edge2.y = planePolygon.Vertex[2].y - planePolygon.Vertex[0].y;
00199     edge2.z = planePolygon.Vertex[2].z - planePolygon.Vertex[0].z;
00200     planeNormal = CrossVector(edge1, edge2);
00201 
00202     // get the normal of the portal to split
00203     edge1.x = portalToSplit->Vertex[1].x - portalToSplit->Vertex[0].x;
00204     edge1.y = portalToSplit->Vertex[1].y - portalToSplit->Vertex[0].y;
00205     edge1.z = portalToSplit->Vertex[1].z - portalToSplit->Vertex[0].z;
00206     edge2.x = portalToSplit->Vertex[2].x - portalToSplit->Vertex[0].x;
00207     edge2.y = portalToSplit->Vertex[2].y - portalToSplit->Vertex[0].y;
00208     edge2.z = portalToSplit->Vertex[2].z - portalToSplit->Vertex[0].z;
00209     polysNormal = CrossVector(edge1, edge2);
00210 
00211     // check if the portal lies on the plane
00212     for (int loop = 0; loop < numVerts; loop++)
00213     {
00214         temp.x = portalToSplit->Vertex[loop].x;
00215         temp.y = portalToSplit->Vertex[loop].y;
00216         temp.z = portalToSplit->Vertex[loop].z;
00217         if (ClassifyPoint(temp, pointOnPlane, planeNormal) == 0)
00218             count++;
00219         else
00220             break;
00221     }
00222     if (count == numVerts)
00223     {
00224         if (ClassifyPoint(polysNormal, pointOnPlane, planeNormal) == 1)
00225             return Front;
00226         if (ClassifyPoint(polysNormal, pointOnPlane, planeNormal) == -1)
00227             return Back;
00228     }
00229 
00230     // find if all of the points are infront of or behind the plane
00231     int frontcount = 0, backcount = 0;
00232     for (int loop = 0; loop < numVerts; loop++)
00233     {
00234         temp.x = portalToSplit->Vertex[loop].x;
00235         temp.y = portalToSplit->Vertex[loop].y;
00236         temp.z = portalToSplit->Vertex[loop].z;
00237         if (ClassifyPoint(temp, pointOnPlane, planeNormal) == 0)
00238         {
00239             frontcount++;
00240             backcount++;
00241         }
00242         else if (ClassifyPoint(temp, pointOnPlane, planeNormal) == 1)
00243             frontcount++;
00244         else if (ClassifyPoint(temp, pointOnPlane, planeNormal) == -1)
00245             backcount++;
00246     }
00247     if (frontcount == numVerts)
00248             return Front;
00249     if (backcount == numVerts)
00250             return Back;
00251 
00252     // try to split the portal
00253     ptA = portalToSplit->Vertex[numVerts - 1];
00254     temp.x = ptA.x;
00255     temp.y = ptA.y;
00256     temp.z = ptA.z;
00257     sideA = ClassifyPoint(temp, pointOnPlane, planeNormal);
00258     for (int i = -1; ++i < numVerts;)
00259     {
00260         ptB = portalToSplit->Vertex[i];
00261         temp.x = ptB.x;
00262         temp.y = ptB.y;
00263         temp.z = ptB.z;
00264         sideB = ClassifyPoint(temp, pointOnPlane, planeNormal);
00265         if (sideB > 0)
00266         {
00267             if (sideA < 0)
00268             {
00269                 // find intersection
00270                 edge1.x = ptA.x;
00271                 edge1.y = ptA.y;
00272                 edge1.z = ptA.z;
00273                 edge2.x = ptB.x;
00274                 edge2.y = ptB.y;
00275                 edge2.z = ptB.z;
00276 
00277                 temp = GetEdgeIntersection(edge1, edge2, planePolygon);
00278                 intersection.x = temp.x;
00279                 intersection.y = temp.y;
00280                 intersection.z = temp.z;
00281 
00282                 outpts[out_c++] = inpts[in_c++] = intersection;
00283             }
00284             inpts[in_c++] = ptB;
00285         }
00286         else if (sideB < 0)
00287         {
00288             if (sideA > 0)
00289             {
00290                 // find intersection
00291                 edge1.x = ptA.x;
00292                 edge1.y = ptA.y;
00293                 edge1.z = ptA.z;
00294                 edge2.x = ptB.x;
00295                 edge2.y = ptB.y;
00296                 edge2.z = ptB.z;
00297 
00298                 temp = GetEdgeIntersection(edge1, edge2, planePolygon);
00299                 intersection.x = temp.x;
00300                 intersection.y = temp.y;
00301                 intersection.z = temp.z;
00302 
00303                 outpts[out_c++] = inpts[in_c++] = intersection;
00304             }
00305             outpts[out_c++] = ptB;
00306         }
00307         else
00308             outpts[out_c++] = inpts[in_c++] = ptB;
00309         ptA = ptB;
00310         sideA = sideB;
00311     }
00312 
00313     if (out_c == 0 || in_c == 0)
00314     {
00315         int side;
00316 
00317         for (int loop = 0; loop < numVerts; loop++)
00318         {
00319             temp.x = portalToSplit->Vertex[loop].x;
00320             temp.y = portalToSplit->Vertex[loop].y;
00321             temp.z = portalToSplit->Vertex[loop].z;
00322             side = ClassifyPoint(temp, pointOnPlane, planeNormal);
00323             if (side == 1)
00324                 return Front;
00325             else if (side == -1)
00326                 return Back;
00327         }
00328     }
00329     else
00330     {
00331         front->Vertex = new VERTEX[in_c];
00332         back->Vertex = new VERTEX[out_c];
00333         front->numVertices = in_c;
00334         back->numVertices = out_c;
00335 
00336         for (loop = 0; loop < in_c; loop++)
00337             front->Vertex[loop] = inpts[loop];
00338         for (loop = 0; loop < out_c; loop++)
00339             back->Vertex[loop] = outpts[loop];
00340         return PortalWasSplit;
00341     }
00342     return 0;
00343 }
00344 
00345 void MakePortalList()
00346 {
00347     // Create the large portals
00348     for (int loop = 1; loop <= numpartitions; loop++)
00349     {
00350         listnode = PartitionList.Get(loop);
00351         portal = new PORTAL;
00352         portal->Vertex = 0;
00353         portal->linkPosition = loop;
00354         portal->PartitionNodeId = loop;
00355         CreateLargePortal(listnode->node->partition, portal);
00356         PortalList.Insert(portal);
00357     }
00358 
00359     // Split the large portals into potential portals
00360     numportals = numpartitions;
00361     int result, portalToSplit;
00362     PORTAL* frontportal;
00363     PORTAL* backportal;
00364     for (int partition = 1; partition <= numpartitions; partition++)
00365     {
00366         listnode = PartitionList.Get(partition);
00367         portalToSplit = numportals;
00368         while (portalToSplit > 0)
00369         {
00370             frontportal = new PORTAL;
00371             backportal = new PORTAL;
00372 
00373             portal = PortalList.Get(portalToSplit);
00374             result = SplitPortal(portal, listnode->node->partition, frontportal, backportal);
00375 
00376             if (result == PortalWasSplit)
00377             {
00378                 frontportal->PartitionNodeId = portal->PartitionNodeId;
00379                 backportal->PartitionNodeId = portal->PartitionNodeId;
00380 
00381                 delete[] portal->Vertex;
00382                 portal->Vertex = 0;
00383                 PortalList.Delete(portalToSplit);
00384                 delete portal;
00385                 numportals--;
00386 
00387                 frontportal->linkPosition = ++numportals;
00388                 PortalList.Insert(frontportal);
00389                 backportal->linkPosition = ++numportals;
00390                 PortalList.Insert(backportal);
00391             }
00392             else
00393             {
00394                 delete frontportal;
00395                 delete backportal;
00396             }
00397             portalToSplit--;
00398         }
00399     }
00400 
00401     // Loop through the portals and assign a unique id
00402     for (int loop = 1; loop <= numportals; loop++)
00403     {
00404         portal = PortalList.Get(loop);
00405         portal->PortalId = loop;
00406     }
00407 }
00408 
00409 int ClassifyPortal(PORTAL* portal, POLYGON planePolygon)
00410 {
00411     int numVerts = portal->numVertices;
00412     int count = 0;
00413     VECTOR planeNormal, polysNormal, pointOnPlane, edge1, edge2, temp;
00414 
00415     // get a point on the plane
00416     pointOnPlane.x = planePolygon.Vertex[0].x;
00417     pointOnPlane.y = planePolygon.Vertex[0].y;
00418     pointOnPlane.z = planePolygon.Vertex[0].z;
00419 
00420     // get the planes normal
00421     edge1.x = planePolygon.Vertex[1].x - planePolygon.Vertex[0].x;
00422     edge1.y = planePolygon.Vertex[1].y - planePolygon.Vertex[0].y;
00423     edge1.z = planePolygon.Vertex[1].z - planePolygon.Vertex[0].z;
00424     edge2.x = planePolygon.Vertex[2].x - planePolygon.Vertex[0].x;
00425     edge2.y = planePolygon.Vertex[2].y - planePolygon.Vertex[0].y;
00426     edge2.z = planePolygon.Vertex[2].z - planePolygon.Vertex[0].z;
00427     planeNormal = CrossVector(edge1, edge2);
00428 
00429     // get the normal of the portal
00430     edge1.x = portal->Vertex[1].x - portal->Vertex[0].x;
00431     edge1.y = portal->Vertex[1].y - portal->Vertex[0].y;
00432     edge1.z = portal->Vertex[1].z - portal->Vertex[0].z;
00433     edge2.x = portal->Vertex[2].x - portal->Vertex[0].x;
00434     edge2.y = portal->Vertex[2].y - portal->Vertex[0].y;
00435     edge2.z = portal->Vertex[2].z - portal->Vertex[0].z;
00436     polysNormal = CrossVector(edge1, edge2);
00437 
00438     // check if the portal lies on the plane
00439     for (int loop = 0; loop < numVerts; loop++)
00440     {
00441         temp.x = portal->Vertex[loop].x;
00442         temp.y = portal->Vertex[loop].y;
00443         temp.z = portal->Vertex[loop].z;
00444         if (ClassifyPoint(temp, pointOnPlane, planeNormal) == 0)
00445             count++;
00446         else
00447             break;
00448     }
00449     if (count == numVerts)
00450             return OnPartition;
00451 
00452     // find if all of the points are infront of or behind the plane
00453     int result, frontcount = 0, backcount = 0;
00454     for (int loop = 0; loop < numVerts; loop++)
00455     {
00456         temp.x = portal->Vertex[loop].x;
00457         temp.y = portal->Vertex[loop].y;
00458         temp.z = portal->Vertex[loop].z;
00459         result = ClassifyPoint(temp, pointOnPlane, planeNormal);
00460         if (result == 0)
00461         {
00462             frontcount++;
00463             backcount++;
00464         }
00465         else
00466             if (result == 1)
00467                 frontcount++;
00468         else
00469             if (result == -1)
00470                 backcount++;
00471     }
00472     if (frontcount == numVerts)
00473             return Front;
00474     if (backcount == numVerts)
00475             return Back;
00476 
00477     return 0;
00478 }
00479 
00480 int ClassifyInvertedPortal(PORTAL* portal, POLYGON planePolygon)
00481 {
00482     int numVerts = portal->numVertices;
00483     int count = 0;
00484     VECTOR planeNormal, polysNormal, pointOnPlane, edge1, edge2, temp;
00485 
00486     // get a point on the plane
00487     pointOnPlane.x = planePolygon.Vertex[0].x;
00488     pointOnPlane.y = planePolygon.Vertex[0].y;
00489     pointOnPlane.z = planePolygon.Vertex[0].z;
00490 
00491     // get the planes normal
00492     edge1.x = planePolygon.Vertex[1].x - planePolygon.Vertex[0].x;
00493     edge1.y = planePolygon.Vertex[1].y - planePolygon.Vertex[0].y;
00494     edge1.z = planePolygon.Vertex[1].z - planePolygon.Vertex[0].z;
00495     edge2.x = planePolygon.Vertex[2].x - planePolygon.Vertex[0].x;
00496     edge2.y = planePolygon.Vertex[2].y - planePolygon.Vertex[0].y;
00497     edge2.z = planePolygon.Vertex[2].z - planePolygon.Vertex[0].z;
00498     planeNormal = CrossVector(edge1, edge2);
00499 
00500     // get the normal of the portal
00501     edge1.x = portal->Vertex[1].x - portal->Vertex[0].x;
00502     edge1.y = portal->Vertex[1].y - portal->Vertex[0].y;
00503     edge1.z = portal->Vertex[1].z - portal->Vertex[0].z;
00504     edge2.x = portal->Vertex[2].x - portal->Vertex[0].x;
00505     edge2.y = portal->Vertex[2].y - portal->Vertex[0].y;
00506     edge2.z = portal->Vertex[2].z - portal->Vertex[0].z;
00507     polysNormal = CrossVector(edge1, edge2);
00508     polysNormal.x *= -1;
00509     polysNormal.y *= -1;
00510     polysNormal.z *= -1;
00511 
00512     // check if the portal lies on the plane
00513     for (int loop = 0; loop < numVerts; loop++)
00514     {
00515         temp.x = portal->Vertex[loop].x;
00516         temp.y = portal->Vertex[loop].y;
00517         temp.z = portal->Vertex[loop].z;
00518         if (ClassifyPoint(temp, pointOnPlane, planeNormal) == 0)
00519             count++;
00520         else
00521             break;
00522     }
00523     if (count == numVerts)
00524     {
00525         if (ClassifyPoint(polysNormal, pointOnPlane, planeNormal) == 1)
00526             return Front;
00527         if (ClassifyPoint(polysNormal, pointOnPlane, planeNormal) == -1)
00528             return Back;
00529     }
00530 
00531     // find if all of the points are infront of or behind the plane
00532     int result, frontcount = 0, backcount = 0;
00533     for (int loop = 0; loop < numVerts; loop++)
00534     {
00535         temp.x = portal->Vertex[loop].x;
00536         temp.y = portal->Vertex[loop].y;
00537         temp.z = portal->Vertex[loop].z;
00538         result = ClassifyPoint(temp, pointOnPlane, planeNormal);
00539         if (result == 0)
00540         {
00541             frontcount++;
00542             backcount++;
00543         }
00544         else
00545             if (result == 1)
00546                 frontcount++;
00547         else
00548             if (result == -1)
00549                 backcount++;
00550     }
00551     if (frontcount == numVerts)
00552             return Front;
00553     if (backcount == numVerts)
00554             return Back;
00555 
00556     return 0;
00557 }
00558 
00559 void InvertPortal(PORTAL* portal)
00560 {
00561     PORTAL* tempportal = CopyPortal(portal);
00562     int numverts = portal->numVertices;
00563     for (int loop = 0; loop < numverts; loop++)
00564         portal->Vertex[loop] = tempportal->Vertex[(numverts - 1) - loop];
00565     delete[] tempportal->Vertex;
00566     tempportal->Vertex = 0;
00567     delete tempportal;
00568     return;
00569 }
00570 
00571 void InvertPortals(BSP_node* node)
00572 {
00573     VECTOR planeNormal, polysNormal, pointOnPlane, edge1, edge2, temp;
00574     int flag;
00575     for (int loop = 1; loop <= node->numportals; loop++)
00576     {
00577         PORTAL* tempportal = node->portallist.Get(loop);
00578         // get a point on the plane
00579         pointOnPlane.x = tempportal->Vertex[0].x;
00580         pointOnPlane.y = tempportal->Vertex[0].y;
00581         pointOnPlane.z = tempportal->Vertex[0].z;
00582 
00583         // get the normal of the portals plane
00584         edge1.x = tempportal->Vertex[1].x - tempportal->Vertex[0].x;
00585         edge1.y = tempportal->Vertex[1].y - tempportal->Vertex[0].y;
00586         edge1.z = tempportal->Vertex[1].z - tempportal->Vertex[0].z;
00587         edge2.x = tempportal->Vertex[2].x - tempportal->Vertex[0].x;
00588         edge2.y = tempportal->Vertex[2].y - tempportal->Vertex[0].y;
00589         edge2.z = tempportal->Vertex[2].z - tempportal->Vertex[0].z;
00590         planeNormal = CrossVector(edge1, edge2);
00591 
00592         flag = 0;
00593         for (int polygon = 0; polygon < node->numpolys; polygon++)
00594         {
00595             for (int vert = 0; vert < 3; vert++)
00596             {
00597                 temp.x = node->nodepolylist[polygon].Vertex[vert].x;
00598                 temp.y = node->nodepolylist[polygon].Vertex[vert].y;
00599                 temp.z = node->nodepolylist[polygon].Vertex[vert].z;
00600 
00601                 flag = ClassifyPoint(temp, pointOnPlane, planeNormal);
00602                 if (flag == -1)
00603                 {
00604                     InvertPortal(tempportal);
00605                 }
00606                 if (flag == 1 || flag == -1)
00607                 {
00608                     if (tempportal->frontleaf->nodeid != node->nodeid)
00609                     {
00610                         BSP_node* tempnode = tempportal->backleaf;
00611                         tempportal->backleaf = tempportal->frontleaf;
00612                         tempportal->frontleaf = tempnode;
00613                     }
00614                     break;
00615                 }
00616             }
00617             if (flag == 1 || flag == -1)
00618                 break;
00619         }
00620     }
00621 }
00622 
00623 void AddPortal(PORTAL* thisportal, BSP_node* node)
00624 {
00625     if (node->leaf == true)
00626     {
00627         node->numportals++;
00628         thisportal->linkPosition = node->numportals;
00629         node->portallist.Insert(thisportal);
00630         return;
00631     }
00632 
00633     int side = ClassifyPortal(thisportal, node->partition);
00634     if (side == Front)
00635     {
00636         AddPortal(thisportal, node->frontnode);
00637     }
00638     if (side == Back)
00639     {
00640         AddPortal(thisportal, node->backnode);
00641     }
00642     if (side == OnPartition)
00643     {
00644         AddPortal(thisportal, node->frontnode);
00645         PORTAL* tempportal = CopyPortal(thisportal);
00646         AddPortal(tempportal, node->backnode);
00647     }
00648     return;
00649 }
00650 
00651 void AddPortalsToLeaves(BSP_node* root)
00652 {
00653     for (int loop = 1; loop <= numportals; loop++)
00654     {
00655         PORTAL* tempportal = CopyPortal(PortalList.Get(loop));
00656         AddPortal(tempportal, root);
00657     }
00658 }
00659 
00660 int ClipPortalToFrontLeaf(PORTAL* portal)
00661 {
00662     int result, returnvalue = 0;
00663     for (int polygon = 0; polygon < portal->frontleaf->numpolys; polygon++)
00664     {
00665         PORTAL* front = new PORTAL;
00666         PORTAL* back = new PORTAL;
00667         result = SplitPortal(portal, portal->frontleaf->nodepolylist[polygon], front, back);
00668 
00669         if (result == PortalWasSplit)
00670         {
00671             returnvalue = PortalWasSplit;
00672             delete[] back->Vertex;
00673             back->Vertex = 0;
00674             delete back;
00675             delete[] portal->Vertex;
00676             portal->Vertex = 0;
00677             portal->numVertices = front->numVertices; 
00678             portal->Vertex = front->Vertex;
00679             delete front;
00680         }
00681 
00682         else
00683         {
00684             delete back;
00685             delete front;
00686         }
00687     }
00688     return returnvalue;
00689 }
00690 
00691 int ClipPortalToBackLeaf(PORTAL* portal)
00692 {
00693     int result, returnvalue = 0;
00694     for (int polygon = 0; polygon < portal->backleaf->numpolys; polygon++)
00695     {
00696         PORTAL* front = new PORTAL;
00697         PORTAL* back = new PORTAL;
00698         result = SplitPortal(portal, portal->backleaf->nodepolylist[polygon], front, back);
00699 
00700         if (result == PortalWasSplit)
00701         {
00702             returnvalue = PortalWasSplit;
00703             delete[] back->Vertex;
00704             back->Vertex = 0;
00705             delete back;
00706             delete[] portal->Vertex;
00707             portal->Vertex = 0;
00708             portal->numVertices = front->numVertices;
00709             portal->Vertex = front->Vertex;
00710             delete front;
00711         }
00712         else
00713         {
00714             delete back;
00715             delete front;
00716         }
00717     }
00718     return returnvalue;
00719 }
00720 
00721 void CheckForSinglePortals(BSP_node* node, BSP_node* originalnode, PORTAL* portal, int* flag)
00722 {
00723     PORTAL* tempportal;
00724     if (node->leaf == true)
00725     {
00726         if (node->nodeid != originalnode->nodeid)
00727         {
00728             for (int portalnum = node->numportals; portalnum > 0; portalnum--)
00729             {
00730                 tempportal = node->portallist.Get(portalnum);
00731                 if (tempportal->PortalId == portal->PortalId)
00732                 {
00733                     portal->frontleaf = originalnode;
00734                     portal->backleaf = node;
00735                     *flag += 1;
00736                 }
00737             }
00738         }
00739         return;
00740     }
00741     else
00742     {
00743         CheckForSinglePortals(node->frontnode, originalnode, portal, flag);
00744         CheckForSinglePortals(node->backnode, originalnode, portal, flag);
00745         return;
00746     }
00747 }
00748 
00749 int RemoveExtraPortals(PORTAL* portal)
00750 {
00751     int result, count = 0;
00752     POLYGON temppoly;
00753     BSP_node* tempnode = portal->backleaf;
00754     for (int loop = 0; loop < tempnode->numpolys; loop++)
00755     {
00756         temppoly = tempnode->nodepolylist[loop];
00757         result = ClassifyInvertedPortal(portal, temppoly);
00758         if (result == Front)
00759             count++;
00760     }
00761     if (count != portal->backleaf->numpolys)
00762         return true;
00763     else
00764         return false;
00765 }
00766 
00767 void FindTruePortals(BSP_node* node)
00768 {
00769     int flag;
00770     if (node->leaf == true)
00771     {
00772         for (int portalnumber = node->numportals; portalnumber > 0; portalnumber--)
00773         {
00774             flag = 0;
00775             PORTAL* tempportal = node->portallist.Get(portalnumber);
00776             CheckForSinglePortals(root, node, tempportal, &flag);
00777             if (flag == 0)
00778             {
00779                 delete[] tempportal->Vertex;
00780                 tempportal->Vertex = 0;
00781                 node->portallist.Delete(portalnumber);
00782                 delete tempportal;
00783                 node->numportals--;
00784             }
00785             else
00786             {
00787                 ClipPortalToFrontLeaf(tempportal);
00788                 ClipPortalToBackLeaf(tempportal);
00789             }
00790         }
00791 
00792         InvertPortals(node);    // also inverts the front and back leaf pointers if necessary
00793 
00794         for (int portalnumber = node->numportals; portalnumber > 0; portalnumber--)
00795         {
00796             PORTAL* tempportal = node->portallist.Get(portalnumber);
00797             flag = RemoveExtraPortals(tempportal);
00798             if (flag == true)
00799             {
00800                 delete[] tempportal->Vertex;
00801                 tempportal->Vertex = 0;
00802                 node->portallist.Delete(portalnumber);
00803                 delete tempportal;
00804                 node->numportals--;
00805             }
00806         }
00807         return;
00808     }
00809     else
00810     {
00811         FindTruePortals(node->frontnode);
00812         FindTruePortals(node->backnode);
00813         return;
00814     }
00815 }
00816 

Generated on Fri Dec 23 05:20:18 2005 for Portals by doxygen1.2.15