<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "../Interface/Database.h"
#include "../Interface/Server.h"
#include "../Interface/DatabaseCursor.h"
#include "../Interface/File.h"
#include "database.h"
#include "server_settings.h"
#include "LMDBFileIndex.h"
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include "serverinterface/helper.h"
#include "dao/ServerBackupDao.h"

namespace
{
const size_t sqlite_data_allocation_chunk_size = 50 * 1024 * 1024; //50MB

struct SCallbackData
{
	IDatabaseCursor* cur;
	int64 pos;
	int64 max_pos;
	SStartupStatus* status;
};

db_results create_callback(size_t n_done, size_t n_rows, void *userdata)
{
	SCallbackData *data=(SCallbackData*)userdata;

	data->status->processed_file_entries=n_done;

	int last_pc = static_cast<int>(data->status->pc_done*1000 + 0.5);

	if(data->max_pos>0)
	{
		data->status->pc_done = static_cast<double>(n_rows)/data->max_pos;
	}

	int curr_pc = static_cast<int>(data->status->pc_done*1000 + 0.5);

	if(curr_pc!=last_pc)
	{
		Server->Log("Creating files index: "+convert((double)curr_pc/10)+"% finished", LL_INFO);
	}

	db_results ret;
	db_single_result res;

	if(data->cur->next(res))
	{
		ret.push_back(res);
	}

	return ret;
}

bool create_files_index_common(FileIndex& fileindex, SStartupStatus& status)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_FILES);

	db_results cache_res;
	if(db->getEngineName()=="sqlite")
	{
		Server->Log("Deleting database journal...", LL_INFO);
		db->Write("PRAGMA journal_mode = DELETE");

		if (FileExists("urbackup/backup_server_files.db-journal")
			|| FileExists("urbackup/backup_server_files.db-wal"))
		{
			Server->Log("Deleting database journal failed. Aborting.", LL_ERROR);
			return false;
		}

		Server->destroyAllDatabases();

		Server->deleteFile("urbackup/backup_server_files_new.db");

		Server->Log("Copying/reflinking database...", LL_INFO);
		if (!os_create_hardlink("urbackup/backup_server_files_new.db",
			"urbackup/backup_server_files.db", true, NULL))
		{
			Server->Log("Reflinking failed. Falling back to copying...", LL_DEBUG);

			if (!copy_file("urbackup/backup_server_files.db",
				"urbackup/backup_server_files_new.db"))
			{
				Server->Log("Copying file failed. " + os_last_error_str(), LL_ERROR);
				return false;
			}
		}

		str_map params;
		if (!Server->openDatabase("urbackup/backup_server_files_new.db", URBACKUPDB_SERVER_FILES_NEW, params))
		{
			Server->Log("Couldn't open Database backup_server_files_new.db. Exiting. Expecting database at \"" +
				Server->getServerWorkingDir() + os_file_sep() + "urbackup" + os_file_sep() + "backup_server_files_new.db\"", LL_ERROR);
			return false;
		}

		Server->setDatabaseAllocationChunkSize(URBACKUPDB_SERVER_FILES_NEW, sqlite_data_allocation_chunk_size);

		db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_FILES_NEW);
		if (db==NULL)
		{
			Server->Log("Couldn't open backup server database. Exiting. Expecting database at \"" +
				Server->getServerWorkingDir() + os_file_sep() + "urbackup" + os_file_sep() + "backup_server_files_new.db\"", LL_ERROR);
			return false;
		}

		cache_res=db->Read("PRAGMA cache_size");
		ServerSettings server_settings(db);
		db->Write("PRAGMA cache_size = -"+convert(server_settings.getSettings()->update_stats_cachesize));

		db->Write("PRAGMA journal_mode = OFF");
		db->Write("PRAGMA synchronous = OFF");
	}

	status.creating_filesindex=true;
	Server->Log("Creating file entry index. This might take a while...", LL_WARNING);

	Server->Log("Getting number of files...", LL_INFO);

	db_results res = db->Read("SELECT COUNT(*) AS c FROM files");

	int64 n_files = 0;
	if(!res.empty())
	{
		n_files=watoi64(res[0]["c"]);
	}

	Server->Log("Dropping index...", LL_INFO);

	db->Write("DROP INDEX IF EXISTS files_backupid");

	Server->Log("Starting creating files index...", LL_INFO);

	IQuery *q_read=db->Prepare("SELECT id, shahash, filesize, clientid, next_entry, prev_entry, pointed_to FROM files ORDER BY shahash ASC, filesize ASC, clientid ASC, created DESC");

	SCallbackData data;
	data.cur=q_read->Cursor();
	data.pos=0;
	data.max_pos=n_files;
	data.status=&status;

	fileindex.create(create_callback, &data);

	if(fileindex.has_error())
	{
		return false;
	}
	else
	{
		if (data.cur->has_error())
		{
			return false;
		}

		Server->Log("Creating backupid index...", LL_INFO);

		db->Write("CREATE INDEX files_backupid ON files (backupid)");

		Server->Log("Syncing...", LL_INFO);

		Server->destroyAllDatabases();

		std::auto_ptr<IFile> db_file(Server->openFile("urbackup/backup_server_files_new.db", MODE_RW));

		if (db_file.get() == NULL)
		{
			Server->Log("Error opening new database file", LL_ERROR);
			return false;
		}

		db_file->Sync();
		db_file.reset();

		Server->Log("Renaming back result...", LL_INFO);

		if (!os_rename_file("urbackup/backup_server_files_new.db",
			"urbackup/backup_server_files.db"))
		{
			Server->Log("Renaming database file failed. " + os_last_error_str(), LL_ERROR);
			return false;
		}

		db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_FILES);

		if (db == NULL)
		{
			Server->Log("Error opening database after file index creation.", LL_ERROR);
			return false;
		}

		db->Write("PRAGMA journal_mode = WAL");
	}

	status.creating_filesindex=false;

	return true;
}

bool setup_lmdb_file_index(SStartupStatus& status)
{
	LMDBFileIndex fileindex(true);;
	if(fileindex.has_error())
	{
		Server->Log("Error creating file index", LL_ERROR);
		return false;
	}

	return create_files_index_common(fileindex, status);
}

}

void delete_file_index(void)
{
	Server->deleteFile("urbackup/fileindex/backup_server_files_index.lmdb");
	Server->deleteFile("urbackup/fileindex/backup_server_files_index.lmdb-lock");
}

bool create_files_index(SStartupStatus& status)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);

	bool creating_index;

	{
		ServerBackupDao backupdao(db);
		creating_index = backupdao.getMiscValue("creating_file_entry_index").value == "true";
	}

	if(!FileExists("urbackup/fileindex/backup_server_files_index.lmdb") || creating_index)
	{
		delete_file_index();

		{
			DBScopedSynchronous synchronous_db(db);

			ServerBackupDao backupdao(db);

			backupdao.delMiscValue("creating_file_entry_index");
			backupdao.addMiscValue("creating_file_entry_index", "true");
		}

		status.upgrading_database=false;
		status.creating_filesindex=true;

		if(!setup_lmdb_file_index(status))
		{
			Server->Log("Setting up file index failed", LL_ERROR);
			return false;
		}
		else
		{
			db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
			ServerBackupDao backupdao(db);
			backupdao.delMiscValue("creating_file_entry_index");
		}
	}

	LMDBFileIndex::initFileIndex();

	return true;

}

FileIndex* create_lmdb_files_index(void)
{
	if(!FileExists("urbackup/fileindex/backup_server_files_index.lmdb"))
	{
		return NULL;
	}

	return new LMDBFileIndex();
}<commit_msg>Don't increase cache size (use os cache)<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "../Interface/Database.h"
#include "../Interface/Server.h"
#include "../Interface/DatabaseCursor.h"
#include "../Interface/File.h"
#include "database.h"
#include "server_settings.h"
#include "LMDBFileIndex.h"
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include "serverinterface/helper.h"
#include "dao/ServerBackupDao.h"

namespace
{
const size_t sqlite_data_allocation_chunk_size = 50 * 1024 * 1024; //50MB

struct SCallbackData
{
	IDatabaseCursor* cur;
	int64 pos;
	int64 max_pos;
	SStartupStatus* status;
};

db_results create_callback(size_t n_done, size_t n_rows, void *userdata)
{
	SCallbackData *data=(SCallbackData*)userdata;

	data->status->processed_file_entries=n_done;

	int last_pc = static_cast<int>(data->status->pc_done*1000 + 0.5);

	if(data->max_pos>0)
	{
		data->status->pc_done = static_cast<double>(n_rows)/data->max_pos;
	}

	int curr_pc = static_cast<int>(data->status->pc_done*1000 + 0.5);

	if(curr_pc!=last_pc)
	{
		Server->Log("Creating files index: "+convert((double)curr_pc/10)+"% finished", LL_INFO);
	}

	db_results ret;
	db_single_result res;

	if(data->cur->next(res))
	{
		ret.push_back(res);
	}

	return ret;
}

bool create_files_index_common(FileIndex& fileindex, SStartupStatus& status)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_FILES);

	if(db->getEngineName()=="sqlite")
	{
		Server->Log("Deleting database journal...", LL_INFO);
		db->Write("PRAGMA journal_mode = DELETE");

		if (FileExists("urbackup/backup_server_files.db-journal")
			|| FileExists("urbackup/backup_server_files.db-wal"))
		{
			Server->Log("Deleting database journal failed. Aborting.", LL_ERROR);
			return false;
		}

		Server->destroyAllDatabases();

		Server->deleteFile("urbackup/backup_server_files_new.db");

		Server->Log("Copying/reflinking database...", LL_INFO);
		if (!os_create_hardlink("urbackup/backup_server_files_new.db",
			"urbackup/backup_server_files.db", true, NULL))
		{
			Server->Log("Reflinking failed. Falling back to copying...", LL_DEBUG);

			if (!copy_file("urbackup/backup_server_files.db",
				"urbackup/backup_server_files_new.db"))
			{
				Server->Log("Copying file failed. " + os_last_error_str(), LL_ERROR);
				return false;
			}
		}

		str_map params;
		if (!Server->openDatabase("urbackup/backup_server_files_new.db", URBACKUPDB_SERVER_FILES_NEW, params))
		{
			Server->Log("Couldn't open Database backup_server_files_new.db. Exiting. Expecting database at \"" +
				Server->getServerWorkingDir() + os_file_sep() + "urbackup" + os_file_sep() + "backup_server_files_new.db\"", LL_ERROR);
			return false;
		}

		Server->setDatabaseAllocationChunkSize(URBACKUPDB_SERVER_FILES_NEW, sqlite_data_allocation_chunk_size);

		db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_FILES_NEW);
		if (db==NULL)
		{
			Server->Log("Couldn't open backup server database. Exiting. Expecting database at \"" +
				Server->getServerWorkingDir() + os_file_sep() + "urbackup" + os_file_sep() + "backup_server_files_new.db\"", LL_ERROR);
			return false;
		}

		db->Write("PRAGMA journal_mode = OFF");
		db->Write("PRAGMA synchronous = OFF");
	}

	status.creating_filesindex=true;
	Server->Log("Creating file entry index. This might take a while...", LL_WARNING);

	Server->Log("Getting number of files...", LL_INFO);

	db_results res = db->Read("SELECT COUNT(*) AS c FROM files");

	int64 n_files = 0;
	if(!res.empty())
	{
		n_files=watoi64(res[0]["c"]);
	}

	Server->Log("Dropping index...", LL_INFO);

	db->Write("DROP INDEX IF EXISTS files_backupid");

	Server->Log("Starting creating files index...", LL_INFO);

	IQuery *q_read=db->Prepare("SELECT id, shahash, filesize, clientid, next_entry, prev_entry, pointed_to FROM files ORDER BY shahash ASC, filesize ASC, clientid ASC, created DESC");

	SCallbackData data;
	data.cur=q_read->Cursor();
	data.pos=0;
	data.max_pos=n_files;
	data.status=&status;

	fileindex.create(create_callback, &data);

	if(fileindex.has_error())
	{
		return false;
	}
	else
	{
		if (data.cur->has_error())
		{
			return false;
		}

		Server->Log("Creating backupid index...", LL_INFO);

		db->Write("CREATE INDEX files_backupid ON files (backupid)");

		Server->Log("Syncing...", LL_INFO);

		Server->destroyAllDatabases();

		std::auto_ptr<IFile> db_file(Server->openFile("urbackup/backup_server_files_new.db", MODE_RW));

		if (db_file.get() == NULL)
		{
			Server->Log("Error opening new database file", LL_ERROR);
			return false;
		}

		db_file->Sync();
		db_file.reset();

		Server->Log("Renaming back result...", LL_INFO);

		if (!os_rename_file("urbackup/backup_server_files_new.db",
			"urbackup/backup_server_files.db"))
		{
			Server->Log("Renaming database file failed. " + os_last_error_str(), LL_ERROR);
			return false;
		}

		db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_FILES);

		if (db == NULL)
		{
			Server->Log("Error opening database after file index creation.", LL_ERROR);
			return false;
		}

		db->Write("PRAGMA journal_mode = WAL");
	}

	status.creating_filesindex=false;

	return true;
}

