/*! \brief Called when a new player is connected to the server
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0            1         2          
 *       -------------------------------------
 *  Size |     1      |    1   |             |
 *  Data | player_id  | hostid | player name |
 *       -------------------------------------
 */
void ClientLobbyRoomProtocol::newPlayer(Event* event)
{
    if (!checkDataSize(event, 2)) return;
    const NetworkString &data = event->data();

    uint8_t player_id = data.getUInt8();
    uint8_t host_id   = data.getUInt8();
    core::stringw name;
    data.decodeStringW(&name);
    // FIXME need adjusting when splitscreen is used/
    if(STKHost::get()->getGameSetup()->isLocalMaster(player_id))
    {
        Log::error("ClientLobbyRoomProtocol",
                   "The server notified me that I'm a new player in the "
                   "room (not normal).");
    }
    else if (m_setup->getProfile(player_id) == NULL)
    {
        Log::verbose("ClientLobbyRoomProtocol", "New player connected.");
        NetworkPlayerProfile* profile = 
                      new NetworkPlayerProfile(name, player_id, host_id);
        m_setup->addPlayer(profile);
        NetworkingLobby::getInstance()->addPlayer(profile);
    }
    else
    {
        Log::error("ClientLobbyRoomProtocol",
                   "One of the player notified in the list is myself.");
    }
}   // newPlayer
/*! \brief Called when a player asks to select a kart.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0          1                      2            
 *       ----------------------------------------------
 *  Size |    1     |           1         |     N     |
 *  Data |player id |  N (kart name size) | kart name |
 *       ----------------------------------------------
 */
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
{
    if(m_state!=SELECTING)
    {
        Log::warn("Server", "Received kart selection while in state %d.",
                  m_state);
        return;
    }

    if (!checkDataSize(event, 1)) return;

    const NetworkString &data = event->data();
    STKPeer* peer = event->getPeer();

    uint8_t player_id = data.getUInt8();
    std::string kart_name;
    data.decodeString(&kart_name);
    // check if selection is possible
    if (!m_selection_enabled)
    {
        NetworkString *answer = getNetworkString(2);
        // selection still not started
        answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(2);
        peer->sendPacket(answer);
        delete answer;
        return;
    }
    // check if somebody picked that kart
    if (!m_setup->isKartAvailable(kart_name))
    {
        NetworkString *answer = getNetworkString(2);
        // kart is already taken
        answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(0);
        peer->sendPacket(answer);
        delete answer;
        return;
    }
    // check if this kart is authorized
    if (!m_setup->isKartAllowed(kart_name))
    {
        NetworkString *answer = getNetworkString(2);
        // kart is not authorized
        answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(1);
        peer->sendPacket(answer);
        delete answer;
        return;
    }

    // send a kart update to everyone
    NetworkString *answer = getNetworkString(3+kart_name.size());
    // This message must be handled synchronously on the client.
    answer->setSynchronous(true);
    // kart update (3), 1, race id
    answer->addUInt8(LE_KART_SELECTION_UPDATE).addUInt8(player_id)
          .encodeString(kart_name);
    sendMessageToPeersChangingToken(answer);
    delete answer;
    m_setup->setPlayerKart(player_id, kart_name);
}   // kartSelectionRequested
/*! \brief Called when the server accepts the connection.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0                   1        2            3       
 *       ---------------------------------------------------------
 *  Size |    1     |   1    | 1          |             |
 *  Data | player_id| hostid | authorised |playernames* |
 *       ---------------------------------------------------------
 */
