Standalone app, cook the world :)

Get technical support about the C++ source code and about Lua scripts for maps, entities, GUIs, the console, materials, etc. Also covered are the Cafu libraries and APIs, as well as compiling, linking, and the build system.
User avatar
Carsten
Site Admin
Posts: 2160
Joined: 2004-08-19, 13:46
Location: Germany
Contact:

Re: Standalone app, cook the world :)

Post by Carsten » 2008-09-11, 23:44

While I still didn't manage to try your code "live", I spotted an issue that is certainly a candidate for causing the crash that you experience: The counts of vertices and faces that you pass to the WorldDesc are not accurate.

In order to fix, why don't you remove the variables WORLD_NBVERTICES and WORLD_NBFACES entirely, then replace

Code: Select all

    WorldDesc.numVertices   = WORLD_NBVERTICES;      // Number of vertices in mesh.
    WorldDesc.numTriangles  = WORLD_NBFACES;         // Number of triangles(3 indices per triangle)
with

Code: Select all

    WorldDesc.numVertices   = gWorldVertices.size();      // Number of vertices in mesh.
    WorldDesc.numTriangles  = gWorldTriangles.size()/3;         // Number of triangles(3 indices per triangle)
This works because gWorldTriangles actually holds indices for triangles (not triangles themselves). To be more precise, it holds 3 indices for each triangle, thus the division by 3 yields the proper number of triangles.

Even if this doesn't immediately fix the crash, it makes your program shorter and more correct. :cheesy:
Best regards,
Carsten
minosdis
Posts: 24
Joined: 2008-08-09, 05:42

Re: Standalone app, cook the world :)

Post by minosdis » 2008-09-12, 03:41

I actually went through a few things, noticed that also. I changed the main loop a bit so that it a) got the counts correct, so far I've tested with most of the different primative shapes (box, pyramid, cylinder so far) and its correct. B) I added support to avoid redundant vertices. While it doesn't seem this is required by PhysX, it makes the cooked binary that much smaller and quicker to load. The docs also mentioned that redudant vertices can cause inconsistent behavior, so I figured I might as well get it done. Unfortunately, none of these fixed the problem. Here is the new main loop if you want to replace it in your version:

Code: Select all

    ArrayT<NxVec3> gWorldVertices;
    ArrayT<NxU32>  gWorldTriangles;

    for (unsigned long BrushNr=0; BrushNr<MFEntityList[0].MFBrushes.Size(); BrushNr++)
    {
        ArrayT< Polygon3T<double> > BrushPolys;
        
        ComputeBrushPolys(MFEntityList[0].MFBrushes[BrushNr], BrushPolys, 0, BrushNr);

        for (unsigned int PolyNr=0; PolyNr<BrushPolys.Size(); PolyNr++)
        {
            unsigned int NumVerts    = 0;
            unsigned int FirstIndex  = 0;
            unsigned int SecondIndex = 0;
            unsigned int ThirdIndex  = 0;
            cout << "Poly[" << endl;

            // Just add all vertices of the polygon to gWorldVertices.
            // (When polygons share vertices removing the redundancy is not taken into account.)
            for (unsigned int VerticeNr=0; VerticeNr<BrushPolys[PolyNr].Vertices.Size(); VerticeNr++)
            {
                NxVec3 tempVec;
                NumVerts++;
                if (FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr]) == -1) 
                {
                    tempVec.x=BrushPolys[PolyNr].Vertices[VerticeNr].x;
                    tempVec.y=BrushPolys[PolyNr].Vertices[VerticeNr].y;
                    tempVec.z=BrushPolys[PolyNr].Vertices[VerticeNr].z;
                    WORLD_NBVERTICES++;
                    gWorldVertices.PushBack(tempVec);

                    cout << "    V(" << tempVec.x
                         << ", "  << tempVec.y
                         << ", "  << tempVec.z 
                         << ")"  << endl;
                         
                }
            }

            // Add the right indices for the V-2 triangles to gWorldTriangles.
            for (unsigned int VerticeNr=0; VerticeNr+2<BrushPolys[PolyNr].Vertices.Size(); VerticeNr++)
            {
                // FIXME / Check: Is the triangle orientation right (same as in Ca3DE)?
                //                Swap the last two lines otherwise.
                if (FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[0]) != -1) // if vert is already defined
                    FirstIndex  = FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[0]);
                if (FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr+1]) != -1) // if vert is already defined
                    SecondIndex = FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr+1]);
                if (FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr+1]) != -1) // if vert is already defined
                    ThirdIndex  = FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr+2]);

                gWorldTriangles.PushBack(static_cast<NxU32>(FirstIndex) );      // Always the first.
                gWorldTriangles.PushBack(static_cast<NxU32>(SecondIndex) );
                gWorldTriangles.PushBack(static_cast<NxU32>(ThirdIndex) );
                cout << "    T(" << FirstIndex
                     << ", "      << SecondIndex
                     << ", "      << ThirdIndex
                     << ")"      << endl;
                WORLD_NBFACES++;
            }
            cout << "]" << endl;
        }
    }