bool setup_lmdb_file_index(SStartupStatus& status)
{
	LMDBFileIndex fileindex(true);;
	if(fileindex.has_error())
	{
		Server->Log("Error creating file index", LL_ERROR);
		return false;
	}

	return create_files_index_common(fileindex, status);
}

}

void delete_file_index(void)
{
	Server->deleteFile("urbackup/fileindex/backup_server_files_index.lmdb");
	Server->deleteFile("urbackup/fileindex/backup_server_files_index.lmdb-lock");
}

bool create_files_index(SStartupStatus& status)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);

	bool creating_index;

	{
		ServerBackupDao backupdao(db);
		creating_index = backupdao.getMiscValue("creating_file_entry_index").value == "true";
	}

	if(!FileExists("urbackup/fileindex/backup_server_files_index.lmdb") || creating_index)
	{
		delete_file_index();

		{
			DBScopedSynchronous synchronous_db(db);

			ServerBackupDao backupdao(db);

			backupdao.delMiscValue("creating_file_entry_index");
			backupdao.addMiscValue("creating_file_entry_index", "true");
		}

		status.upgrading_database=false;
		status.creating_filesindex=true;

		if(!setup_lmdb_file_index(status))
		{
			Server->Log("Setting up file index failed", LL_ERROR);
			return false;
		}
		else
		{
			db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
			ServerBackupDao backupdao(db);
			backupdao.delMiscValue("creating_file_entry_index");
		}
	}

	LMDBFileIndex::initFileIndex();

	return true;

}

FileIndex* create_lmdb_files_index(void)
{
	if(!FileExists("urbackup/fileindex/backup_server_files_index.lmdb"))
	{
		return NULL;
	}

	return new LMDBFileIndex();
}<|endoftext|>


<commit_before>/**
 * @file typedef.hpp
 * @author Ryan Curtin
 *
 * Simple typedefs describing template instantiations of the NeighborSearch
 * class which are commonly used.  This is meant to be included by
 * neighbor_search.h but is a separate file for simplicity.
 */
#ifndef MLPACK_NEIGHBOR_SEARCH_TYPEDEF_H
#define MLPACK_NEIGHBOR_SEARCH_TYPEDEF_H

// In case someone included this directly.
#include "neighbor_search.hpp"

#include <mlpack/core/metrics/lmetric.hpp>

#include "sort_policies/nearest_neighbor_sort.hpp"
#include "sort_policies/furthest_neighbor_sort.hpp"

namespace mlpack {
namespace neighbor {

/**
 * The AllkNN class is the all-k-nearest-neighbors method.  It returns L2
 * distances (Euclidean distances) for each of the k nearest neighbors.
 */
typedef NeighborSearch<NearestNeighborSort, metric::EuclideanDistance> AllkNN;

/**
 * The AllkFN class is the all-k-furthest-neighbors method.  It returns L2
 * distances (Euclidean distances) for each of the k furthest neighbors.
 */
typedef NeighborSearch<FurthestNeighborSort, metric::EuclideanDistance> AllkFN;

} // namespace neighbor
} // namespace mlpack

#endif
<commit_msg>Deprecate old names; add new names.<commit_after>/**
 * @file typedef.hpp
 * @author Ryan Curtin
 *
 * Simple typedefs describing template instantiations of the NeighborSearch
 * class which are commonly used.  This is meant to be included by
 * neighbor_search.h but is a separate file for simplicity.
 */
#ifndef MLPACK_NEIGHBOR_SEARCH_TYPEDEF_H
#define MLPACK_NEIGHBOR_SEARCH_TYPEDEF_H

// In case someone included this directly.
#include "neighbor_search.hpp"

#include <mlpack/core/metrics/lmetric.hpp>

#include "sort_policies/nearest_neighbor_sort.hpp"
#include "sort_policies/furthest_neighbor_sort.hpp"

namespace mlpack {
namespace neighbor {

/**
 * The KNN class is the k-nearest-neighbors method.  It returns L2 distances
 * (Euclidean distances) for each of the k nearest neighbors.
 */
typedef NeighborSearch<NearestNeighborSort, metric::EuclideanDistance> KNN;

/**
 * The KFN class is the k-furthest-neighbors method.  It returns L2 distances
 * (Euclidean distances) for each of the k furthest neighbors.
 */
typedef NeighborSearch<FurthestNeighborSort, metric::EuclideanDistance> KFN;

/**
 * @deprecated
 * The AllkNN class is the k-nearest-neighbors method.  It returns L2 distances
 * (Euclidean distances) for each of the k nearest neighbors.  This typedef will
 * be removed in mlpack 3.0.0; use the KNN typedef instead.
 */
typedef NeighborSearch<NearestNeighborSort, metric::EuclideanDistance> AllkNN;

/**
 * @deprecated
 * The AllkFN class is the k-furthest-neighbors method.  It returns L2
 * distances (Euclidean distances) for each of the k furthest neighbors.  This
 * typedef will be removed in mlpack 3.0.0; use the KFN typedef instead.
 */
typedef NeighborSearch<FurthestNeighborSort, metric::EuclideanDistance> AllkFN;

} // namespace neighbor
} // namespace mlpack

#endif
<|endoftext|>


<commit_before>#include "flatgltf/2.0/glTFio.hpp"
#include "flatgltf/2.0/glTF_generated.h"
#include "flatgltf/2.0/glTFapi.hpp"
#include "flatgltf/common/glTFutils.hpp"
#include "glTFinternal.hpp"

#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"

#define KHUTILS_ASSERTION_INLINE
#include "khutils/assertion.hpp"
#include "khutils/file.hpp"
#include "khutils/logging.hpp"
#include "khutils/runtime_exceptions.hpp"

/// terribly sorry for this dependency. will remove asap
#include <boost/filesystem/path.hpp>

#include <algorithm>
#include <memory>
#include <numeric>
#include <string>
#include <vector>

// flatbuffer schema string for parser
extern const std::string flatgltf_2_0_schema;

namespace glTF_2_0
{
	using namespace glTF_common;

	///------------------------------------------------------------------------
	/// load document as-is, without modification or external data
	///------------------------------------------------------------------------

	inline void initializeDocument(Document* const doc, Root_t&& root)
	{
		KHUTILS_ASSERT_PTR(doc);
		KHUTILS_ASSERT_PTR(root);

		doc->root.swap(root);
		doc->bindata.clear();
		doc->imgdata.clear();
	}

	//---

	// load document as-is, without modification or external data
	bool loadDocument_json(Document* const doc, const char* location, data_reader_t reader)
	{
		KHUTILS_ASSERT_PTR(doc);

		std::vector<uint8_t> buffer;
		auto				 readOk = reader(location, buffer);

		if (readOk)
		{
			KHUTILS_ASSERT_CNTR_NOT_EMPTY(buffer);
			std::string jsonString(reinterpret_cast<const char*>(buffer.data()), buffer.size());
			initializeDocument(doc, from_json_internal(jsonString));
			return true;
		}

		return false;
	}

	//---

	bool loadDocument_glf(Document* const doc, const char* location, data_reader_t reader)
	{
		std::vector<uint8_t> buffer;
		auto				 readOk = reader(location, buffer);

		if (readOk)
		{
			KHUTILS_ASSERT_CNTR_NOT_EMPTY(buffer);
			initializeDocument(doc, from_flatbuffer_internal(buffer));
			return true;
		}

		return false;
	}

	//---

	// loadDocument_glb implemented further below

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// load document: transform data uris to buffers, load external resources
	///------------------------------------------------------------------------

	bool loadDocument_dataAndReferences(Document* const doc, const char* location, data_reader_t reader)
	{
		KHUTILS_ASSERT_PTR(doc);

		bool allBuffersLoadOk = std::all_of(doc->root->buffers.begin(), doc->root->buffers.end(), [&](auto& buf) {
			if (isDataUri(buf->uri))
			{
				setBufferData(convertUriToData(buf->uri), doc, buf.get());
				return true;
			}

			std::vector<uint8_t>bufData;
			if (reader(buf->uri.c_str(), bufData))
			{
				setBufferData(bufData, doc, buf.get());
				return true;
			}
			return false;
		});

		bool allImagesLoadOk = std::all_of(doc->root->images.begin(), doc->root->images.end(), [&](auto& img) {
			if (isValidBufferViewId(doc, img->bufferView))
				return true;

			if (isDataUri(img->uri))
			{
				setImageData(convertUriToData(img->uri), doc, img.get());
				return true;
			}

			std::vector<uint8_t>bufData;
			if (reader(img->uri.c_str(), bufData))
			{
				setImageData(bufData, doc, img.get());
				return true;
			}
			return false;
		});

		return allBuffersLoadOk && allImagesLoadOk;
	}

	//---

	// load document: transform data uris to buffers, load external resources
	bool loadDocument_json_plus(Document* const doc, const char* location, data_reader_t reader)
	{
		return loadDocument_json(doc, location, reader) &&	//
			   loadDocument_dataAndReferences(doc, location, reader);
	}

	//---

	bool loadDocument_glf_plus(Document* const doc, const char* location, data_reader_t reader)
	{
		return loadDocument_glf(doc, location, reader) &&	//
			   loadDocument_dataAndReferences(doc, location, reader);
	}

	//---

	// load document from glTF-binary: all buffers merged into 1, with external data
	bool loadDocument_glb_plus(Document* const doc, const char* location, data_reader_t reader)
	{
		return loadDocument_glb(doc, location, reader) &&	//
			   loadDocument_dataAndReferences(doc, location, reader);
	}

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// write document as-is, without modification or external data
	///------------------------------------------------------------------------

	bool saveDocument_json(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto jsonString = to_json(doc->root);
		KHUTILS_ASSERT_CNTR_NOT_EMPTY(jsonString);

		std::vector<uint8_t> buffer;
		buffer.reserve(jsonString.size());
		std::transform(jsonString.begin(), jsonString.end(), std::back_inserter(buffer), [](auto& c) {
			return static_cast<uint8_t>(c);
		});

		return writer(location, buffer);
	}

	//---