void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
{
    // At least 3 bytes should remain now
    if(!checkDataSize(event, 3)) return;

    NetworkString &data = event->data();
    STKPeer* peer = event->getPeer();

    // Accepted
    // ========
    Log::info("ClientLobbyRoomProtocol",
              "The server accepted the connection.");

    // self profile
    irr::core::stringw name;
    if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN)
        name = PlayerManager::getCurrentOnlineUserName();
    else
        name = PlayerManager::getCurrentPlayer()->getName();
    uint8_t my_player_id = data.getUInt8();
    uint8_t my_host_id   = data.getUInt8();
    uint8_t authorised   = data.getUInt8();
    // Store this client's authorisation status in the peer information
    // for the server.
    event->getPeer()->setAuthorised(authorised!=0);
    STKHost::get()->setMyHostId(my_host_id);

    NetworkPlayerProfile* profile = 
        new NetworkPlayerProfile(name, my_player_id, my_host_id);
    STKHost::get()->getGameSetup()->setLocalMaster(my_player_id);
    m_setup->setNumLocalPlayers(1);
    // connection token
    uint32_t token = data.getToken();
    peer->setClientServerToken(token);

    // Add all players
    // ===============
    while (data.size() > 0)
    {
        uint8_t player_id = data.getUInt8();
        uint8_t host_id   = data.getUInt8();
        irr::core::stringw name;
        int bytes_read = data.decodeStringW(&name);
        
        NetworkPlayerProfile* profile2 =
            new NetworkPlayerProfile(name, player_id, host_id);
        m_setup->addPlayer(profile2);
        // Inform the network lobby of all players so that the GUI can
        // show all currently connected players.
        NetworkingLobby::getInstance()->addPlayer(profile2);
    }

    // Add self after other players so that player order is identical
    // on server and all clients.
    m_setup->addPlayer(profile);
    NetworkingLobby::getInstance()->addPlayer(profile);
    m_server = event->getPeer();
    m_state = CONNECTED;
}   // connectionAccepted
/*! \brief Called when a player votes for a minor race mode.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0           1
 *       -------------------------------
 *  Size |      1    |        4        |
 *  Data | player id | minor mode vote |
 *       -------------------------------
 */
void ClientLobbyRoomProtocol::playerMinorVote(Event* event)
{
    if (!checkDataSize(event, 2)) return;
    const NetworkString &data = event->data();
    uint8_t player_id = data.getUInt8();
    uint8_t minor     = data.getUInt8();
    m_setup->getRaceConfig()->setPlayerMinorVote(player_id, minor);
}   // playerMinorVote
/*! \brief Called when a player votes for a major race mode.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0           1      2
 *       ----------------------------------------
 *  Size |     1     |   1  |       1           |
 *  Data | player id | laps | track number (gp) |
 *       ----------------------------------------
 */
void ClientLobbyRoomProtocol::playerLapsVote(Event* event)
{
    if (!checkDataSize(event, 3)) return;
    const NetworkString &data = event->data();
    uint8_t player_id = data.getUInt8();
    uint8_t laps      = data.getUInt8();
    uint8_t number    = data.getUInt8();
    m_setup->getRaceConfig()->setPlayerLapsVote(player_id, laps, number);
}   // playerLapsVote
/*! \brief Called when a player votes for a track.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0           1                   2   3
 *       --------------------------------------------------
 *  Size |      1    |       1           | 1 |     N      |
 *  Data | player id | track number (gp) | N | track name |
 *       --------------------------------------------------
 */
void ClientLobbyRoomProtocol::playerTrackVote(Event* event)
{
    if (!checkDataSize(event, 3)) return;
    const NetworkString &data = event->data();
    std::string track_name;
    uint8_t player_id = data.getUInt8();
    uint8_t number    = data.getUInt8();
    int N = data.decodeString(&track_name);
    m_setup->getRaceConfig()->setPlayerTrackVote(player_id, track_name,
                                                 number);
}   // playerTrackVote
/*! \brief Called when a player votes for a minor race mode.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0           1
 *       -------------------------------
 *  Size |      1    |         4       |
 *  Data | player-id | minor mode vote |
 *       -------------------------------
 */