Also a function to add in utils.hpp,

Code: Select all

int FindIndex(ArrayT<NxVec3> inpArray, Vector3T<double> toFind)
{
    NxVec3 tempVec;
    tempVec.x = toFind.x;
    tempVec.y = toFind.y;
    tempVec.z = toFind.z;
    for (unsigned int ElementNr = 0; ElementNr < inpArray.Size(); ElementNr++)
        if (inpArray[ElementNr].equals(tempVec, 2))
            return ElementNr;
    return -1;
}
As far as I know, everything else is the same.
minosdis
Posts: 24
Joined: 2008-08-09, 05:42

Re: Standalone app, cook the world :)

Post by minosdis » 2008-09-13, 03:08

So I made a little bit of progress. I studied one of the samples (SampleTransforms), and found that they were creating arrays of floats and ints for the vertices and indices then passing them directly to the points and triangles members, like so:

Code: Select all

float gVertices[] = {...};
int gIndices[] = {...};
meshDesc.points = gVertices;
meshDesc.triangles = gIndices;
So I gave that a shot, and came up with this hack. Its ugly, and dumb, but it works. Well, some of the time. I attempted to cook all of the maps I have, and was able to cook some of them. Some of the maps gave mapfile errors (missing textures), so they never even got to the polygons loop. I'd imagine I'm just missing some of the textures for those maps. Other had runtime errors in two different locations (depending on the map) and TechDemo, after working for 10 minutes or so finally gave up and "requested the Runtime to terminate it in an unusual way." Heres the code I came up with:

Code: Select all

// CaCook.cpp : 'Cook's world geometry into binary files readable by PhysX for high speed collision detection.
// by Phil Clark

/////////////////////////////
//Debug Mode
// 0 - No Debug Output
// 1 - Shows line output
// 2 - Line output and complete point and vertice data
#define _DEBUGMODE 1

#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NONSTDC_NO_DEPRECATE

#include <iostream>
#include <vector>
#include "utils.hpp"
#include "MapFile.hpp"
#include "ConsoleCommands/ConsoleStdout.hpp"
#include "TextParser/TextParser.hpp"
#include "MaterialSystem/MaterialManagerImpl.hpp"


#include "NxCooking.h"
#include "NXU_Helper.h"
#include "NXU_Streaming.h"

using namespace std;
using namespace cf;


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)
        Error("No materials found in scripts in \"Games/DeathMatch/Materials\"");
    ArrayT<MapFileEntityT> MFEntityList;


    ///////////////////////////////////////////////////////////////
    //PhysX Initializations
    static NxPhysicsSDK*	   gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
    if (!gPhysicsSDK) Error("Failed to load PhysX SDK");
    else Console->Print("Loaded PhysX SDK\n");

    static NxCookingInterface *gCooking    = NxGetCookingLib(NX_PHYSICS_SDK_VERSION);
    if (!gCooking->NxInitCooking()) Error("Failed to load NxCooking");
    else Console->Print("Loaded NxCooking\n");