	bool saveDocument_glf(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto buffer = to_flatbuffer(doc->root);
		KHUTILS_ASSERT_CNTR_NOT_EMPTY(buffer);

		return writer(location, buffer);
	}

	//---

	// bool saveDocument_glb implemented further below

	///------------------------------------------------------------------------
	/// write document as-is, write buffers and images set to external URIs
	///------------------------------------------------------------------------

	bool saveDocument_buffers(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		return std::all_of(doc->root->buffers.begin(), doc->root->buffers.end(), [&](auto& buf) {
			if (isDataUri(buf->uri))
				return true;

			return writer(buf->uri.c_str(), getBufferData(doc, buf.get()));
		});
	}

	//---

	bool saveDocument_images(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		return std::all_of(doc->root->images.begin(), doc->root->images.end(), [&](auto& img) {
			if (isDataUri(img->uri))
				return true;

			if (isValidBufferViewId(doc, img->bufferView))
				return true;

			return writer(img->uri.c_str(), getImageData(doc, img.get()));
		});
	}

	//---

	bool saveDocument_dataAndReferences(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);
		return saveDocument_buffers(doc, location, writer) && saveDocument_images(doc, location, writer);
	}

	//---

	bool saveDocument_json_plus(const Document* const doc, const char* location, data_writer_t writer)
	{
		return saveDocument_json(doc, location, writer) &&	//
			   saveDocument_dataAndReferences(doc, location, writer);
	}

	//---

	bool saveDocument_glf_plus(const Document* const doc, const char* location, data_writer_t writer)
	{
		return saveDocument_glf(doc, location, writer) &&	//
			   saveDocument_dataAndReferences(doc, location, writer);
	}

	//---

	bool saveDocument_glb_plus(const Document* const doc, const char* location, data_writer_t writer)
	{
		return saveDocument_glb(doc, location, writer) &&	 //
			   saveDocument_images(doc, location, writer);	// only external images, buffer is already written
	}

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// write document: ALL buffers/images will be embedded base64 URIs
	///------------------------------------------------------------------------

	bool saveDocument_json_embed(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto embeddedRoot = embedDocumentBuffersAndImages(doc);
		KHUTILS_ASSERT_PTR(embeddedRoot);

		auto jsonString = to_json(embeddedRoot);
		KHUTILS_ASSERT_CNTR_NOT_EMPTY(jsonString);

		std::vector<uint8_t> buffer;
		buffer.reserve(jsonString.size());
		std::transform(jsonString.begin(), jsonString.end(), std::back_inserter(buffer), [](auto& c) {
			return static_cast<uint8_t>(c);
		});

		return writer(location, buffer);
	}

	//---

	bool saveDocument_glf_embed(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto embeddedRoot = embedDocumentBuffersAndImages(doc);
		KHUTILS_ASSERT_PTR(embeddedRoot);

		auto buffer = to_flatbuffer(embeddedRoot);
		KHUTILS_ASSERT_CNTR_NOT_EMPTY(buffer);

		return writer(location, buffer);
	}

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// write document: ALL buffers/images will be external files named after URI or name or counter
	///------------------------------------------------------------------------

	bool saveDocument_json_external(const Document* const _doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(_doc);
		auto doc = createDocument("copy");

		return cloneDocument(_doc, doc) &&	//
			   dislodgeDocument(doc) &&		  //
			   saveDocument_json_plus(doc, location, writer);
	}

	//---

	bool saveDocument_glf_external(const Document* const _doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(_doc);
		auto doc = createDocument("copy");

		return cloneDocument(_doc, doc) &&	//
			   dislodgeDocument(doc) &&		  //
			   saveDocument_glf_plus(doc, location, writer);
	}

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// ease-of-use load/save functions, to file by default
	///------------------------------------------------------------------------

	namespace fs = boost::filesystem;

	bool loadDocument(Document* const doc, const char* uri)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto p = fs::path(uri);
		if (p.extension() == ".glb")
		{
			return loadDocument_glb_plus(doc, uri);
		}

		if (p.extension() == ".glf")
		{
			return loadDocument_glf_plus(doc, uri);
		}

		if (p.extension() == ".gltf")
		{
			return loadDocument_json_plus(doc, uri);
		}

		return false;
	}

	//---

	bool saveDocument(const Document* const doc, const char* uri)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto p = fs::path(uri);
		if (p.extension() == ".glb")
		{
			return saveDocument_glb_plus(doc, uri);
		}

		if (p.extension() == ".glf")
		{
			return saveDocument_glf_plus(doc, uri);
		}

		if (p.extension() == ".gltf")
		{
			return saveDocument_json_plus(doc, uri);
		}

		return false;
	}

	//-------------------------------------------------------------------------
	//-------------------------------------------------------------------------

}	// namespace glTF_2_0
<commit_msg>whitespace<commit_after>#include "flatgltf/2.0/glTFio.hpp"
#include "flatgltf/2.0/glTF_generated.h"
#include "flatgltf/2.0/glTFapi.hpp"
#include "flatgltf/common/glTFutils.hpp"
#include "glTFinternal.hpp"

#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"

#define KHUTILS_ASSERTION_INLINE
#include "khutils/assertion.hpp"
#include "khutils/file.hpp"
#include "khutils/logging.hpp"
#include "khutils/runtime_exceptions.hpp"

/// terribly sorry for this dependency. will remove asap
#include <boost/filesystem/path.hpp>

#include <algorithm>
#include <memory>
#include <numeric>
#include <string>
#include <vector>

// flatbuffer schema string for parser
extern const std::string flatgltf_2_0_schema;

namespace glTF_2_0
{
	using namespace glTF_common;

	///------------------------------------------------------------------------
	/// load document as-is, without modification or external data
	///------------------------------------------------------------------------

	inline void initializeDocument(Document* const doc, Root_t&& root)
	{
		KHUTILS_ASSERT_PTR(doc);
		KHUTILS_ASSERT_PTR(root);

		doc->root.swap(root);
		doc->bindata.clear();
		doc->imgdata.clear();
	}

	//---

	// load document as-is, without modification or external data
	bool loadDocument_json(Document* const doc, const char* location, data_reader_t reader)
	{
		KHUTILS_ASSERT_PTR(doc);

		std::vector<uint8_t> buffer;
		auto				 readOk = reader(location, buffer);

		if (readOk)
		{
			KHUTILS_ASSERT_CNTR_NOT_EMPTY(buffer);
			std::string jsonString(reinterpret_cast<const char*>(buffer.data()), buffer.size());
			initializeDocument(doc, from_json_internal(jsonString));
			return true;
		}

		return false;
	}

	//---

	bool loadDocument_glf(Document* const doc, const char* location, data_reader_t reader)
	{
		std::vector<uint8_t> buffer;
		auto				 readOk = reader(location, buffer);

		if (readOk)
		{
			KHUTILS_ASSERT_CNTR_NOT_EMPTY(buffer);
			initializeDocument(doc, from_flatbuffer_internal(buffer));
			return true;
		}

		return false;
	}

	//---

	// loadDocument_glb implemented further below

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// load document: transform data uris to buffers, load external resources
	///------------------------------------------------------------------------

	bool loadDocument_dataAndReferences(Document* const doc, const char* location, data_reader_t reader)
	{
		KHUTILS_ASSERT_PTR(doc);

		bool allBuffersLoadOk = std::all_of(doc->root->buffers.begin(), doc->root->buffers.end(), [&](auto& buf) {
			if (isDataUri(buf->uri))
			{
				setBufferData(convertUriToData(buf->uri), doc, buf.get());
				return true;
			}

			std::vector<uint8_t>bufData;
			if (reader(buf->uri.c_str(), bufData))
			{
				setBufferData(bufData, doc, buf.get());
				return true;
			}
			return false;
		});

		bool allImagesLoadOk = std::all_of(doc->root->images.begin(), doc->root->images.end(), [&](auto& img) {
			if (isValidBufferViewId(doc, img->bufferView))
				return true;

			if (isDataUri(img->uri))
			{
				setImageData(convertUriToData(img->uri), doc, img.get());
				return true;
			}

			std::vector<uint8_t>bufData;
			if (reader(img->uri.c_str(), bufData))
			{
				setImageData(bufData, doc, img.get());
				return true;
			}
			return false;
		});

		return allBuffersLoadOk && allImagesLoadOk;
	}

	//---

	// load document: transform data uris to buffers, load external resources
	bool loadDocument_json_plus(Document* const doc, const char* location, data_reader_t reader)
	{
		return loadDocument_json(doc, location, reader) &&	//
			   loadDocument_dataAndReferences(doc, location, reader);
	}

	//---

	bool loadDocument_glf_plus(Document* const doc, const char* location, data_reader_t reader)
	{
		return loadDocument_glf(doc, location, reader) &&	//
			   loadDocument_dataAndReferences(doc, location, reader);
	}

	//---

	// load document from glTF-binary: all buffers merged into 1, with external data
	bool loadDocument_glb_plus(Document* const doc, const char* location, data_reader_t reader)
	{
		return loadDocument_glb(doc, location, reader) &&	//
			   loadDocument_dataAndReferences(doc, location, reader);
	}

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// write document as-is, without modification or external data
	///------------------------------------------------------------------------

	bool saveDocument_json(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto jsonString = to_json(doc->root);
		KHUTILS_ASSERT_CNTR_NOT_EMPTY(jsonString);

		std::vector<uint8_t> buffer;
		buffer.reserve(jsonString.size());
		std::transform(jsonString.begin(), jsonString.end(), std::back_inserter(buffer), [](auto& c) {
			return static_cast<uint8_t>(c);
		});

		return writer(location, buffer);
	}

	//---

	bool saveDocument_glf(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto buffer = to_flatbuffer(doc->root);
		KHUTILS_ASSERT_CNTR_NOT_EMPTY(buffer);

		return writer(location, buffer);
	}

	//---

	// bool saveDocument_glb implemented further below

	///------------------------------------------------------------------------
	/// write document as-is, write buffers and images set to external URIs
	///------------------------------------------------------------------------

	bool saveDocument_buffers(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		return std::all_of(doc->root->buffers.begin(), doc->root->buffers.end(), [&](auto& buf) {
			if (isDataUri(buf->uri))
				return true;

			return writer(buf->uri.c_str(), getBufferData(doc, buf.get()));
		});
	}

	//---

	bool saveDocument_images(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		return std::all_of(doc->root->images.begin(), doc->root->images.end(), [&](auto& img) {
			if (isDataUri(img->uri))
				return true;

			if (isValidBufferViewId(doc, img->bufferView))
				return true;

			return writer(img->uri.c_str(), getImageData(doc, img.get()));
		});
	}

	//---