void ServerLobbyRoomProtocol::playerMinorVote(Event* event)
{
    if (!checkDataSize(event, 1)) return;
    NetworkString &data = event->data();
    uint8_t player_id   = data.getUInt8();
    uint32_t minor      = data.getUInt32();
    m_setup->getRaceConfig()->setPlayerMinorVote(player_id, minor);

    // Send the vote to everybody (including the sender)
    NetworkString *other = getNetworkString(3);
    other->addUInt8(LE_VOTE_MINOR).addUInt8(player_id).addUInt8(minor); 
    sendMessageToPeersChangingToken(other);
    delete other;
}   // playerMinorVote
/*! \brief Called when all karts have finished the race.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0           1
 *       -------------------------------
 *  Size |     1     |     1     |     |
 *  Data | Kart 1 ID | kart id 2 | ... |
 *       -------------------------------
 */
void ClientLobbyRoomProtocol::raceFinished(Event* event)
{
    if(!checkDataSize(event, 1)) return;

    NetworkString &data = event->data();
    Log::error("ClientLobbyRoomProtocol",
               "Server notified that the race is finished.");

    // stop race protocols
    Protocol* protocol = ProtocolManager::getInstance()
                       ->getProtocol(PROTOCOL_CONTROLLER_EVENTS);
    if (protocol)
        ProtocolManager::getInstance()->requestTerminate(protocol);
    else
        Log::error("ClientLobbyRoomProtocol",
                   "No controller events protocol registered.");

    protocol = ProtocolManager::getInstance() 
             ->getProtocol(PROTOCOL_KART_UPDATE);
    if (protocol)
        ProtocolManager::getInstance()->requestTerminate(protocol);
    else
        Log::error("ClientLobbyRoomProtocol",
                   "No kart update protocol registered.");

    protocol = ProtocolManager::getInstance()
             ->getProtocol(PROTOCOL_GAME_EVENTS);
    if (protocol)
        ProtocolManager::getInstance()->requestTerminate(protocol);
    else
        Log::error("ClientLobbyRoomProtocol",
                   "No game events protocol registered.");

    // finish the race
    WorldWithRank* ranked_world = (WorldWithRank*)(World::getWorld());
    ranked_world->beginSetKartPositions();
    ranked_world->setPhase(WorldStatus::RESULT_DISPLAY_PHASE);
    int position = 1;
    while(data.size()>0)
    {
        uint8_t kart_id = data.getUInt8();
        ranked_world->setKartPosition(kart_id,position);
        Log::info("ClientLobbyRoomProtocol", "Kart %d has finished #%d",
                  kart_id, position);
        position++;
    }
    ranked_world->endSetKartPositions();
    m_state = RACE_FINISHED;
    ranked_world->terminateRace();
}   // raceFinished
/*! \brief Called when a player votes for a major race mode.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0           1      2 
 *       ----------------------------------------
 *  Size |     1     |   1  |       1           |
 *  Data | player id | laps | track number (gp) |
 *       ----------------------------------------
 */
void ServerLobbyRoomProtocol::playerLapsVote(Event* event)
{
    if (!checkDataSize(event, 2)) return;
    NetworkString &data = event->data();
    uint8_t player_id   = data.getUInt8();
    uint8_t lap_count   = data.getUInt8();
    uint8_t track_nb    = data.getUInt8();
    m_setup->getRaceConfig()->setPlayerLapsVote(player_id, lap_count,
                                                track_nb);
    NetworkString *other = getNetworkString(4);
    other->addUInt8(LE_VOTE_LAPS).addUInt8(player_id).addUInt8(lap_count)
          .addUInt8(track_nb);
    sendMessageToPeersChangingToken(other);
    delete other;
}   // playerLapsVote
/*! \brief Called when the server tells to update a player's kart.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0           1           2                    3           N+3
 *       --------------------------------------------------
 *  Size |    1      |       1            |     N     |
 *  Data | player id | N (kart name size) | kart name |
 *       --------------------------------------------------
 */