//    if (!NxInitCooking()) Error("Failed to load NxCooking");
//    else Console->Print("Loaded NxCooking\n");

    NxScene                 *gScene=NULL;     //
    NxSceneDesc              sceneDesc;  // Physics 'scene' descriptor
    sceneDesc.gravity      = NxVec3(0.0f, -9810.0f, 0.0f);
    gScene                 = gPhysicsSDK->createScene(sceneDesc);
    if (gScene == NULL) Error("Unable to create a PhysX scene");
    else Console->Print("Created PhysX scene\n");

    NxActor                 *gActor;     // Actor
    NxActorDesc              actorDesc;  // Actor desc
    NxTriangleMeshDesc       WorldDesc;  // World geometry
    NxTriangleMeshShapeDesc  WorldShapeDesc;    // This is getting obscene....
    NXU::MemoryWriteBuffer   buffer;
	unsigned int             WORLD_NBVERTICES =0;  // Number of vertices
	unsigned int             WORLD_NBFACES =0;     // Number of faces


    ///////////////////////////////////////////////////////////////
    //Load the CMAP
    Console->Print("Loading map file, please be patient.\n");
    TextParserT TP(inputfilename, "()");
	if (TP.IsAtEOF())
        Error("Unable to open map file.");
    try
    {
        while (!TP.IsAtEOF())
        {
            MFEntityList.PushBack(MapFileEntityT(TP));
        }
    }
    catch (const TextParserT::ParseError&)
    {
        Error("Problem with parsing the map near byte %lu (%.3f%%) of the file.", TP.GetReadPosByte(), TP.GetReadPosPercent()*100.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<NxVec3> gWorldVertices;
    ArrayT<NxU32>  gWorldTriangles;

    for (unsigned long BrushNr=0; BrushNr<MFEntityList[0].MFBrushes.Size(); BrushNr++)
    {
        ArrayT< Polygon3T<double> > BrushPolys;
        
        ComputeBrushPolys(MFEntityList[0].MFBrushes[BrushNr], BrushPolys, 0, BrushNr);

        for (unsigned int PolyNr=0; PolyNr<BrushPolys.Size(); PolyNr++)
        {
            unsigned int NumVerts    = 0;
            unsigned int FirstIndex  = 0;
            unsigned int SecondIndex = 0;
            unsigned int ThirdIndex  = 0;
            if(_DEBUGMODE>1)cout << "Poly[" << endl;

            // Just add all vertices of the polygon to gWorldVertices.
            // (When polygons share vertices removing the redundancy is not taken into account.)
            for (unsigned int VerticeNr=0; VerticeNr<BrushPolys[PolyNr].Vertices.Size(); VerticeNr++)
            {
                NxVec3 tempVec;
                NumVerts++;
                if (FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr]) == -1) 
                {
                    tempVec.x=BrushPolys[PolyNr].Vertices[VerticeNr].x;
                    tempVec.y=BrushPolys[PolyNr].Vertices[VerticeNr].y;
                    tempVec.z=BrushPolys[PolyNr].Vertices[VerticeNr].z;
                    WORLD_NBVERTICES++;
                    gWorldVertices.PushBack(tempVec);

                    if(_DEBUGMODE>1)cout << "    V(" << tempVec.x
                                  << ", "  << tempVec.y
                                  << ", "  << tempVec.z 
                                  << ")"  << endl;
                         
                }
            }

            // Add the right indices for the V-2 triangles to gWorldTriangles.
            for (unsigned int VerticeNr=0; VerticeNr+2<BrushPolys[PolyNr].Vertices.Size(); VerticeNr++)
            {
                // FIXME / Check: Is the triangle orientation right (same as in Ca3DE)?
                //                Swap the last two lines otherwise.
                if (FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[0]) != -1) // if vert is already defined
                    FirstIndex  = FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[0]);
                if (FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr+1]) != -1) // if vert is already defined
                    SecondIndex = FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr+1]);
                if (FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr+1]) != -1) // if vert is already defined
                    ThirdIndex  = FindIndex(gWorldVertices, BrushPolys[PolyNr].Vertices[VerticeNr+2]);

                gWorldTriangles.PushBack(static_cast<NxU32>(FirstIndex) );      // Always the first.
                gWorldTriangles.PushBack(static_cast<NxU32>(SecondIndex) );
                gWorldTriangles.PushBack(static_cast<NxU32>(ThirdIndex) );
                if(_DEBUGMODE>1)cout << "    T(" << FirstIndex
                              << ", "      << SecondIndex
                              << ", "      << ThirdIndex
                              << ")"      << endl;
                WORLD_NBFACES++;
            }
            if(_DEBUGMODE>1)cout << "]" << endl;
        }
    }
    cout << endl
         << "Total Triangles: " << WORLD_NBFACES    << endl 
         << "Total Vertices: "  << WORLD_NBVERTICES << endl
	     << "Saving Points..."  << endl;
    
    int *gWorldTrisIndices = new int[WORLD_NBFACES*3];
    for (unsigned int IndexNr =0; IndexNr < (WORLD_NBFACES*3); IndexNr++)
    {
        gWorldTrisIndices[IndexNr] = gWorldTriangles[IndexNr];
    }
    float *gWorldVerts = new float[WORLD_NBVERTICES];
    for (unsigned int VerticeNr =0; VerticeNr < WORLD_NBVERTICES; VerticeNr+=3)
    {
        gWorldVerts[VerticeNr] = gWorldVertices[VerticeNr].x;
        gWorldVerts[VerticeNr+1] = gWorldVertices[VerticeNr].y;
        gWorldVerts[VerticeNr+2] = gWorldVertices[VerticeNr].z;
    }
    WorldDesc.numVertices   = WORLD_NBVERTICES;      // Number of vertices in mesh.
    WorldDesc.numTriangles  = WORLD_NBFACES;         // Number of triangles(3 indices per triangle)

    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    = (const void *)gWorldVerts;
    WorldDesc.triangles = (const void *)gWorldTrisIndices;
    WorldDesc.flags     = 0;
    if (!WorldDesc.isValid()) Error("Descriptor invalid");
   
    // Cook the mesh to memory, and read it back again.