	bool saveDocument_dataAndReferences(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);
		return saveDocument_buffers(doc, location, writer) && saveDocument_images(doc, location, writer);
	}

	//---

	bool saveDocument_json_plus(const Document* const doc, const char* location, data_writer_t writer)
	{
		return saveDocument_json(doc, location, writer) &&	//
			   saveDocument_dataAndReferences(doc, location, writer);
	}

	//---

	bool saveDocument_glf_plus(const Document* const doc, const char* location, data_writer_t writer)
	{
		return saveDocument_glf(doc, location, writer) &&	//
			   saveDocument_dataAndReferences(doc, location, writer);
	}

	//---

	bool saveDocument_glb_plus(const Document* const doc, const char* location, data_writer_t writer)
	{
		return saveDocument_glb(doc, location, writer) &&	 //
			   saveDocument_images(doc, location, writer);	// only external images, buffer is already written
	}

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// write document: ALL buffers/images will be embedded base64 URIs
	///------------------------------------------------------------------------

	bool saveDocument_json_embed(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto embeddedRoot = embedDocumentBuffersAndImages(doc);
		KHUTILS_ASSERT_PTR(embeddedRoot);

		auto jsonString = to_json(embeddedRoot);
		KHUTILS_ASSERT_CNTR_NOT_EMPTY(jsonString);

		std::vector<uint8_t> buffer;
		buffer.reserve(jsonString.size());
		std::transform(jsonString.begin(), jsonString.end(), std::back_inserter(buffer), [](auto& c) {
			return static_cast<uint8_t>(c);
		});

		return writer(location, buffer);
	}

	//---

	bool saveDocument_glf_embed(const Document* const doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto embeddedRoot = embedDocumentBuffersAndImages(doc);
		KHUTILS_ASSERT_PTR(embeddedRoot);

		auto buffer = to_flatbuffer(embeddedRoot);
		KHUTILS_ASSERT_CNTR_NOT_EMPTY(buffer);

		return writer(location, buffer);
	}

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// write document: ALL buffers/images will be external files named after URI or name or counter
	///------------------------------------------------------------------------

	bool saveDocument_json_external(const Document* const _doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(_doc);
		auto doc = createDocument("copy");

		return cloneDocument(_doc, doc) &&	//
			   dislodgeDocument(doc) &&		  //
			   saveDocument_json_plus(doc, location, writer);
	}

	//---

	bool saveDocument_glf_external(const Document* const _doc, const char* location, data_writer_t writer)
	{
		KHUTILS_ASSERT_PTR(_doc);
		auto doc = createDocument("copy");

		return cloneDocument(_doc, doc) &&	//
			   dislodgeDocument(doc) &&		  //
			   saveDocument_glf_plus(doc, location, writer);
	}

	//-------------------------------------------------------------------------

	///------------------------------------------------------------------------
	/// ease-of-use load/save functions, to file by default
	///------------------------------------------------------------------------

	namespace fs = boost::filesystem;

	bool loadDocument(Document* const doc, const char* uri)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto p = fs::path(uri);
		if (p.extension() == ".glb")
		{
			return loadDocument_glb_plus(doc, uri);
		}

		if (p.extension() == ".glf")
		{
			return loadDocument_glf_plus(doc, uri);
		}

		if (p.extension() == ".gltf")
		{
			return loadDocument_json_plus(doc, uri);
		}

		return false;
	}

	//---

	bool saveDocument(const Document* const doc, const char* uri)
	{
		KHUTILS_ASSERT_PTR(doc);

		auto p = fs::path(uri);
		if (p.extension() == ".glb")
		{
			return saveDocument_glb_plus(doc, uri);
		}

		if (p.extension() == ".glf")
		{
			return saveDocument_glf_plus(doc, uri);
		}

		if (p.extension() == ".gltf")
		{
			return saveDocument_json_plus(doc, uri);
		}

		return false;
	}

	//-------------------------------------------------------------------------
	//-------------------------------------------------------------------------

}	// namespace glTF_2_0
<|endoftext|>


<commit_before>/* $Id$ */
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell

CppAD is distributed under multiple licenses. This distribution is under
the terms of the
                    Common Public License Version 1.0.

A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */

/*
$begin ode_taylor.cpp$$
$spell
	Taylor
	Cpp
	const
	std
	Adolc
	adouble
$$

$section Taylor's Ode Solver: An Example and Test$$
$index ODE, Taylor$$
$index Taylor, ODE$$
$index example, ODE$$
$index test, ODE$$

$head Purpose$$
This example solves an ordinary differential equation using Taylor's method;
i.e.,
$latex \[
	Z(t + \Delta t)
	\approx
	=
	Z^{(0)} (t) +
	\frac{ Z^{(1)} (t) }{ 1 !} \Delta t + \cdots +
	\frac{ Z^{(p)} (t) }{ p !} ( \Delta t )^p )
\] $$

$head ODE$$
The ODE is defined by the function
$latex h : \B{R}^n rightarrow \B{R}^n$$,
which for this example is given by
$latex \[
	Z^{(1)} (t) = H(Z) =
	\left( \begin{array}{c}
			1                       \\
			Z_1                     \\
			\vdots                  \\
			Z_{n-1}
	\end{array} \right)
\] $$
and the initial condition is $latex z(0) = 0$$.

$head ODE Solution$$
The solution for this example can be calculated by
starting with the first row and then using the solution
for the first row to solve the second and so on.
Doing this we obtain
$latex \[
	Z(t) =
	\left( \begin{array}{c}
		t           \\
		t^2 / 2     \\
		\vdots      \\
		t^n / n !
	\end{array} \right)
\] $$

$head Forward Mode$$
Given the Taylor coefficients for $latex k = 0 , \ldots , K$$
$latex \[
	z^{(k)} = \frac{ Z^{(k)} }{ / k !} (t)
\]$$.
we note that
$latex \[
\begin{array}{rcl}
Z^{(1)} (t)
& = &
H( z^{(0)} + z^{(1)} t + \cdots + z^{(K)} t^K ) + O( t^{K+1} )
\\
& = &
h^{(0)} + h^{(1)} t + \cdots + h^{(K)} t^K + O( t^{K+1} )
\end{array}
\] $$
where $latex h^{(k)}$$ is the $th k$$ order Taylor coefficient for
$latex H( Z(t) )$$.
Taking $th K$$ order derivatives of both sides we obtain
$latex \[
\begin{array}{rcl}
Z^{(K+1)} (t) & = & K ! h^{(K)}  \\
z^{(K+1)}     & = & h^{(K)} / K
\end{array}
\] $$
The code below uses this relationship to implement Taylor's
method for approximating the solution of an ODE.

$code
$verbatim%example/ode_taylor.cpp%0%// BEGIN C++%// END C++%1%$$
$$

$end
--------------------------------------------------------------------------
*/
// BEGIN C++

# include <cppad/cppad.hpp>

// =========================================================================
// define types for each level
namespace { // BEGIN empty namespace
	using CppAD::AD;

	CPPAD_TESTVECTOR( AD<double> ) ode(
		const CPPAD_TESTVECTOR( AD<double> )& Z )
	{	size_t n = Z.size();
		CPPAD_TESTVECTOR( AD<double> ) y(n);
		y[0] = 1;
		for(size_t k = 1; k < n; k++)
			y[k] = Z[k-1];
		return y;
	}

}

// -------------------------------------------------------------------------
// Example that uses Taylor's method to solve ordinary differential equaitons
bool ode_taylor(void)
{	// initialize the return value as true
	bool ok = true;

	// some temporary indices
	size_t i, j, k;

	// The ODE does not depend on the arugment values
	// so only tape once, also note that ode does not depend on t
	size_t n = 5;    // number of independent and dependent variables
	CPPAD_TESTVECTOR( AD<double> ) a_x(n), a_y(n);
	CppAD::Independent( a_x );
	a_y = ode(a_x);
	CppAD::ADFun<double> H(a_x, a_y);

	// initialize the solution vector at time zero
	CPPAD_TESTVECTOR( double ) z(n);
	for(j = 0; j < n; j++)
		z[j] = 0.0;

	size_t order   = n;   // order of the Taylor method
	size_t n_step  = 4;   // number of time steps
	double dt      = 0.5; // step size in time
	// Taylor coefficients of order k
	CPPAD_TESTVECTOR( double ) hk(n), zk(n);

	// loop with respect to each step of Taylor's method
	for(size_t i_step = 0; i_step < n_step; i_step++)
	{	// Use Taylor's method to take a step
		zk           = z;     // initialize z^{(k)}  for k = 0
		double dt_kp = dt;    // initialize dt^(k+1) for k = 0
		for(k = 0; k < order; k++)
		{	// evaluate k-th order Taylor coefficient of H
			hk = H.Forward(k, zk);

			for(j = 0; j < n; j++)
			{	// convert to (k+1)-Taylor coefficient for z
				zk[j] = hk[j] / double(k + 1);

				// add term for to this Taylor coefficient
				// to solution for y(t, x)
				z[j] += zk[j] * dt_kp;
			}
			// next power of t
			dt_kp *= dt;
		}
	}

	// check solution of the ODE,
	// Taylor's method should have no truncation error for this case
	double eps   = 100. * std::numeric_limits<double>::epsilon();
	double check = 1.;
	double t     = n_step * dt;
	for(i = 0; i < n; i++)
	{	check *= t / double(i + 1);
		ok &= CppAD::NearEqual(z[i], check, eps, eps);
	}

	return ok;
}

// END C++
<commit_msg>ode_taylor.cpp: minor edits of documentation.<commit_after>/* $Id$ */
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell

CppAD is distributed under multiple licenses. This distribution is under
the terms of the
                    Common Public License Version 1.0.

A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */

/*
$begin ode_taylor.cpp$$
$spell
	Taylor
	Cpp
	const
	std
	Adolc
	adouble
$$

$section Taylor's Ode Solver: An Example and Test$$
$index ODE, Taylor$$
$index Taylor, ODE$$
$index example, ODE$$
$index test, ODE$$

$head Purpose$$
This example solves an ordinary differential equation using Taylor's method;
i.e.,
$latex \[
	Z(t + \Delta t)
	\approx
	Z^{(0)} (t) +
	\frac{ Z^{(1)} (t) }{ 1 !} \Delta t + \cdots +
	\frac{ Z^{(p)} (t) }{ p !} ( \Delta t )^p )
\] $$

$head ODE$$
The ODE is defined by the function
$latex h : \B{R}^n \rightarrow \B{R}^n$$,
which for this example is given by
$latex \[
	Z^{(1)} (t) = H[ Z(t) ] =
	\left( \begin{array}{c}
			1                       \\
			Z_1 (t)                 \\
			\vdots                  \\
			Z_{n-1} (t)
	\end{array} \right)
\] $$
and the initial condition is $latex z(0) = 0$$.

$head ODE Solution$$
The solution for this example can be calculated by
starting with the first row and then using the solution
for the first row to solve the second and so on.
Doing this we obtain
$latex \[
	Z(t) =
	\left( \begin{array}{c}
		t           \\
		t^2 / 2     \\
		\vdots      \\
		t^n / n !
	\end{array} \right)
\] $$

$head Forward Mode$$
Given the Taylor coefficients for $latex k = 0 , \ldots , K$$
$latex \[
	z^{(k)} = \frac{ Z^{(k)} }{ k !} (t)
\]$$
we note that
$latex \[
\begin{array}{rcl}
Z^{(1)} (t)
& = &
H( z^{(0)} + z^{(1)} t + \cdots + z^{(K)} t^K ) + O( t^{K+1} )
\\
& = &
h^{(0)} + h^{(1)} t + \cdots + h^{(K)} t^K + O( t^{K+1} )
\end{array}
\] $$
where $latex h^{(k)}$$ is the $th k$$ order Taylor coefficient for
$latex H( Z(t) )$$.
Taking $th K$$ order derivatives of both sides we obtain
$latex \[
\begin{array}{rcl}
Z^{(K+1)} (t) & = & K ! h^{(K)}  \\
z^{(K+1)}     & = & h^{(K)} / K
\end{array}
\] $$
The code below uses this relationship to implement Taylor's
method for approximating the solution of an ODE.

$code
$verbatim%example/ode_taylor.cpp%0%// BEGIN C++%// END C++%1%$$
$$

$end
--------------------------------------------------------------------------
*/
// BEGIN C++

# include <cppad/cppad.hpp>

// =========================================================================
// define types for each level
namespace { // BEGIN empty namespace
	using CppAD::AD;