void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event)
{
    if(!checkDataSize(event, 3)) return;
    const NetworkString &data = event->data();
    uint8_t player_id = data.getUInt8();
    std::string kart_name;
    data.decodeString(&kart_name);
    if (!m_setup->isKartAvailable(kart_name))
    {
        Log::error("ClientLobbyRoomProtocol",
                   "The updated kart is taken already.");
    }
    m_setup->setPlayerKart(player_id, kart_name);
    NetworkKartSelectionScreen::getInstance()->playerSelected(player_id,
                                                              kart_name);
}   // kartSelectionUpdate
/*! \brief Called when a player votes for the reverse mode of a race
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0           1          2
 *       --------------------------------------------
 *  Size |     1     |     1    |       1           |
 *  Data | player id | reversed | track number (gp) |
 *       --------------------------------------------
 */
void ServerLobbyRoomProtocol::playerReversedVote(Event* event)
{
    if (!checkDataSize(event, 3)) return;

    NetworkString &data = event->data();
    uint8_t player_id   = data.getUInt8();
    uint8_t reverse     = data.getUInt8();
    uint8_t nb_track    = data.getUInt8();
    m_setup->getRaceConfig()->setPlayerReversedVote(player_id,
                                                    reverse!=0, nb_track);
    // Send the vote to everybody (including the sender)
    NetworkString *other = getNetworkString(4);
    other->addUInt8(LE_VOTE_REVERSE).addUInt8(player_id).addUInt8(reverse)
          .addUInt8(nb_track);
    sendMessageToPeersChangingToken(other);
    delete other;
}   // playerReversedVote
/*! \brief Called when a player votes for a track.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0           1                    2  3
 *       --------------------------------------------------
 *  Size |     1     |        1          | 1 |      N     |
 *  Data | player id | track number (gp) | N | track name |
 *       --------------------------------------------------
 */
void ServerLobbyRoomProtocol::playerTrackVote(Event* event)
{
    if (!checkDataSize(event, 3)) return;
    NetworkString &data  = event->data();
    uint8_t player_id    = data.getUInt8();
    // As which track this track should be used, e.g. 1st track: Sandtrack
    // 2nd track Mathclass, ...
    uint8_t track_number = data.getUInt8();
    std::string track_name;
    int N = data.decodeString(&track_name);
    m_setup->getRaceConfig()->setPlayerTrackVote(player_id, track_name,
                                                 track_number);
    // Send the vote to everybody (including the sender)
    NetworkString *other = getNetworkString(3+1+data.size());
    other->addUInt8(LE_VOTE_TRACK).addUInt8(player_id).addUInt8(track_number)
          .encodeString(track_name);
    sendMessageToPeersChangingToken(other);
    delete other;
    if(m_setup->getRaceConfig()->getNumTrackVotes()==m_setup->getPlayerCount())
        startGame();
}   // playerTrackVote
/*! \brief Called when the server refuses the kart selection request.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0
 *       ----------------
 *  Size |      1       |
 *  Data | refusal code |
 *       ----------------
 */
void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
{
    if(!checkDataSize(event, 1)) return;

    const NetworkString &data = event->data();

    switch (data.getUInt8()) // the error code
    {
    case 0:
        Log::info("ClientLobbyRoomProtocol",
                  "Kart selection refused : already taken.");
        break;
    case 1:
        Log::info("ClientLobbyRoomProtocol",
                  "Kart selection refused : not available.");
        break;
    default:
        Log::info("ClientLobbyRoomProtocol", "Kart selection refused.");
        break;
    }
}   // kartSelectionRefused
/*! \brief Called when the server refuses the connection.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0 
 *       ----------------
 *  Size |      1       |
 *  Data | refusal code |
 *       ----------------
 */
void ClientLobbyRoomProtocol::connectionRefused(Event* event)
{
    if (!checkDataSize(event, 1)) return;
    const NetworkString &data = event->data();
    
    switch (data.getUInt8()) // the second byte
    {
    case 0:
        Log::info("ClientLobbyRoomProtocol",
                  "Connection refused : too many players.");
        break;
    case 1:
        Log::info("ClientLobbyRoomProtocol", "Connection refused : banned.");
        break;
    case 2:
        Log::info("ClientLobbyRoomProtocol", "Client busy.");
        break;
    default:
        Log::info("ClientLobbyRoomProtocol", "Connection refused.");
        break;
    }
}   // connectionRefused
/*! \brief Called when a new player is disconnected
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0 
 *       --------------
 *  Size |    1       |
 *  Data | player id *|
 *       --------------
 */