if(_DEBUGMODE)cout << "1" << endl;
    bool status = gCooking->NxCookTriangleMesh(WorldDesc,buffer);
if(_DEBUGMODE)cout << "2" << endl;
    // I commented this so the program would crash and I could debug it.  Will uncomment once fixed.
    if (status == false) 
    {
        if (!buffer.data) 
            Error("Memory Buffer invalid");
        Error("Unable to cook mesh!");
    }
    else Console->Print("Cooking successfull!\n");
if(_DEBUGMODE)cout << "3" << endl;
    NxTriangleMesh *WorldMesh = gPhysicsSDK->createTriangleMesh(NXU::MemoryReadBuffer(buffer.data));
if(_DEBUGMODE)cout << "4" << endl;
    WorldShapeDesc.meshData   = WorldMesh;
if(_DEBUGMODE)cout << "5" << endl;
    // Add the shape desc to an actor desc, then add the actor (from desc) to the scene
    actorDesc.shapes.pushBack(&WorldShapeDesc);
if(_DEBUGMODE)cout << "6" << endl;
    gActor = gScene->createActor(actorDesc);
if(_DEBUGMODE)cout << "7" << endl;
    // Create collection for the scene and save it to the outputfile
    NXU::NxuPhysicsCollection *collection = NXU::createCollection ();
if(_DEBUGMODE)cout << "8" << endl;  
    NXU::addEntireScene(*collection, *gScene) ;
if(_DEBUGMODE)cout << "8.5" << endl;
    if ( NXU::saveCollection(collection, outputfilename, NXU::FT_BINARY, true, true) )
        Console->Print("Done cooking world.\n");
    else
        Console->Print("Error cooking world.\n");
if(_DEBUGMODE)cout << "9" << endl;
    // Release all out resources
    //delete gWorldTrisIndices;