	CPPAD_TESTVECTOR( AD<double> ) ode(
		const CPPAD_TESTVECTOR( AD<double> )& Z )
	{	size_t n = Z.size();
		CPPAD_TESTVECTOR( AD<double> ) y(n);
		y[0] = 1;
		for(size_t k = 1; k < n; k++)
			y[k] = Z[k-1];
		return y;
	}

}

// -------------------------------------------------------------------------
// Example that uses Taylor's method to solve ordinary differential equaitons
bool ode_taylor(void)
{	// initialize the return value as true
	bool ok = true;

	// some temporary indices
	size_t i, j, k;

	// The ODE does not depend on the arugment values
	// so only tape once, also note that ode does not depend on t
	size_t n = 5;    // number of independent and dependent variables
	CPPAD_TESTVECTOR( AD<double> ) a_x(n), a_y(n);
	CppAD::Independent( a_x );
	a_y = ode(a_x);
	CppAD::ADFun<double> H(a_x, a_y);

	// initialize the solution vector at time zero
	CPPAD_TESTVECTOR( double ) z(n);
	for(j = 0; j < n; j++)
		z[j] = 0.0;

	size_t order   = n;   // order of the Taylor method
	size_t n_step  = 4;   // number of time steps
	double dt      = 0.5; // step size in time
	// Taylor coefficients of order k
	CPPAD_TESTVECTOR( double ) hk(n), zk(n);

	// loop with respect to each step of Taylor's method
	for(size_t i_step = 0; i_step < n_step; i_step++)
	{	// Use Taylor's method to take a step
		zk           = z;     // initialize z^{(k)}  for k = 0
		double dt_kp = dt;    // initialize dt^(k+1) for k = 0
		for(k = 0; k < order; k++)
		{	// evaluate k-th order Taylor coefficient of H
			hk = H.Forward(k, zk);

			for(j = 0; j < n; j++)
			{	// convert to (k+1)-Taylor coefficient for z
				zk[j] = hk[j] / double(k + 1);

				// add term for to this Taylor coefficient
				// to solution for y(t, x)
				z[j] += zk[j] * dt_kp;
			}
			// next power of t
			dt_kp *= dt;
		}
	}

	// check solution of the ODE,
	// Taylor's method should have no truncation error for this case
	double eps   = 100. * std::numeric_limits<double>::epsilon();
	double check = 1.;
	double t     = n_step * dt;
	for(i = 0; i < n; i++)
	{	check *= t / double(i + 1);
		ok &= CppAD::NearEqual(z[i], check, eps, eps);
	}

	return ok;
}

// END C++
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2003 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <algorithm>
#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#include "BZAdminUI.h"
#if (defined(HAVE_CURSES_H) || defined (HAVE_NCURSES_H))
#include "CursesUI.h"
#endif
#include "OptionParser.h"
#include "ServerLink.h"
#include "StdBothUI.h"
#include "StdInUI.h"
#include "StdOutUI.h"
#include "UIMap.h"

// causes persistent rebuilding to obtain build versioning
#include "version.h"

using namespace std;

// function prototypes
/** Checks for new packets from the server, ignores them or stores a
    text message in str. Tells ui about new or removed players. Returns
    false if no interesting packets have arrived. */
bool getServerString(ServerLink& sLink, string& str, BZAdminUI& ui);

/** Sends the message msg to the server. */
void sendMessage(ServerLink& sLink, const string& msg, PlayerId target);

/** Formats an incoming message. */
string formatMessage(const string& msg, PlayerId src,
		     PlayerId dst, TeamColor dstTeam, PlayerId me);

// some global variables
map<PlayerId, string> players;
TeamColor myTeam(ObserverTeam);
struct CLOptions {
  CLOptions() : ui("curses"), showHelp(false) { }
  string ui;
  bool showHelp;
} clOptions;

// Here we go.
int main(int argc, char** argv) {

  // no curses, use stdboth instead
  const UIMap::map_t& interfaces(UIMap::getInstance().getMap());
  if (interfaces.find("curses") == interfaces.end())
    clOptions.ui = "stdboth";

  // build a usage string with all interfaces
  UIMap::map_t::const_iterator uiIter;
  string uiUsage;
  for (uiIter = interfaces.begin(); uiIter != interfaces.end(); ++uiIter)
    uiUsage += uiIter->first + '|';
  uiUsage = string("[-ui ") + uiUsage.substr(0, uiUsage.size() - 1) + ']';

  // register and parse command line arguments
  OptionParser op;
  op.registerVariable("ui", clOptions.ui, uiUsage,
		      "choose a user interface");
  op.registerVariable("help", clOptions.showHelp, "[-help]",
		      "print this help message");
  if (!op.parse(argc, argv)) {
    cerr<<op.getError()<<endl;
    op.printUsage(cout, argv[0]);
    cout<<"CALLSIGN@HOST[:PORT] [COMMAND] [COMMAND] ..."<<endl;
    return 1;
  }
  if (clOptions.showHelp) {
    cout<<"bzadmin "<<getAppVersion()<<endl;
    op.printUsage(cout, argv[0]);
    cout<<"CALLSIGN@HOST[:PORT] [COMMAND] [COMMAND] ..."<<endl<<endl;
    op.printHelp(cout);
    return 0;
  }

  // check that the ui is valid
  uiIter = UIMap::getInstance().getMap().find(clOptions.ui);
  if (uiIter == UIMap::getInstance().getMap().end()) {
    cerr<<"There is no interface called \""<<clOptions.ui<<"\"."<<endl;
    return 1;
  }

  // check that we have callsign and host in the right format and extract them
  if (op.getParameters().size() == 0) {
    cerr<<"You have to specify callsign@host."<<endl;
    return 1;
  }
  const string& namehost = op.getParameters()[0];
  int atPos = namehost.find('@');
  if (atPos == -1) {
    cerr<<"You have to specify callsign@host."<<endl;
    return 1;
  }
  string name = namehost.substr(0, atPos);
  string host = namehost.substr(atPos + 1);
  int port = ServerPort;
  int cPos = host.find(':');
  if (cPos != -1) {
    port = atoi(host.substr(cPos + 1).c_str());
    host = host.substr(0, cPos);
  }

  // connect to the server
  Address a(host);
  ServerLink sLink(a, port);
  if (sLink.getState() != ServerLink::Okay) {
    cerr<<"Could not connect to "<<host<<':'<<port<<'.'<<endl;
    return 0;
  }
  sLink.sendEnter(TankPlayer, myTeam, name.c_str(), "");
  if (sLink.getState() != ServerLink::Okay) {
    cerr<<"Rejected."<<endl;
    return 0;
  }

  // if we got commands as arguments, send them and exit
  if (op.getParameters().size() > 1) {
    for (unsigned int i = 1; i < op.getParameters().size(); ++i)
      sendMessage(sLink, op.getParameters()[i], AllPlayers);
    return 0;
  }

  // choose UI
  BZAdminUI*  ui = uiIter->second(players, sLink.getId());

  // main loop
  string str;
  PlayerId me = sLink.getId();
  while (true) {
    while (getServerString(sLink, str, *ui))
      ui->outputMessage(str);
    if (ui->checkCommand(str)) {
      if (str == "/quit")
	break;
      sendMessage(sLink, str, ui->getTarget());
      // private messages to other players aren't sent back to us, print here
      if (players.count(ui->getTarget()))
	ui->outputMessage(formatMessage(str, me, ui->getTarget(), NoTeam, me));
    }
  }
  delete ui;

  return 0;
}

bool getServerString(ServerLink& sLink, string& str, BZAdminUI& ui) {
  uint16_t code, len;
  char inbuf[MaxPacketLen];
  int e;
  std::string dstName, srcName;
  str = "";

  /* read until we have a package that we want, or until there are no more
     packages for 100 ms */
  while ((e = sLink.read(code, len, inbuf, 100)) == 1) {
    void* vbuf = inbuf;
    PlayerId p;
    switch (code) {

    case MsgAddPlayer:

      vbuf = nboUnpackUByte(vbuf, p);

      uint16_t team, type, wins, losses, tks;
      char callsign[CallSignLen];
      char email[EmailLen];
      vbuf = nboUnpackUShort(vbuf, type);
      vbuf = nboUnpackUShort(vbuf, team);
      vbuf = nboUnpackUShort(vbuf, wins);
      vbuf = nboUnpackUShort(vbuf, losses);
      vbuf = nboUnpackUShort(vbuf, tks);
      vbuf = nboUnpackString(vbuf, callsign, CallSignLen);
      vbuf = nboUnpackString(vbuf, email, EmailLen);
      players[p] = callsign;
      if (p != sLink.getId())
	ui.addedPlayer(p);
      str = str + "*** '" + callsign + "' joined the game.";
      return true;

    case MsgRemovePlayer:
      vbuf = nboUnpackUByte(vbuf, p);
      str = str + "*** '" + players[p] + "' left the game.";
      ui.removingPlayer(p);
      players.erase(p);
      return true;

    case MsgMessage:

      // unpack the message header
      PlayerId src;
      PlayerId dst;
      PlayerId me = sLink.getId();
      vbuf = nboUnpackUByte(vbuf, src);
      vbuf = nboUnpackUByte(vbuf, dst);

      // is the message for me?
      TeamColor dstTeam = (dst >= 244 && dst <= 250 ?
			   TeamColor(250 - dst) : NoTeam);
      if (dst == AllPlayers || src == me || dst == me || dstTeam == myTeam) {
	str = (char*)vbuf;
	if (str == "CLIENTQUERY") {
	  sendMessage(sLink, string("bzadmin ") + getAppVersion(), src);
	  ui.outputMessage("    [Sent versioninfo per request]");
	}
	else {
	  str = formatMessage((char*)vbuf, src, dst, dstTeam, me);
	  return true;
	}
      }
    }

    if (e == -2) {
      cerr<<"Server communication error!"<<endl;
      exit(0);
    }
  }

  return false;
}

void sendMessage(ServerLink& sLink, const string& msg, PlayerId target) {
  char buffer[MessageLen];
  char buffer2[1 + MessageLen];
  void* buf = buffer2;

  buf = nboPackUByte(buf, target);
  memset(buffer, 0, MessageLen);
  strncpy(buffer, msg.c_str(), MessageLen);
  nboPackString(buffer2 + 1, buffer, MessageLen);
  sLink.send(MsgMessage, sizeof(buffer2), buffer2);
}

string formatMessage(const string& msg, PlayerId src,
		     PlayerId dst, TeamColor dstTeam, PlayerId me) {
  string formatted = "    ";

  // get sender and receiver
  const string srcName = (src == ServerPlayer ? "SERVER" :
			  (players.count(src) ? players[src] : "(UNKNOWN)"));
  const string dstName = (players.count(dst) ? players[dst] : "(UNKNOWN)");

  // direct message to or from me
  if (dst == me || players.count(dst)) {
    if (!(src == me && dst == me)) {
      formatted += "[";
      if (src == me) {
	formatted += "->";
	formatted += dstName;
      }
      else {
	formatted += srcName;
	formatted += "->";
      }
      formatted += "] ";
    }
    formatted += msg;
  }

  // public or team message
  else {
    if (dstTeam != NoTeam)
      formatted += "[Team] ";
    formatted += srcName;
    formatted += ": ";
    formatted += msg;
  }

  return formatted;
}
<commit_msg>Added primitive check to bzadmin that tries to wait until all commands have been processed by the server before it quits<commit_after>/* bzflag
 * Copyright (c) 1993 - 2003 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <algorithm>
#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#include "BZAdminUI.h"
#if (defined(HAVE_CURSES_H) || defined (HAVE_NCURSES_H))
#include "CursesUI.h"
#endif
#include "OptionParser.h"
#include "ServerLink.h"
#include "StdBothUI.h"
#include "StdInUI.h"
#include "StdOutUI.h"
#include "UIMap.h"

// causes persistent rebuilding to obtain build versioning
#include "version.h"

using namespace std;

// function prototypes
/** Checks for new packets from the server, ignores them or stores a
    text message in str. Tells ui about new or removed players. Returns
    false if no interesting packets have arrived. */