void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
{
    if (!checkDataSize(event, 1)) return;

    NetworkString &data = event->data();
    while(data.size()>0)
    {
        const NetworkPlayerProfile *profile = 
                        m_setup->getProfile(data.getUInt8());
        if (m_setup->removePlayer(profile))
        {
            Log::info("ClientLobbyRoomProtocol",
                      "Player %d removed successfully.",
                      profile->getGlobalPlayerId());
        }
        else
        {
            Log::error("ClientLobbyRoomProtocol",
                       "The disconnected peer wasn't known.");
        }
    }   // while

    STKHost::get()->removePeer(event->getPeer());
}   // disconnectedPlayer
Пример #16
0
/** Called when receiving a message. On the client side the message is a ping
 *  from the server, which is answered back. On the server the received message
 *  is a reply to a previous ping request. The server will keep track of
 *  average latency.
 */
bool LatencyProtocol::notifyEventAsynchronous(Event* event)
{
    if (event->getType() != EVENT_TYPE_MESSAGE)
        return true;
    if(!checkDataSize(event, 5)) return true;

    const NetworkString &data = event->data();
    uint32_t request  = data.getUInt8();
    uint32_t sequence = data.getUInt32();

    const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
    assert(peers.size() > 0);

    // Find the right peer id. The host id (i.e. each host sendings its
    // host id) can not be used here, since host ids can have gaps (if a
    // host should disconnect)
    uint8_t peer_id = -1;
    for (unsigned int i = 0; i < peers.size(); i++)
    {
        if (peers[i]->isSamePeer(event->getPeer()))
        {
            peer_id = i;
            break;
        }
    }

    if (request)
    {
        // Only a client should receive a request for a ping response
        assert(NetworkConfig::get()->isClient());
        NetworkString *response = getNetworkString(5);
        // The '0' indicates a response to a ping request
        response->addUInt8(0).addUInt32(sequence);
        event->getPeer()->sendPacket(response, false);
        delete response;
    }
    else // receive response to a ping request
    {
        // Only a server should receive this kind of message
        assert(NetworkConfig::get()->isServer());
        if (sequence >= m_pings[peer_id].size())
        {
            Log::warn("LatencyProtocol",
                      "The sequence# %u isn't known.", sequence);
            return true;
        }
        double current_time = StkTime::getRealTime();
        m_total_diff[peer_id] += current_time - m_pings[peer_id][sequence];
        m_successed_pings[peer_id]++;
        m_average_ping[peer_id] =
            (int)((m_total_diff[peer_id]/m_successed_pings[peer_id])*1000.0);

        Log::debug("LatencyProtocol",
            "Peer %d sequence %d ping %u average %u at %lf",
            peer_id, sequence,
            (unsigned int)((current_time - m_pings[peer_id][sequence])*1000),
            m_average_ping[peer_id],
            StkTime::getRealTime());
    }
    return true;
}   // notifyEventAsynchronous
//-----------------------------------------------------------------------------------------
astra::CFloat32Data3DMemory *
allocateDataObject(const std::string & sDataType,
		const mxArray * const geometry, const mxArray * const data,
		const mxArray * const unshare, const mxArray * const zIndex)
{
	astra::CFloat32Data3DMemory* pDataObject3D = NULL;

	bool bUnshare = true;
	if (unshare)
	{
		if (!mexIsScalar(unshare))
		{
			mexErrMsgTxt("Argument 5 (read-only) must be scalar");
			return NULL;
		}
		// unshare the array if we're not linking read-only
		bUnshare = !(bool)mxGetScalar(unshare);
	}

	mwIndex iZ = 0;
	if (zIndex)
	{
		if (!mexIsScalar(zIndex))
		{
			mexErrMsgTxt("Argument 6 (Z) must be scalar");
			return NULL;
		}
		iZ = (mwSignedIndex)mxGetScalar(zIndex);
	}

	// SWITCH DataType
	if (sDataType == "-vol")
	{
		// Read geometry
		astra::Config* cfg = structToConfig("VolumeGeometry3D", geometry);
		astra::CVolumeGeometry3D* pGeometry = new astra::CVolumeGeometry3D();
		if (!pGeometry->initialize(*cfg))
		{
			mexErrMsgTxt("Geometry class not initialized. \n");
			delete pGeometry;
			delete cfg;
			return NULL;
		}
		delete cfg;

		// If data is specified, check dimensions
		if (data && !mexIsScalar(data))
		{
			if (! (zIndex
					? checkDataSize(data, pGeometry, iZ)
					: checkDataSize(data, pGeometry)) )
			{
				mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry. \n");
				delete pGeometry;
				return NULL;
			}
		}

		// Initialize data object
#ifdef USE_MATLAB_UNDOCUMENTED
		if (unshare) {
			CFloat32CustomMemoryMatlab3D* pHandle =
					new CFloat32CustomMemoryMatlab3D(data, bUnshare, iZ);

			// Initialize data object
			pDataObject3D = new astra::CFloat32VolumeData3DMemory(pGeometry, pHandle);
		}
		else
		{
			pDataObject3D = new astra::CFloat32VolumeData3DMemory(pGeometry);
		}
#else
		pDataObject3D = new astra::CFloat32VolumeData3DMemory(pGeometry);
#endif
		delete pGeometry;
	}
	else if (sDataType == "-sino" || sDataType == "-proj3d" || sDataType == "-sinocone")
	{
		// Read geometry
		astra::Config* cfg = structToConfig("ProjectionGeometry3D", geometry);
		// FIXME: Change how the base class is created. (This is duplicated
		// in Projector3D.cpp.)
		std::string type = cfg->self.getAttribute("type");
		astra::CProjectionGeometry3D* pGeometry = 0;
		if (type == "parallel3d") {
			pGeometry = new astra::CParallelProjectionGeometry3D();
		} else if (type == "parallel3d_vec") {
			pGeometry = new astra::CParallelVecProjectionGeometry3D();
		} else if (type == "cone") {
			pGeometry = new astra::CConeProjectionGeometry3D();
		} else if (type == "cone_vec") {
			pGeometry = new astra::CConeVecProjectionGeometry3D();
		} else {
			mexErrMsgTxt("Invalid geometry type.\n");
			return NULL;
		}

		if (!pGeometry->initialize(*cfg)) {
			mexErrMsgTxt("Geometry class not initialized. \n");
			delete pGeometry;
			delete cfg;
			return NULL;
		}
		delete cfg;

		// If data is specified, check dimensions
		if (data && !mexIsScalar(data))
		{
			if (! (zIndex
					? checkDataSize(data, pGeometry, iZ)
					: checkDataSize(data, pGeometry)) )
			{
				mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry. \n");
				delete pGeometry;
				return NULL;
			}
		}

		// Initialize data object
#ifdef USE_MATLAB_UNDOCUMENTED
		if (unshare)
		{
			CFloat32CustomMemoryMatlab3D* pHandle =
					new CFloat32CustomMemoryMatlab3D(data, bUnshare, iZ);

			// Initialize data object
			pDataObject3D = new astra::CFloat32ProjectionData3DMemory(pGeometry, pHandle);
		}
		else
		{
			pDataObject3D = new astra::CFloat32ProjectionData3DMemory(pGeometry);
		}
#else
		pDataObject3D = new astra::CFloat32ProjectionData3DMemory(pGeometry);
#endif
		delete pGeometry;
	}
	else
	{
		mexErrMsgTxt("Invalid datatype.  Please specify '-vol' or '-proj3d'. \n");
		return NULL;
	}

	// Check initialization
	if (!pDataObject3D->isInitialized())
	{
		mexErrMsgTxt("Couldn't initialize data object.\n");
		delete pDataObject3D;
		return NULL;
	}

	return pDataObject3D;
}