if(_DEBUGMODE)cout << "10" << endl;
    //delete gWorldVerts;
if(_DEBUGMODE)cout << "11" << endl;
    NXU::releasePersistentMemory();
if(_DEBUGMODE)cout << "12" << endl;
    gCooking->NxCloseCooking();
if(_DEBUGMODE)cout << "13" << endl;
    //NxCloseCooking();
    gPhysicsSDK->release();
if(_DEBUGMODE)cout << "14" << endl;
    return 1;
}
And heres a more detailed explanation of each map file and the results I had:
SUCCESS:
09/07/2008 04:30 PM 4,503 cookme.cmap
This is just a hollowed cube, ie, 6 box type brushes - no entities
09/11/2008 10:16 AM 1,272 cylinder.cmap
Just a 6 sided cylinder type brush - no entities
09/10/2008 11:35 PM 889 triangles.cmap
A pyramid brush
05/27/2008 03:06 PM 841,245 Kidney.cmap
A full, working map file :) :)
08/08/2008 09:12 PM 414,940 test.cmap
Very large terrain inside a hollow cube. Has an info_player_start and several point lights
08/14/2008 04:01 PM 8,500 VehicleTest.cmap
The beginings of a test level for vehicles, just a hollow cube, info_player_start, a few lights and a 'car' entity

FAILED:
Runtime / Unhandled Exception errors: (Number is the outputed line/label before crash)
05/27/2008 03:04 PM 606,210 AEonsCanyonTower.cmap (1)
05/27/2008 03:05 PM 1,009,243 AEonsCube.cmap (1)
09/08/2008 07:35 PM 5,774 arch.cmap (1)
05/27/2008 03:09 PM 971,691 BPRockB.cmap (1)
05/27/2008 03:07 PM 936,523 ReNoEcho.cmap (1)
09/11/2008 08:18 AM 969 block.cmap (8)


Mapfile loading errors:
05/27/2008 03:05 PM 1,544,049 BPWxBeta.cmap
Libs\MaterialSystem\MaterialManagerImpl.cpp (332):
GetMaterial("Textures/Q1/sliptopsd") returns NULL.
Warning: Entity ??, Brush 1026, plane 0: Unknown material "Textures/Q1/sliptopsd".
FATAL ERROR: Problem with parsing the map near byte 900962 (58.351%) of the file.
Program aborted.

05/27/2008 03:05 PM 443,960 Gotham.cmap
Libs\MaterialSystem\MaterialManagerImpl.cpp (332):
GetMaterial("Textures/Q1/metal5_1") returns NULL.
Warning: Entity ??, Brush 6, plane 1: Unknown material "Textures/Q1/metal5_1".
FATAL ERROR: Problem with parsing the map near byte 5598 (1.261%) of the file.
Program aborted.