bool getServerString(ServerLink& sLink, string& str, BZAdminUI& ui);

/** Sends the message msg to the server. */
void sendMessage(ServerLink& sLink, const string& msg, PlayerId target);

/** Formats an incoming message. */
string formatMessage(const string& msg, PlayerId src,
		     PlayerId dst, TeamColor dstTeam, PlayerId me);

// some global variables
map<PlayerId, string> players;
TeamColor myTeam(ObserverTeam);
struct CLOptions {
  CLOptions() : ui("curses"), showHelp(false) { }
  string ui;
  bool showHelp;
} clOptions;

// Here we go.
int main(int argc, char** argv) {

  // no curses, use stdboth instead
  const UIMap::map_t& interfaces(UIMap::getInstance().getMap());
  if (interfaces.find("curses") == interfaces.end())
    clOptions.ui = "stdboth";

  // build a usage string with all interfaces
  UIMap::map_t::const_iterator uiIter;
  string uiUsage;
  for (uiIter = interfaces.begin(); uiIter != interfaces.end(); ++uiIter)
    uiUsage += uiIter->first + '|';
  uiUsage = string("[-ui ") + uiUsage.substr(0, uiUsage.size() - 1) + ']';

  // register and parse command line arguments
  OptionParser op;
  op.registerVariable("ui", clOptions.ui, uiUsage,
		      "choose a user interface");
  op.registerVariable("help", clOptions.showHelp, "[-help]",
		      "print this help message");
  if (!op.parse(argc, argv)) {
    cerr<<op.getError()<<endl;
    op.printUsage(cout, argv[0]);
    cout<<"CALLSIGN@HOST[:PORT] [COMMAND] [COMMAND] ..."<<endl;
    return 1;
  }
  if (clOptions.showHelp) {
    cout<<"bzadmin "<<getAppVersion()<<endl;
    op.printUsage(cout, argv[0]);
    cout<<"CALLSIGN@HOST[:PORT] [COMMAND] [COMMAND] ..."<<endl<<endl;
    op.printHelp(cout);
    return 0;
  }

  // check that the ui is valid
  uiIter = UIMap::getInstance().getMap().find(clOptions.ui);
  if (uiIter == UIMap::getInstance().getMap().end()) {
    cerr<<"There is no interface called \""<<clOptions.ui<<"\"."<<endl;
    return 1;
  }

  // check that we have callsign and host in the right format and extract them
  if (op.getParameters().size() == 0) {
    cerr<<"You have to specify callsign@host."<<endl;
    return 1;
  }
  const string& namehost = op.getParameters()[0];
  int atPos = namehost.find('@');
  if (atPos == -1) {
    cerr<<"You have to specify callsign@host."<<endl;
    return 1;
  }
  string name = namehost.substr(0, atPos);
  string host = namehost.substr(atPos + 1);
  int port = ServerPort;
  int cPos = host.find(':');
  if (cPos != -1) {
    port = atoi(host.substr(cPos + 1).c_str());
    host = host.substr(0, cPos);
  }

  // connect to the server
  Address a(host);
  ServerLink sLink(a, port);
  if (sLink.getState() != ServerLink::Okay) {
    cerr<<"Could not connect to "<<host<<':'<<port<<'.'<<endl;
    return 0;
  }
  sLink.sendEnter(TankPlayer, myTeam, name.c_str(), "");
  if (sLink.getState() != ServerLink::Okay) {
    cerr<<"Rejected."<<endl;
    return 0;
  }

  // if we got commands as arguments, send them and exit
  if (op.getParameters().size() > 1) {
    for (unsigned int i = 1; i < op.getParameters().size(); ++i)
      sendMessage(sLink, op.getParameters()[i], AllPlayers);
    return 0;
  }

  // choose UI
  BZAdminUI*  ui = uiIter->second(players, sLink.getId());

  // main loop
  string str;
  PlayerId me = sLink.getId();
  while (true) {
    while (getServerString(sLink, str, *ui))
      ui->outputMessage(str);
    if (ui->checkCommand(str)) {
      if (str == "/quit")
	break;
      sendMessage(sLink, str, ui->getTarget());
      // private messages to other players aren't sent back to us, print here
      if (players.count(ui->getTarget()))
	ui->outputMessage(formatMessage(str, me, ui->getTarget(), NoTeam, me));
    }
  }

  // we need to know that the server has processed all our messages
  // send a private message to ourself and wait for it to come back
  // this assumes that the order of messages isn't changed along the way
  sendMessage(sLink, "bzadminping", me);
  string expected = formatMessage("bzadminping", me, me, NoTeam, me);
  do {
    getServerString(sLink, str, *ui);
  } while (str != expected);
  delete ui;

  return 0;
}

bool getServerString(ServerLink& sLink, string& str, BZAdminUI& ui) {
  uint16_t code, len;
  char inbuf[MaxPacketLen];
  int e;
  std::string dstName, srcName;
  str = "";

  /* read until we have a package that we want, or until there are no more
     packages for 100 ms */
  while ((e = sLink.read(code, len, inbuf, 100)) == 1) {
    void* vbuf = inbuf;
    PlayerId p;
    switch (code) {

    case MsgAddPlayer:

      vbuf = nboUnpackUByte(vbuf, p);

      uint16_t team, type, wins, losses, tks;
      char callsign[CallSignLen];
      char email[EmailLen];
      vbuf = nboUnpackUShort(vbuf, type);
      vbuf = nboUnpackUShort(vbuf, team);
      vbuf = nboUnpackUShort(vbuf, wins);
      vbuf = nboUnpackUShort(vbuf, losses);
      vbuf = nboUnpackUShort(vbuf, tks);
      vbuf = nboUnpackString(vbuf, callsign, CallSignLen);
      vbuf = nboUnpackString(vbuf, email, EmailLen);
      players[p] = callsign;
      if (p != sLink.getId())
	ui.addedPlayer(p);
      str = str + "*** '" + callsign + "' joined the game.";
      return true;

    case MsgRemovePlayer:
      vbuf = nboUnpackUByte(vbuf, p);
      str = str + "*** '" + players[p] + "' left the game.";
      ui.removingPlayer(p);
      players.erase(p);
      return true;

    case MsgMessage:

      // unpack the message header
      PlayerId src;
      PlayerId dst;
      PlayerId me = sLink.getId();
      vbuf = nboUnpackUByte(vbuf, src);
      vbuf = nboUnpackUByte(vbuf, dst);

      // is the message for me?
      TeamColor dstTeam = (dst >= 244 && dst <= 250 ?
			   TeamColor(250 - dst) : NoTeam);
      if (dst == AllPlayers || src == me || dst == me || dstTeam == myTeam) {
	str = (char*)vbuf;
	if (str == "CLIENTQUERY") {
	  sendMessage(sLink, string("bzadmin ") + getAppVersion(), src);
	  ui.outputMessage("    [Sent versioninfo per request]");
	}
	else {
	  str = formatMessage((char*)vbuf, src, dst, dstTeam, me);
	  return true;
	}
      }
    }

    if (e == -2) {
      cerr<<"Server communication error!"<<endl;
      exit(0);
    }
  }

  return false;
}

void sendMessage(ServerLink& sLink, const string& msg, PlayerId target) {
  char buffer[MessageLen];
  char buffer2[1 + MessageLen];
  void* buf = buffer2;

  buf = nboPackUByte(buf, target);
  memset(buffer, 0, MessageLen);
  strncpy(buffer, msg.c_str(), MessageLen);
  nboPackString(buffer2 + 1, buffer, MessageLen);
  sLink.send(MsgMessage, sizeof(buffer2), buffer2);
}

string formatMessage(const string& msg, PlayerId src,
		     PlayerId dst, TeamColor dstTeam, PlayerId me) {
  string formatted = "    ";

  // get sender and receiver
  const string srcName = (src == ServerPlayer ? "SERVER" :
			  (players.count(src) ? players[src] : "(UNKNOWN)"));
  const string dstName = (players.count(dst) ? players[dst] : "(UNKNOWN)");

  // direct message to or from me
  if (dst == me || players.count(dst)) {
    if (!(src == me && dst == me)) {
      formatted += "[";
      if (src == me) {
	formatted += "->";
	formatted += dstName;
      }
      else {
	formatted += srcName;
	formatted += "->";
      }
      formatted += "] ";
    }
    formatted += msg;
  }

  // public or team message
  else {
    if (dstTeam != NoTeam)
      formatted += "[Team] ";
    formatted += srcName;
    formatted += ": ";
    formatted += msg;
  }

  return formatted;
}
<|endoftext|>


<commit_before>// @(#)root/gl:$Name:  $:$Id: TRootOIViewer.cxx,v 1.4 2001/05/14 15:25:38 fine Exp $
// Author: Valery Fine & Fons Rademakers   5/10/2000 and 28/4/2001

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootOIViewer                                                        //
//                                                                      //
// This class creates a toplevel window and an OpenInventor             //
// drawing area and context using the ROOT native GUI.                  //
//                                                                      //
// Open Inventor can be downloaded from                                 //
//  ftp://oss.sgi.com/projects/inventor/download/                       //
//                                                                      //
// Free version of OpenGL API:                                          //
//   http://sourceforge.net/project/showfiles.php?group_id=3            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <Inventor/Xt/SoXt.h>
#include <Inventor/Xt/viewers/SoXtExaminerViewer.h>
#include <Inventor/actions/SoGetBoundingBoxAction.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoCallback.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/elements/SoCacheElement.h>
#include <X11/IntrinsicP.h>

#include "TRootOIViewer.h"
#include "TGClient.h"
#include "TGCanvas.h"
#include "TGMsgBox.h"
#include "TVirtualX.h"

#include "TROOT.h"
#include "TError.h"
#include "Buttons.h"
#include "TVirtualPad.h"
#include "TPadOpenGLView.h"
#include "TView.h"
#include "TVirtualGL.h"
#include "TColor.h"
#include "TSystem.h"

XtAppContext TRootOIViewer::fgAppContext = 0;

//______________________________________________________________________________
void InventorCallback(void *d, SoAction *action)
{
   // OpenInventor call back function.

   if (!d) return;
   TRootOIViewer *currentViewer = (TRootOIViewer *)d;
   if (currentViewer) {
      if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
         SoCacheElement::invalidate(action->getState());

         // gVirtualGL->SetRootLight(kFALSE);

         glEnable(GL_COLOR_MATERIAL);
         currentViewer->Paint("");
         glDisable(GL_COLOR_MATERIAL);

      } else if (action->isOfType(SoGetBoundingBoxAction::getClassTypeId())) {
        // define the default range
         Float_t minBound[3]={-1000,-1000,-1000};
         Float_t maxBound[3]={ 1000, 1000, 1000};

         // pick the "real" range provided by TPad object
         currentViewer->GetGLView()->GetPad()->GetView()->GetRange(minBound,maxBound);
         if (minBound[0] == maxBound[0])
              SoCacheElement::invalidate(action->getState());

         ((SoGetBoundingBoxAction *)action)->
            extendBy(SbBox3f(minBound[0],minBound[1],minBound[2]
                            ,maxBound[0],maxBound[2],maxBound[2])
                   );
      }
   }
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSoXtEventHandler                                                    //
//                                                                      //
// All X events that are not for any of the windows under the control   //
// of the ROOT GUI are forwarded by this class to Xt.                   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TSoXtEventHandler : public TGUnknownWindowHandler {
private:
   TRootOIViewer  *fViewer;   // pointer back to viewer imp
