Okay, well, I've made some adjustments following your suggestions
Fixed all my linker errors and the runtime seg faults, etc. I'm able to load a cmap successfully, and I now realize what you were saying about the points. Just arbitrary points on the planes, so stole some stuff from CaBSP, mainly ComputeBrushPolys(), Error() and I might end up using the MapFileSanityCheck() eventually. However, I'm getting some interesting stuff from ComputeBrushPolys. Heres a sample of it's output:
D:\Dev\Ca3DE-src-r626\Projects\Ca3D-Engine>cacook bprockb.cmap bprockb.bin
Input File:Games/DeathMatch/Maps/bprockb.cmap
Output File:Games/DeathMatch/Worlds/bprockb.bin
Registering archive "Games/DeathMatch/Textures/TechDemo.zip".
Registering archive "Games/DeathMatch/Textures/SkyDomes.zip".
(0, 0, 1), 6019.8 Textures/Frank/metal_bord1a
(0, 0, -1), -5689.6 Textures/Frank/metal_bord1a
(1, 0, 0), 2819.4 Textures/Frank/metal_bord1a
(-1, 0, 0), -2489.2 Textures/Frank/metal_bord1a
(0, -1, 0), 32512 Textures/Frank/metal_bord1a
(0, 1, 0), -31546.8 Textures/Frank/metal_bord1a
Plane (0, 0, 1), 5842, Vertices
Plane (0, 0, -1), -5791.20038757324, Vertices
Plane (1, 0, 0), 2489.2, Vertices (2489.2, -32283.4000000004, 5791.20038757306)
(2489.2, -32334.1999999993, 5791.20038757306) (2489.2, -32334.1999999993, 5842)
(2489.2, -32283.4, 5842)
Plane (-1, 0, 0), -2463.8, Vertices
Plane (0, -1, 0), 32334.2, Vertices
Plane (0, 1, 0), -32283.4, Vertices
Plane (0, 0, 1), 6019.8, Vertices
Plane (0, 0, -1), -5689.6, Vertices
Plane (1, 0, 0), 2819.4, Vertices
Plane (-1, 0, 0), -2489.2, Vertices (2489.2, -32334.1999999993, 5791.20038757306
) (2489.2, -32283.4, 5791.20038757306) (2489.2, -32283.4000000004, 5842) (2489.2
, -32334.1999999993, 5842)
Plane (0, -1, 0), 32512, Vertices
Plane (0, 1, 0), -31546.8, Vertices
FATAL ERROR: Entity #0, brush #1: polygon #0 is invalid.
Program aborted.
I get a similar error (Same Entity, Brush, Polygon) no matter what cmap I try and load. I'm using if if(!BrushPolys[MFPlaneNr].IsValid(2, 10)) in the loop checking for validity in ComputeBrushPolys, if that makes a difference. Heres the full source if your interested (no more userstream class, btw, found one included with the SDK)
Code: Select all
// CaCook.cpp : 'Cooks world geometry into binary files readable by PhysX for high speed collision detection.
// by Phil Clark
#include <string.h>
#include <iostream>
#include "utils.hpp"
#include "MapFile.hpp"
#include "FileSys/FileManImpl.hpp"
#include "ConsoleCommands/ConsoleStdout.hpp"
#include "TextParser/TextParser.hpp"
#include "MaterialSystem/Material.hpp"
#include "MaterialSystem/MaterialManager.hpp"
#include "MaterialSystem/MaterialManagerImpl.hpp"
#include "NxPhysics.h"
#include "NxCooking.h"
#include "NXU_Helper.h"
#include "NXU_Streaming.h"
using namespace std;
using namespace cf;
#define MAX_VERTICES 100000
#define MAX_TRIANGLES 100000
//bool addEntireScene(NxuPhysicsCollection &, NxScene &, const char *,const char *, NXU::NXU_userNotify * = 0);
//class NxTriangleMeshDesc;
int main(int argc, char *argv[])
{
if ( argc < 3 ) {
cout << "Usage:" << endl
<< "CaCook.exe <InputFileName> <OutputFileName>" << endl;
return 0;
}
char inputfilename[255], outputfilename[255];
sprintf(inputfilename, "Games/DeathMatch/Maps/%s", argv[1]);
sprintf(outputfilename, "Games/DeathMatch/Worlds/%s", argv[2]);
cout << " Input File:" << inputfilename << endl
<< "Output File:" << outputfilename << endl;
///////////////////////////////////////////////////////////////
//Ca3D Initializations
FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_LOCAL_PATH, "./", "");
FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_ZIP_ARCHIVE, "Games/DeathMatch/Textures/TechDemo.zip", "Games/DeathMatch/Textures/TechDemo/", "Ca3DE");
FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_ZIP_ARCHIVE, "Games/DeathMatch/Textures/SkyDomes.zip", "Games/DeathMatch/Textures/SkyDomes/", "Ca3DE");
static MaterialManagerImplT MatManImpl;
MaterialManager = &MatManImpl;
if (MaterialManager->RegisterMaterialScriptsInDir("Games/DeathMatch/Materials", "Games/DeathMatch/").Size()==0)
{
Console->Print(std::string("\nNo materials found in scripts in \"Games/DeathMatch/Materials\".\n"));
cout << "No materials found.";
exit(0);
}
ArrayT<MapFileEntityT> MFEntityList;
MapFileBrushT *CurrentBrush;
///////////////////////////////////////////////////////////////
//PhysX Initializations
static NxPhysicsSDK* gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
static NxCookingInterface *gCooking = NxGetCookingLib(NX_PHYSICS_SDK_VERSION);
gCooking->NxInitCooking();
if(!gPhysicsSDK) { cout << "Wrong SDK DLL version?"; exit(0); }
NxScene *gScene; //
NxSceneDesc sceneDesc; // Physics 'scene' descriptor
NxActor *gActor; // Actor
NxActorDesc actorDesc; // Actor desc
NxTriangleMeshDesc WorldDesc; // World geometry
NxTriangleMeshShapeDesc WorldShapeDesc; // This is getting obscene....
NXU::MemoryWriteBuffer buffer;
unsigned int WORLD_NBVERTICES; // Number of vertices
unsigned int WORLD_NBFACES; // Number of faces
///////////////////////////////////////////////////////////////
//Load the CMAP
TextParserT TP(inputfilename, "()");
if (TP.IsAtEOF()) {
cout << "Unable to open map file.";
return 0;
}
try
{
while (!TP.IsAtEOF())
{
MFEntityList.PushBack(MapFileEntityT(TP));
}
}
catch (const TextParserT::ParseError&)
{
cout << "Problem with parsing the map near byte " << TP.GetReadPosByte() << "(" << TP.GetReadPosPercent()*100.0 << ") of the file." << endl;
exit(0);
}
// Check for any 'func_group' brushes, add them to worldspawn
for (unsigned long EntityNr = 1; EntityNr < MFEntityList.Size(); EntityNr++)
{
if (MFEntityList[EntityNr].MFProperties["classname"]=="func_group")
{
// Copy all brushes of this entity into the 'worldspawn' entity.
for (unsigned long BrushNr=0; BrushNr<MFEntityList[EntityNr].MFBrushes.Size(); BrushNr++)
MFEntityList[0].MFBrushes.PushBack(MFEntityList[EntityNr].MFBrushes[BrushNr]);
// Copy all bezier patches of this entity into the 'worldspawn' entity.
for (unsigned long BPNr=0; BPNr<MFEntityList[EntityNr].MFPatches.Size(); BPNr++)
MFEntityList[0].MFPatches.PushBack(MFEntityList[EntityNr].MFPatches[BPNr]);
// Delete this entity.
MFEntityList[EntityNr]=MFEntityList[MFEntityList.Size()-1];
MFEntityList.DeleteBack();
EntityNr--;
}
}
ArrayT< Polygon3T<double> > BrushPolys;
for (unsigned long BrushNr=0; BrushNr<MFEntityList[0].MFBrushes.Size(); BrushNr++) // Step through a brush
{
ComputeBrushPolys(MFEntityList[0].MFBrushes[BrushNr], BrushPolys, 0, BrushNr);
for (unsigned int PolyNr = 0; PolyNr < BrushPolys.Size(); PolyNr++)
{
for (unsigned int VerticeNr =0; VerticeNr < BrushPolys[PolyNr].Vertices.Size(); VerticeNr++)
{
WORLD_NBVERTICES++;
}
WORLD_NBFACES++;
}
}
NxVec3 *gWorldVertices = (NxVec3*)malloc(WORLD_NBVERTICES*sizeof(NxVec3)); // Array of vertices
NxU32 *gWorldTriangles = (NxU32*)malloc(WORLD_NBFACES*sizeof(NxU32)); // Array of triangles
for (unsigned long BrushNr=0; BrushNr<MFEntityList[0].MFBrushes.Size(); BrushNr++) // Step through a brush
{
cout << "B[";
ComputeBrushPolys(MFEntityList[0].MFBrushes[BrushNr], BrushPolys, 0, BrushNr);
for (unsigned int PolyNr = 0; PolyNr < BrushPolys.Size(); PolyNr++)
{
for (unsigned int VerticeNr =0; VerticeNr < BrushPolys[PolyNr].Vertices.Size(); VerticeNr++)
{
cout << "P(" << BrushPolys[PolyNr].Vertices[VerticeNr].x << ",";
gWorldVertices[ PolyNr*VerticeNr].x = (int)BrushPolys[PolyNr].Vertices[VerticeNr].x;
gWorldTriangles[PolyNr*VerticeNr + 0] = BrushPolys[PolyNr].Vertices[VerticeNr].x;
cout << BrushPolys[PolyNr].Vertices[VerticeNr].y << ",";
gWorldVertices[ PolyNr*VerticeNr].y = BrushPolys[PolyNr].Vertices[VerticeNr].y;
gWorldTriangles[PolyNr*VerticeNr + 1] = BrushPolys[PolyNr].Vertices[VerticeNr].y;
cout << BrushPolys[PolyNr].Vertices[VerticeNr].z << ") ";
gWorldVertices[ PolyNr*VerticeNr].z = BrushPolys[PolyNr].Vertices[VerticeNr].z;
gWorldTriangles[PolyNr*VerticeNr + 2] = BrushPolys[PolyNr].Vertices[VerticeNr].z;
}
}
cout << "] ";
}
cout << endl
<< "Total Faces: " << WORLD_NBFACES << endl
<< "Total Vertices: " << WORLD_NBVERTICES << endl
<< "Saving Points..." << endl;
WorldDesc.numVertices = WORLD_NBVERTICES; // Number of vertices in mesh.
WorldDesc.numTriangles = WORLD_NBFACES; // Number of triangles(3 indices per triangle)
gWorldVertices = new NxVec3[WORLD_NBVERTICES]; // Array of all the vertices in the world
gWorldTriangles = new NxU32[WORLD_NBFACES*3]; // Array of all the triangles' points in the world
WorldDesc.pointStrideBytes = sizeof(NxVec3); // Number of bytes from one vertex to the next.
WorldDesc.triangleStrideBytes = 3*sizeof(NxU32); // Number of bytes from one triangle to the next.
WorldDesc.points = &gWorldVertices;
WorldDesc.triangles = &gWorldTriangles;
WorldDesc.flags = 0;
// Cook the mesh to memory, and read it back again.
bool status = gCooking->NxCookTriangleMesh(WorldDesc, buffer);
WorldShapeDesc.meshData = gPhysicsSDK->createTriangleMesh(NXU::MemoryReadBuffer(buffer.data));
// Add the shape desc to an actor desc, then add the actor (from desc) to the scene
actorDesc.shapes.pushBack(&WorldShapeDesc);
gActor = gScene->createActor(actorDesc);
// Create collection for the scene and save it to the outputfile
NXU::NxuPhysicsCollection *collection = NXU::createCollection ();
NXU::addEntireScene(*collection, *gScene) ;
if ( NXU::saveCollection(collection, outputfilename, NXU::FT_BINARY, true, true) )
cout << endl << "Done cooking mesh.";
else
cout << endl << "Error cooking mesh.";
// Release all out resources
delete [] gWorldVertices;
delete [] gWorldTriangles;
NxCloseCooking();
NXU::releasePersistentMemory();
gPhysicsSDK->release();
return 1;
}