05/27/2008 03:06 PM 930,883 JrBaseHQ.cmap
(Libs\MaterialSystem\MaterialManagerImpl.cpp (332):
GetMaterial("Textures/Q1/slipbotsd") returns NULL.
Warning: Entity ??, Brush 0, plane 0: Unknown material "Textures/Q1/slipbotsd".
FATAL ERROR: Problem with parsing the map near byte 496 (0.053%) of the file.
Program aborted.

05/27/2008 03:07 PM 2,519,704 ReNoElixir.cmap
Libs\MaterialSystem\MaterialManagerImpl.cpp (332):
GetMaterial("Textures/Q1/tech04_3") returns NULL.
Warning: Entity ??, Brush 724, plane 5: Unknown material "Textures/Q1/tech04_3".
FATAL ERROR: Problem with parsing the map near byte 667460 (26.490%) of the file.
Program aborted.

08/25/2008 06:47 PM 5,381Test1.cmap
Libs\MaterialSystem\MaterialManagerImpl.cpp (332):
GetMaterial("Textures/Q1/stone1_3") returns NULL.
Warning: Entity ??, Brush 0, plane 0: Unknown material "Textures/Q1/stone1_3".
FATAL ERROR: Problem with parsing the map near byte 459 (8.528%) of the file.
Program aborted.

05/27/2008 03:03 PM 18,669 TestPatches.cmap
Libs\MaterialSystem\MaterialManagerImpl.cpp (332):
GetMaterial("Textures/Q1/stone1_3") returns NULL.
Warning: Entity ??, Brush 0, plane 0: Unknown material "Textures/Q1/stone1_3".
FATAL ERROR: Problem with parsing the map near byte 516 (2.764%) of the file.
Program aborted.

Other:
05/27/2008 03:57 PM 20,843,478 TechDemo.cmap
(This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information. )
NOTE: I think techdemo ran out of memory. It plugged away for 10 minutes or so,
then finally gave up.
EDIT:
I'm trying to add a few physx things (the scene and cooked world) to the deathmatch dll. Having some troubles getting it to build with scons however. It compiles fine, but I get 3 linker errors,
GameImpl.obj : error LNK2001: unresolved external symbol "public: static class N
xPhysicsSDK * cf::GameSys::GameImplT::gPhysicsSDK" (?gPhysicsSDK@GameImplT@GameS
ys@cf@@2PAVNxPhysicsSDK@@A)
GameImpl.obj : error LNK2019: unresolved external symbol "bool __cdecl NXU::inst
antiateScene(class NXU::NxuPhysicsCollection *,char const *,class NxPhysicsSDK &
,class NxScene *,class NxMat34 *,class NXU_userNotify *)" (?instantiateScene@NXU
@@YA_NPAVNxuPhysicsCollection@1@PBDAAVNxPhysicsSDK@@PAVNxScene@@PAVNxMat34@@PAVN
XU_userNotify@@@Z) referenced in function "public: virtual void __thiscall cf::G
ameSys::GameImplT::Sv_FinishNewMap(char const *)" (?Sv_FinishNewMap@GameImplT@Ga
meSys@cf@@UAEXPBD@Z)
GameImpl.obj : error LNK2019: unresolved external symbol "class NXU::NxuPhysicsC
ollection * __cdecl NXU::loadCollection(char const *,enum NXU::NXU_FileType,void
*,int)" (?loadCollection@NXU@@YAPAVNxuPhysicsCollection@1@PBDW4NXU_FileType@1@P
AXH@Z) referenced in function "public: virtual void __thiscall cf::GameSys::Game
ImplT::Sv_FinishNewMap(char const *)" (?Sv_FinishNewMap@GameImplT@GameSys@cf@@UA
EXPBD@Z)
Does this SConscript look right to you?

Code: Select all

import os, sys

Import('env', 'buildMode')

gameEnv = env.Copy()

gameEnv.Append(CPPPATH=['#/../ExtLibs/lua-5.1.1/src'])
gameEnv.Append(CPPPATH=['#/../ExtLibs\PhysX\SDKs\Physics\include'])
gameEnv.Append(CPPPATH=['#/../ExtLibs\PhysX\SDKs\PhysXLoader\include'])
gameEnv.Append(CPPPATH=['#/../ExtLibs\PhysX\SDKs\Foundation\include'])
gameEnv.Append(CPPPATH=['#/../ExtLibs\PhysX\SDKs\NxCharacter\include'])
gameEnv.Append(CPPPATH=['#/../ExtLibs\PhysX\SDKs\Cooking\include'])
gameEnv.Append(CPPPATH=['#/../ExtLibs\PhysX\Tools\NxuStream2'])


if sys.platform=="win32":
    gameEnv.Append(CPPDEFINES=['WIN32'])
    gameEnv.Append(LIBPATH=['#/../ExtLibs/PhysX/SDKs/lib/Win32'])
    gameEnv.Append(LIBS=["ClipSys"])   # UHHHHHHH... this should be in cfsLib!!!
    gameEnv.Append(LIBS=Split("MatSys SoundSys cfsLib lua lightwave collada14dom xml2 pcre pcrecpp"))
    gameEnv.Append(LIBS=Split("NxCharacter NxCooking PhysXLoader"))