public:
   TSoXtEventHandler(TRootOIViewer *c) { fViewer = c; }
   Bool_t HandleEvent(Event_t *ev)
      { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
};

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TXtTimerHandler                                                      //
//                                                                      //
// Check every 100 ms if there is an Xt timer event to be processed.    //
// This is the best we can do since there is no way to get access to    //
// the Xt timer queue.                                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TXtTimerHandler : public TTimer {
public:
   TXtTimerHandler() : TTimer(100) {  }
   Bool_t Notify();
};

Bool_t TXtTimerHandler::Notify()
{
   XtInputMask m = XtAppPending(TRootOIViewer::fgAppContext);
   if ((m & XtIMTimer))
      XtAppProcessEvent(TRootOIViewer::fgAppContext, XtIMTimer);
   Reset();
   return kTRUE;
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TOIContainer                                                         //
//                                                                      //
// Utility class used by TRootOIViewer. The TOIContainer is the frame   //
// embedded in the TGCanvas widget. The OI graphics goes into this      //
// frame. This class is used to enable input events on this graphics    //
// frame and forward the events to the TRootOIViewer handlers.          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TOIContainer : public TGCompositeFrame {
private:
   TRootOIViewer  *fViewer;    // pointer back to viewer imp
public:
   TOIContainer(TRootOIViewer *c, Window_t id, const TGWindow *parent);

   Bool_t  HandleButton(Event_t *ev)
          { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
   Bool_t  HandleConfigureNotify(Event_t *ev)
          { TGFrame::HandleConfigureNotify(ev);
            return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
   Bool_t  HandleKey(Event_t *ev)
          { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
   Bool_t  HandleMotion(Event_t *ev)
          { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
   Bool_t  HandleExpose(Event_t *ev)
          { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
};

//______________________________________________________________________________
TOIContainer::TOIContainer(TRootOIViewer *c, Window_t id, const TGWindow *p)
   : TGCompositeFrame(gClient, id, p)
{
   // Create a canvas container.

   fViewer = c;
}

//ClassImp(TRootOIViewer)

//______________________________________________________________________________
TRootOIViewer::TRootOIViewer(TPadOpenGLView *pad, const char *title, UInt_t width, UInt_t height)
   : TGMainFrame(gClient->GetRoot(), width, height)
{
   // Create a ROOT OpenInventor viewer.

   fGLView = pad;

   CreateViewer(title);

   Resize(width, height);

   SetDrawList(0);
}

//______________________________________________________________________________
TRootOIViewer::TRootOIViewer(TPadOpenGLView *pad, const char *title, Int_t x, Int_t y, UInt_t width, UInt_t height)
   : TGMainFrame(gClient->GetRoot(), width, height)
{
   // Create a ROOT OpenInventor viewer.

   fGLView = pad;

   CreateViewer(title);

   MoveResize(x, y, width, height);
   SetWMPosition(x, y);

   SetDrawList(0);
}

//______________________________________________________________________________
TRootOIViewer::~TRootOIViewer()
{
   // Delete ROOT OpenInventor viewer.

   SafeDelete(fInventorViewer);
   DeleteContext();

   fClient->RemoveUnknownWindowHandler(fSoXtHandler);
   delete fSoXtHandler;
   delete fXtTimerHandler;

   delete fCanvasContainer;
   delete fCanvasWindow;
   delete fCanvasLayout;
}

//______________________________________________________________________________
void TRootOIViewer::CreateViewer(const char *title)
{
   // Create the actual canvas.

   fInventorViewer = 0;
   fPaint          = kTRUE;
   fTopLevel       = 0;

   // Create canvas and canvas container to host the OpenInventor graphics
   fCanvasWindow = new TGCanvas(this, GetWidth()+4, GetHeight()+4,
                                kSunkenFrame | kDoubleBorder);

   InitXt();
   if (!fTopLevel) {
      fCanvasContainer = 0;
      fCanvasLayout    = 0;
      return;
   }
   fCanvasContainer = new TOIContainer(this, XtWindow(fTopLevel),
                                       fCanvasWindow->GetViewPort());
   fCanvasWindow->SetContainer(fCanvasContainer);
   fCanvasLayout = new TGLayoutHints(kLHintsExpandX | kLHintsExpandY);
   AddFrame(fCanvasWindow, fCanvasLayout);

   SoXt::init(fTopLevel);
   fRootNode = new SoSeparator;
   fRootNode->ref();

   fGLNode = new SoSeparator;

   fMaterial = new SoMaterial;
//   fMaterial->shininess = 100.;
//   fMaterial->ambientColor.setValue(0.9, 0.1, 0.0);
//   fMaterial->diffuseColor.setValue(0.5,0.2,0.5);
//   fMaterial->transparency = 0.8;

   fRootCallback = new SoCallback;
   fRootCallback->setCallback(InventorCallback, this);

   fSoXtHandler = new TSoXtEventHandler(this);
   fClient->AddUnknownWindowHandler(fSoXtHandler);
   fXtTimerHandler = new TXtTimerHandler;
   fXtTimerHandler->TurnOn();

   fGLNode->addChild(fMaterial);
   fGLNode->addChild(fRootCallback);

   fRootNode->addChild(fGLNode);

   SoInput viewDecor;
   const char *fileDecor = "root.iv";
   if (!gSystem->AccessPathName(fileDecor) && viewDecor.openFile(fileDecor)) {
     SoSeparator *extraObjects = SoDB::readAll(&viewDecor);
     if (extraObjects) {
        fRootNode->addChild(extraObjects);
     }
   }

   fInventorViewer = new SoXtExaminerViewer(fTopLevel);
   fInventorViewer->setSceneGraph(fRootNode);
   fInventorViewer->setTitle(title);
   fInventorViewer->setSize(SbVec2s((short)GetWidth(), (short)GetHeight()));

   // Pick the background color
   TVirtualPad *thisPad = fGLView->GetPad();
   if (thisPad) {
      Color_t color = thisPad->GetFillColor();
      TColor *background = gROOT->GetColor(color);
      if (background) {
          float rgb[3];
          background->GetRGB(rgb[0],rgb[1],rgb[2]);
          fInventorViewer->setBackgroundColor(SbColor(rgb));
      }
   }
   fInventorViewer->show();

   //SoXt::show(fTopLevel);

   InitGLWindow();

   // Misc

   SetWindowName(title);
   SetIconName(title);
   SetClassHints("OIViewer", "OIViewer");

   SetMWMHints(kMWMDecorAll, kMWMFuncAll, kMWMInputModeless);

   MapSubwindows();

   // we need to use GetDefaultSize() to initialize the layout algorithm...
   Resize(GetDefaultSize());

   Show();
}

//______________________________________________________________________________
void TRootOIViewer::InitXt()
{
   // Initialize Xt.

   fDpy = (Display *) gVirtualX->GetDisplay();

   if (!fgAppContext) {
      XtToolkitInitialize();
      fgAppContext = XtCreateApplicationContext();
      int argc = 0;
      XtDisplayInitialize(fgAppContext, fDpy, 0, "Inventor", 0, 0, &argc, 0);
   }

   int xval, yval;
   unsigned int wval, hval, border, depth;
   Window root, wind = (Window) fCanvasWindow->GetViewPort()->GetId();
   XGetGeometry(fDpy, wind, &root, &xval, &yval, &wval, &hval, &border, &depth);

   //fTopLevel = XtAppCreateShell(0, "Inventor", applicationShellWidgetClass,
   fTopLevel = XtAppCreateShell(0, "Inventor", topLevelShellWidgetClass,
                                fDpy, 0, 0);

   // reparent fTopLevel into the ROOT GUI hierarchy
   XtResizeWidget(fTopLevel, 100, 100, 0);
   XtSetMappedWhenManaged(fTopLevel, False);
   XtRealizeWidget(fTopLevel);
   XSync(fDpy, False);    // I want all windows to be created now
   XReparentWindow(fDpy, XtWindow(fTopLevel), wind, xval, yval);
   XtSetMappedWhenManaged(fTopLevel, True);

   Arg reqargs[20];
   Cardinal nargs = 0;
   XtSetArg(reqargs[nargs], XtNx, xval);      nargs++;
   XtSetArg(reqargs[nargs], XtNy, yval);      nargs++;
   XtSetArg(reqargs[nargs], XtNwidth, wval);  nargs++;
   XtSetArg(reqargs[nargs], XtNheight, hval); nargs++;
   //XtSetArg(reqargs[nargs], "mappedWhenManaged", False); nargs++;
   XtSetValues(fTopLevel, reqargs, nargs);

   XtRealizeWidget(fTopLevel);
}

//______________________________________________________________________________
void TRootOIViewer::InitGLWindow()
{
   // Initialize GL window.

   if (fInventorViewer) {
      gVirtualGL->SetTrueColorMode();
   }
}

//______________________________________________________________________________
void TRootOIViewer::DeleteGLWindow()
{
   // X11 specific code to delete GL window.

   // fGLWin is destroyed when parent is destroyed.
}

//______________________________________________________________________________
void TRootOIViewer::CloseWindow()
{
   // In case window is closed via WM we get here.

   delete fGLView;  // this in turn will delete this object
   fGLView = 0;
}

//______________________________________________________________________________
void TRootOIViewer::CreateContext()
{
   // Create OpenGL context.
}

//______________________________________________________________________________
void TRootOIViewer::DeleteContext()
{
   // Delete OpenGL context.
}
//______________________________________________________________________________
void TRootOIViewer::SwapBuffers()
{
   // Swap two GL buffers
}
//______________________________________________________________________________
void TRootOIViewer::Paint(Option_t *)
{
   // Paint scene.

   MakeCurrent();
   gVirtualGL->RunGLList(1+4);
}

//______________________________________________________________________________
void TRootOIViewer::MakeCurrent()
{
   // Set this GL context the current one.

   glXMakeCurrent(fInventorViewer->getDisplay(),
                  fInventorViewer->getNormalWindow(),
                  fInventorViewer->getNormalContext());
}

<commit_msg>remove unused arg warnings.<commit_after>// @(#)root/gl:$Name:  $:$Id: TRootOIViewer.cxx,v 1.2 2001/05/14 16:27:39 brun Exp $
// Author: Valery Fine & Fons Rademakers   5/10/2000 and 28/4/2001

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootOIViewer                                                        //
//                                                                      //
// This class creates a toplevel window and an OpenInventor             //
// drawing area and context using the ROOT native GUI.                  //
//                                                                      //
// Open Inventor can be downloaded from                                 //
//  ftp://oss.sgi.com/projects/inventor/download/                       //
//                                                                      //
// Free version of OpenGL API:                                          //
//   http://sourceforge.net/project/showfiles.php?group_id=3            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <Inventor/Xt/SoXt.h>
#include <Inventor/Xt/viewers/SoXtExaminerViewer.h>
#include <Inventor/actions/SoGetBoundingBoxAction.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoCallback.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/elements/SoCacheElement.h>
#include <X11/IntrinsicP.h>

#include "TRootOIViewer.h"
#include "TGClient.h"
#include "TGCanvas.h"
#include "TGMsgBox.h"
#include "TVirtualX.h"

#include "TROOT.h"
#include "TError.h"
#include "Buttons.h"
#include "TVirtualPad.h"
#include "TPadOpenGLView.h"
#include "TView.h"
#include "TVirtualGL.h"
#include "TColor.h"
#include "TSystem.h"

XtAppContext TRootOIViewer::fgAppContext = 0;

//______________________________________________________________________________
void InventorCallback(void *d, SoAction *action)
{
   // OpenInventor call back function.

   if (!d) return;
   TRootOIViewer *currentViewer = (TRootOIViewer *)d;
   if (currentViewer) {
      if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
         SoCacheElement::invalidate(action->getState());

         // gVirtualGL->SetRootLight(kFALSE);

         glEnable(GL_COLOR_MATERIAL);
         currentViewer->Paint("");
         glDisable(GL_COLOR_MATERIAL);

      } else if (action->isOfType(SoGetBoundingBoxAction::getClassTypeId())) {
        // define the default range
         Float_t minBound[3]={-1000,-1000,-1000};
         Float_t maxBound[3]={ 1000, 1000, 1000};

         // pick the "real" range provided by TPad object
         currentViewer->GetGLView()->GetPad()->GetView()->GetRange(minBound,maxBound);
         if (minBound[0] == maxBound[0])
              SoCacheElement::invalidate(action->getState());

         ((SoGetBoundingBoxAction *)action)->
            extendBy(SbBox3f(minBound[0],minBound[1],minBound[2]
                            ,maxBound[0],maxBound[2],maxBound[2])
                   );
      }
   }
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSoXtEventHandler                                                    //
//                                                                      //
// All X events that are not for any of the windows under the control   //
// of the ROOT GUI are forwarded by this class to Xt.                   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TSoXtEventHandler : public TGUnknownWindowHandler {
private:
   TRootOIViewer  *fViewer;   // pointer back to viewer imp
public:
   TSoXtEventHandler(TRootOIViewer *c) { fViewer = c; }
   Bool_t HandleEvent(Event_t *)
      { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
};

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TXtTimerHandler                                                      //
//                                                                      //
// Check every 100 ms if there is an Xt timer event to be processed.    //
// This is the best we can do since there is no way to get access to    //
// the Xt timer queue.                                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TXtTimerHandler : public TTimer {
public:
   TXtTimerHandler() : TTimer(100) {  }
   Bool_t Notify();
};

Bool_t TXtTimerHandler::Notify()
{
   XtInputMask m = XtAppPending(TRootOIViewer::fgAppContext);
   if ((m & XtIMTimer))
      XtAppProcessEvent(TRootOIViewer::fgAppContext, XtIMTimer);
   Reset();
   return kTRUE;
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TOIContainer                                                         //
//                                                                      //
// Utility class used by TRootOIViewer. The TOIContainer is the frame   //
// embedded in the TGCanvas widget. The OI graphics goes into this      //
// frame. This class is used to enable input events on this graphics    //
// frame and forward the events to the TRootOIViewer handlers.          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TOIContainer : public TGCompositeFrame {
private:
   TRootOIViewer  *fViewer;    // pointer back to viewer imp
public:
   TOIContainer(TRootOIViewer *c, Window_t id, const TGWindow *parent);

   Bool_t  HandleButton(Event_t *)
          { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
   Bool_t  HandleConfigureNotify(Event_t *ev)
          { TGFrame::HandleConfigureNotify(ev);
            return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
   Bool_t  HandleKey(Event_t *)
          { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
   Bool_t  HandleMotion(Event_t *)
          { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
   Bool_t  HandleExpose(Event_t *)
          { return SoXt::dispatchEvent((XEvent *)gVirtualX->GetNativeEvent()); }
};

//______________________________________________________________________________
TOIContainer::TOIContainer(TRootOIViewer *c, Window_t id, const TGWindow *p)
   : TGCompositeFrame(gClient, id, p)
{
   // Create a canvas container.

   fViewer = c;
}

//ClassImp(TRootOIViewer)

//______________________________________________________________________________
TRootOIViewer::TRootOIViewer(TPadOpenGLView *pad, const char *title, UInt_t width, UInt_t height)
   : TGMainFrame(gClient->GetRoot(), width, height)
{
   // Create a ROOT OpenInventor viewer.

   fGLView = pad;

   CreateViewer(title);

   Resize(width, height);

   SetDrawList(0);
}

//______________________________________________________________________________
TRootOIViewer::TRootOIViewer(TPadOpenGLView *pad, const char *title, Int_t x, Int_t y, UInt_t width, UInt_t height)
   : TGMainFrame(gClient->GetRoot(), width, height)
{
   // Create a ROOT OpenInventor viewer.

   fGLView = pad;

   CreateViewer(title);

   MoveResize(x, y, width, height);
   SetWMPosition(x, y);

   SetDrawList(0);
}

//______________________________________________________________________________
TRootOIViewer::~TRootOIViewer()
{
   // Delete ROOT OpenInventor viewer.

   SafeDelete(fInventorViewer);
   DeleteContext();

   fClient->RemoveUnknownWindowHandler(fSoXtHandler);
   delete fSoXtHandler;
   delete fXtTimerHandler;

   delete fCanvasContainer;
   delete fCanvasWindow;
   delete fCanvasLayout;
}

//______________________________________________________________________________
void TRootOIViewer::CreateViewer(const char *title)
{
   // Create the actual canvas.

   fInventorViewer = 0;
   fPaint          = kTRUE;
   fTopLevel       = 0;

   // Create canvas and canvas container to host the OpenInventor graphics
   fCanvasWindow = new TGCanvas(this, GetWidth()+4, GetHeight()+4,
                                kSunkenFrame | kDoubleBorder);

   InitXt();
   if (!fTopLevel) {
      fCanvasContainer = 0;
      fCanvasLayout    = 0;
      return;
   }
   fCanvasContainer = new TOIContainer(this, XtWindow(fTopLevel),
                                       fCanvasWindow->GetViewPort());
   fCanvasWindow->SetContainer(fCanvasContainer);
   fCanvasLayout = new TGLayoutHints(kLHintsExpandX | kLHintsExpandY);
   AddFrame(fCanvasWindow, fCanvasLayout);

   SoXt::init(fTopLevel);
   fRootNode = new SoSeparator;
   fRootNode->ref();

   fGLNode = new SoSeparator;

   fMaterial = new SoMaterial;
//   fMaterial->shininess = 100.;
//   fMaterial->ambientColor.setValue(0.9, 0.1, 0.0);
//   fMaterial->diffuseColor.setValue(0.5,0.2,0.5);
//   fMaterial->transparency = 0.8;

   fRootCallback = new SoCallback;
   fRootCallback->setCallback(InventorCallback, this);

   fSoXtHandler = new TSoXtEventHandler(this);
   fClient->AddUnknownWindowHandler(fSoXtHandler);
   fXtTimerHandler = new TXtTimerHandler;
   fXtTimerHandler->TurnOn();

   fGLNode->addChild(fMaterial);
   fGLNode->addChild(fRootCallback);

   fRootNode->addChild(fGLNode);

   SoInput viewDecor;
   const char *fileDecor = "root.iv";
   if (!gSystem->AccessPathName(fileDecor) && viewDecor.openFile(fileDecor)) {
     SoSeparator *extraObjects = SoDB::readAll(&viewDecor);
     if (extraObjects) {
        fRootNode->addChild(extraObjects);
     }
   }

   fInventorViewer = new SoXtExaminerViewer(fTopLevel);
   fInventorViewer->setSceneGraph(fRootNode);
   fInventorViewer->setTitle(title);
   fInventorViewer->setSize(SbVec2s((short)GetWidth(), (short)GetHeight()));

   // Pick the background color
   TVirtualPad *thisPad = fGLView->GetPad();
   if (thisPad) {
      Color_t color = thisPad->GetFillColor();
      TColor *background = gROOT->GetColor(color);
      if (background) {
          float rgb[3];
          background->GetRGB(rgb[0],rgb[1],rgb[2]);
          fInventorViewer->setBackgroundColor(SbColor(rgb));
      }
   }
   fInventorViewer->show();

   //SoXt::show(fTopLevel);

   InitGLWindow();

   // Misc

   SetWindowName(title);
   SetIconName(title);
   SetClassHints("OIViewer", "OIViewer");

   SetMWMHints(kMWMDecorAll, kMWMFuncAll, kMWMInputModeless);

   MapSubwindows();

   // we need to use GetDefaultSize() to initialize the layout algorithm...
   Resize(GetDefaultSize());

   Show();
}

//______________________________________________________________________________
void TRootOIViewer::InitXt()
{
   // Initialize Xt.

   fDpy = (Display *) gVirtualX->GetDisplay();

   if (!fgAppContext) {
      XtToolkitInitialize();
      fgAppContext = XtCreateApplicationContext();
      int argc = 0;
      XtDisplayInitialize(fgAppContext, fDpy, 0, "Inventor", 0, 0, &argc, 0);
   }

   int xval, yval;
   unsigned int wval, hval, border, depth;
   Window root, wind = (Window) fCanvasWindow->GetViewPort()->GetId();
   XGetGeometry(fDpy, wind, &root, &xval, &yval, &wval, &hval, &border, &depth);

   //fTopLevel = XtAppCreateShell(0, "Inventor", applicationShellWidgetClass,
   fTopLevel = XtAppCreateShell(0, "Inventor", topLevelShellWidgetClass,
                                fDpy, 0, 0);

   // reparent fTopLevel into the ROOT GUI hierarchy
   XtResizeWidget(fTopLevel, 100, 100, 0);
   XtSetMappedWhenManaged(fTopLevel, False);
   XtRealizeWidget(fTopLevel);
   XSync(fDpy, False);    // I want all windows to be created now
   XReparentWindow(fDpy, XtWindow(fTopLevel), wind, xval, yval);
   XtSetMappedWhenManaged(fTopLevel, True);

   Arg reqargs[20];
   Cardinal nargs = 0;
   XtSetArg(reqargs[nargs], XtNx, xval);      nargs++;
   XtSetArg(reqargs[nargs], XtNy, yval);      nargs++;
   XtSetArg(reqargs[nargs], XtNwidth, wval);  nargs++;
   XtSetArg(reqargs[nargs], XtNheight, hval); nargs++;
   //XtSetArg(reqargs[nargs], "mappedWhenManaged", False); nargs++;
   XtSetValues(fTopLevel, reqargs, nargs);

   XtRealizeWidget(fTopLevel);
}

//______________________________________________________________________________
void TRootOIViewer::InitGLWindow()
{
   // Initialize GL window.

   if (fInventorViewer) {
      gVirtualGL->SetTrueColorMode();
   }
}

//______________________________________________________________________________
void TRootOIViewer::DeleteGLWindow()
{
   // X11 specific code to delete GL window.

   // fGLWin is destroyed when parent is destroyed.
}

//______________________________________________________________________________
void TRootOIViewer::CloseWindow()
{
   // In case window is closed via WM we get here.

   delete fGLView;  // this in turn will delete this object
   fGLView = 0;
}

//______________________________________________________________________________
void TRootOIViewer::CreateContext()
{
   // Create OpenGL context.
}

//______________________________________________________________________________
void TRootOIViewer::DeleteContext()
{
   // Delete OpenGL context.
}
//______________________________________________________________________________
void TRootOIViewer::SwapBuffers()
{
   // Swap two GL buffers
}
//______________________________________________________________________________
void TRootOIViewer::Paint(Option_t *)
{
   // Paint scene.

   MakeCurrent();
   gVirtualGL->RunGLList(1+4);
}

//______________________________________________________________________________
void TRootOIViewer::MakeCurrent()
{
   // Set this GL context the current one.

   glXMakeCurrent(fInventorViewer->getDisplay(),
                  fInventorViewer->getNormalWindow(),
                  fInventorViewer->getNormalContext());
}

<|endoftext|>