R E T I R E D






/*
 * @doc nodePS2ObjClose
 * @topic A PS2-specific node to complete an object pipeline |
 * @index | nodePS2ObjClose
 * @normal Copyright (c) Criterion Software Limited
 */
/****************************************************************************
 *                                                                          *
 * module : nodePS2ObjClose.c                                               *
 *                                                                          *
 * purpose: yawn...                                                         *
 *                                                                          *
 ****************************************************************************/

/****************************************************************************
 includes
 */

#include <math.h>
#include <eekernel.h> /* SyncDCache(), etc. */
#include "rwcore.h"
#include "baworld.h"
#include "p2stdclsw.h"
#include "skyisms.h"
#include "nodePS2ObjClose.h"

static const char rcsid[] __RWUNUSED__ = "@@(#)$Id: nodePS2ObjClose.c,v 1.32 2000/07/11 13:49:20 johns Exp $";


/****************************************************************************
 local types
 */

/****************************************************************************
 local (static) prototypes
 */

/****************************************************************************
 local defines
 */

/****************************************************************************
 local (static) globals
 */

/****************************************************************************
 functions
 */

/****************************************************************************
 _rwRabinsObjCloseCode()
 */

static RwBool /* success? */
_rwRabinsObjCloseCode(const RxPS2DMASessionRecord *DMASessionRecord)
{
    RwBool result = FALSE;

    RWFUNCTION(RWSTRING("_rwRabinsObjCloseCode"));

    /* rabin... finalize for object & close local packet */
    switch ( DMASessionRecord->objType )
    {
        case rxOBJTYPE_ATOMIC:
            {
                /* Reset Geometry flags */
                RpGeometry *geom
                  = RpAtomicGetGeometry(DMASessionRecord->sourceObject.atomic);

                geom->lockedSinceLastInst = 0;
            }
            break;

        case rxOBJTYPE_WORLDSECTOR:
        default:
            break;
    }

    result = TRUE; /* success */

    RWRETURN(result);
}

/****************************************************************************
 _rwPS2ObjCloseNodeBody()
 */

static RwBool
_rwPS2ObjCloseNodeBody(RxPipelineNodeInstance *self,
                       RxMemoryArena *arena __RWUNUSED__,
                       void *data __RWUNUSED__)
{
    RxPacket *pk;

    RWFUNCTION(RWSTRING("_rwPS2ObjCloseNodeBody"));

    while ( (pk = RxPacketFetch(self)) != NULL )
    {
        RxCluster             *clDMASessionRecord;
        RxPS2DMASessionRecord *DMASessionRecord;
        RwBool                 result;

        clDMASessionRecord = RxClusterLockRead(pk, 0 /* RxClPS2DMASessionRecord */);
        if ( clDMASessionRecord == NULL || !(clDMASessionRecord->flags & rxCLFLAGS_CLUSTERVALID) )
        {
            RWRETURN(FALSE);
        }

        DMASessionRecord = RxClusterGetCursorData(clDMASessionRecord, RxPS2DMASessionRecord);
        if ( DMASessionRecord == NULL )
        {
            RWRETURN(FALSE);
        }

        result = _rwRabinsObjCloseCode(DMASessionRecord);
        if ( !result )
        {
            RWRETURN(FALSE);
        }

        RxPacketDispatch(pk, 0 /* DefaultOutput */, self);
    }

    RWRETURN(TRUE);
}

/**********************************************************************
 * @func <f RxNodeDefinitionGetPS2ObjClose> returns a pointer to the
 * "PS2ObjClose.csl" node definition.
 *
 * A basic PS2 pipeline organisation is as follows:
 *
 * WorldSectorInstancingPipeline - "PS2ObjWorldSectorOpen.csl", "PS2ObjEnumMeshes.csl", "PS2ObjClose.csl"
 *
 * AtomicInstancingPipeline - "PS2ObjAtomicOpen.csl", "PS2ObjEnumMeshes.csl", "PS2ObjClose.csl"
 *
 * MaterialPipeline - "PS2MatInstance.csl", "PS2MatBridge.csl"
 *
 * Heading up their respective instancing pipelines, the PS2ObjXXXOpen nodes receive a reference to the object via
 * their data pointer and create a packet for the object containing an RxPS2DMASessionRecord. The nodes open
 * a DMA session, and add data to the DMA chain for the object-scoped state (matrix, lights, ...).
 *
 * PS2ObjEnumMeshes receives the object packet output by PS2ObjXXXOpen and generates a new packet for each mesh
 * within the object, each packet containing a reference to the object's RxPS2DMASessionRecord and a unique RxPS2Mesh
 * record, which conveys a pointer to the mesh. Mesh packets are then vectored to material pipelines, either
 * the pipeline assigned to the mesh's material, or in the absence of a specific assignment, to the default material
 * pipeline. Within the material pipeline, the mesh packets receive processing from PS2MatInstance and PS2MatBridge.
 *
 * Once all material pipelines have been executed, flow of control returns to the instancing pipe, which executes
 * node PS2ObjClose to complete object processing.
 *
 * Note the difference between PS2 and "generic" pipelines: PS2 pipelines defer instancing
 * (conversion of compressed atomic or worldsector data into a format suitable for rendering) to the material pipeline,
 * as against generic pipelines which instance at the object level (in the instancing pipeline). This enables PS2
 * pipelines to select instanced data format at mesh granularity, dependent on rendering requirements.
 *
 * @xref <f RxNodeDefinitionGetPS2MatInstance>
 * @xref <f RxNodeDefinitionGetPS2ObjEnumMeshes>
 * @xref <f RxNodeDefinitionGetPS2ObjOpen>
 */

/****************************************************************************
 RxNodeDefinitionGetPS2ObjClose()
 */

RxNodeDefinition *
RxNodeDefinitionGetPS2ObjClose(void)
{
    /******************************************/
    /**                                      **/
    /**  PS2OBJCLOSE.CSL NODE SPECIFICATION  **/
    /**                                      **/
    /******************************************/

    static RxClusterRef nodeClusters[] =
    {
          /* 0 */
        { &RxClPS2DMASessionRecord, rxCLALLOWABSENT, rxCLRESERVED }
    };

    #define NUMCLUSTERSOFINTEREST \
        ((sizeof(nodeClusters))/(sizeof(nodeClusters[0])))

    /* input requirements (this array parallel to ClusterRefs) */
    static RxClusterValidityReq nodeReqs[NUMCLUSTERSOFINTEREST] =
    {
          rxCLREQ_REQUIRED
    };

    /* output state (this array parallel to ClusterRefs) */
    static RxClusterValid nodeOut1[NUMCLUSTERSOFINTEREST] =
    {
          rxCLVALID_VALID
    };

    static RwChar _DefaultOutput[] = RWSTRING("DefaultOutput");

    static RxOutputSpec nodeOuts[] =
    {
        {
            _DefaultOutput,              // Name
            nodeOut1,                    // OutputClusters
            rxCLVALID_NOCHANGE            // AllOtherClusters
        }
    };

    #define NUMOUTPUTS \
        ((sizeof(nodeOuts))/(sizeof(nodeOuts[0])))

    static RwChar _PS2ObjClose_csl[] = RWSTRING("PS2ObjClose.csl");

    static RxNodeDefinition nodePS2ObjCloseCSL =
    {
        _PS2ObjClose_csl,                      // Name
        {                                      // nodemethods
            _rwPS2ObjCloseNodeBody,            // +-- nodebody
            (RxNodeInitFn)NULL,                // +-- nodeinit
            (RxNodeTermFn)NULL,                // +-- nodeterm
            (RxPipelineNodeInitFn) NULL,       // +-- pipelinenodeinit
            (RxPipelineNodeTermFn) NULL,       // +-- pipelineNodeTerm
            (RxPipelineNodeConfigFn) NULL,     // +--  pipelineNodeConfig
            (RxConfigMsgHandlerFn) NULL        // +--  configMsgHandler
        },
        {                                      // Io
            NUMCLUSTERSOFINTEREST,             // +-- NumClustersOfInterest
            nodeClusters,                      // +-- ClustersOfInterest
            nodeReqs,                          // +-- InputRequirements
            NUMOUTPUTS,                        // +-- NumOutputs
            nodeOuts                           // +-- Outputs
        },
        (RwUInt32)0,                           // PipelineNodePrivateDataSize
        FALSE,                                 // editable
        (RwInt32)0                             // inPipes
    };

    /***************************************/

    RxNodeDefinition *result = &nodePS2ObjCloseCSL;

    RWAPIFUNCTION(RWSTRING("RxNodeDefinitionGetPS2ObjClose"));

    /*RWMESSAGE((RWSTRING("Pipeline II node")));*/

    RWRETURN(result);
}