elif sys.platform=="linux2":
    gameEnv.Append(LIBPATH=['#/../ExtLibs/PhysX/SDKs/lib/Win32'])
    gameEnv.Append(LIBS=["ClipSys"])   # UHHHHHHH... this should be in cfsLib!!!
    gameEnv.Append(LIBS=Split("MatSys SoundSys cfsLib lua lightwave collada14dom xml2 pcrecpp pcre"))
    gameEnv.Append(LIBS=Split("NxCharacter NxCooking PhysXLoader"))
    # This LinkerScript is required to make sure that the game DLL only exports the GetGame() symbol (like a Windows DLL),
    # rather than *all* sorts of symbols whose name strings I don't want to appear in the final DSO, e.g. those of the ClipSys.
    gameEnv.Append(LINKFLAGS = ["-Wl,--version-script=Ca3D-Engine/Games/DeathMatch/Code/LinkerScript"])

gameEnv.SharedLibrary("DeathMatch", Split("""
    GameImpl.cpp             ScriptState.cpp          EntityCreateParams.cpp   Corpse.cpp               Item.cpp
    _ResourceManager.cpp     BaseEntity.cpp           ARGrenade.cpp            Butterfly.cpp            CompanyBot.cpp           
    cw.cpp                   cw_357.cpp               cw_9mmAR.cpp             cw_BattleScythe.cpp      cw_CrossBow.cpp
    cw_Egon.cpp              cw_FaceHugger.cpp        cw_Gauss.cpp             cw_Grenade.cpp           cw_Pistol.cpp
    cw_RPG.cpp               cw_Shotgun.cpp           DeathMatch.cpp           Eagle.cpp                FaceHugger.cpp
    FuncDoor.cpp             FuncLadder.cpp           HandGrenade.cpp          HumanPlayer.cpp          InfoPlayerStart.cpp      
    ItemAmmo357.cpp          ItemAmmoArrow.cpp        MonsterMaker.cpp         Mover.cpp                PointLightSource.cpp     
    StaticDetailModel.cpp    Trigger.cpp              Weapon.cpp               Weapon357.cpp            Weapon9mmAR.cpp          
    WeaponCrossbow.cpp       WeaponEgon.cpp           WeaponFaceHugger.cpp     WeaponGauss.cpp          WeaponGrenade.cpp
    WeaponHornetGun.cpp      WeaponPistol.cpp         WeaponRPG.cpp            WeaponShotgun.cpp        WeaponTripmine.cpp
    Speaker.cpp              Rocket.cpp               WeaponBattleScythe.cpp
    Libs/LookupTables.cpp    Libs/Physics.cpp
"""))
minosdis
Posts: 24
Joined: 2008-08-09, 05:42

Re: Standalone app, cook the world :)

Post by minosdis » 2008-09-16, 06:31

So I got the death match mod to compile under VC++ 2008 using a vcproj. Still getting those three errors with scons, although I think I know how to fix that. Either way though, I can build the dm mod with a small amount of physx code in it. So far I'm just attempting to load the phsyx scene from the binary saved with CaCook. I'll let you know if I get anywhere with that :)
User avatar
Carsten
Site Admin
Posts: 2160
Joined: 2004-08-19, 13:46
Location: Germany
Contact:

Re: Standalone app, cook the world :)

Post by Carsten » 2008-09-16, 22:29

minosdis wrote:So I got the death match mod to compile under VC++ 2008 using a vcproj. Still getting those three errors with scons, although I think I know how to fix that. Either way though, I can build the dm mod with a small amount of physx code in it. So far I'm just attempting to load the phsyx scene from the binary saved with CaCook. I'll let you know if I get anywhere with that :)
Great to hear that you're making progress!!
I was very busy during the last few days and will unfortunately be completely absent tomorrow, but I too am making good progress.
The Sconscript looks right, but it seems that still some component from Nx is missing.

Will let you know more when I'm back on Thursday. ;)
Best regards,
Carsten
Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests