diff --git a/pandatool/src/lwo/Sources.pp b/pandatool/src/lwo/Sources.pp new file mode 100644 index 0000000000..45da00cd77 --- /dev/null +++ b/pandatool/src/lwo/Sources.pp @@ -0,0 +1,51 @@ +#define LOCAL_LIBS pandatoolbase +#define OTHER_LIBS \ + mathutil:c linmath:c putil:c express:c panda:m dtoolconfig dtool +#define UNIX_SYS_LIBS \ + m + +#begin ss_lib_target + #define TARGET lwo + + #define SOURCES \ + config_lwo.cxx config_lwo.h iffChunk.I iffChunk.cxx iffChunk.h \ + iffGenericChunk.I iffGenericChunk.cxx iffGenericChunk.h iffId.I \ + iffId.cxx iffId.h iffInputFile.I iffInputFile.cxx iffInputFile.h \ + lwoChunk.I lwoChunk.cxx lwoChunk.h \ + lwoDiscontinuousVertexMap.I lwoDiscontinuousVertexMap.cxx lwoDiscontinuousVertexMap.h \ + lwoGroupChunk.I lwoGroupChunk.cxx lwoGroupChunk.h \ + lwoHeader.I lwoHeader.cxx \ + lwoHeader.h lwoInputFile.I lwoInputFile.cxx lwoInputFile.h \ + lwoLayer.h lwoLayer.I lwoLayer.cxx \ + lwoPoints.h lwoPoints.I lwoPoints.cxx \ + lwoPolygons.h lwoPolygons.I lwoPolygons.cxx \ + lwoPolygonTags.h lwoPolygonTags.I lwoPolygonTags.cxx \ + lwoTags.h lwoTags.I lwoTags.cxx \ + lwoVertexMap.h lwoVertexMap.I lwoVertexMap.cxx + + #define INSTALL_HEADERS \ + iffChunk.I iffChunk.h iffGenericChunk.I iffGenericChunk.h iffId.I \ + iffId.h iffInputFile.I iffInputFile.h \ + lwoChunk.I lwoChunk.h \ + lwoDiscontinuousVertexMap.I lwoDiscontinuousVertexMap.h \ + lwoGroupChunk.I lwoGroupChunk.h \ + lwoHeader.I lwoHeader.h \ + lwoInputFile.I lwoInputFile.h \ + lwoLayer.I lwoLayer.h \ + lwoPoints.I lwoPoints.h \ + lwoPolygons.I lwoPolygons.h \ + lwoPolygonTags.I lwoPolygonTags.h \ + lwoTags.I lwoTags.h \ + lwoVertexMap.I lwoVertexMap.h + +#end ss_lib_target + +#begin test_bin_target + #define TARGET test_lwo + #define LOCAL_LIBS lwo $[LOCAL_LIBS] + #define OTHER_LIBS $[OTHER_LIBS] pystub:c + + #define SOURCES \ + test_lwo.cxx + +#end test_bin_target diff --git a/pandatool/src/lwo/config_lwo.cxx b/pandatool/src/lwo/config_lwo.cxx new file mode 100644 index 0000000000..4a17d518f7 --- /dev/null +++ b/pandatool/src/lwo/config_lwo.cxx @@ -0,0 +1,42 @@ +// Filename: config_lwo.cxx +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "config_lwo.h" +#include "iffChunk.h" +#include "iffGenericChunk.h" +#include "iffInputFile.h" +#include "lwoChunk.h" +#include "lwoDiscontinuousVertexMap.h" +#include "lwoGroupChunk.h" +#include "lwoHeader.h" +#include "lwoInputFile.h" +#include "lwoLayer.h" +#include "lwoPoints.h" +#include "lwoPolygons.h" +#include "lwoPolygonTags.h" +#include "lwoTags.h" +#include "lwoVertexMap.h" + +#include + +Configure(config_lwo); + +ConfigureFn(config_lwo) { + IffChunk::init_type(); + IffGenericChunk::init_type(); + IffInputFile::init_type(); + LwoChunk::init_type(); + LwoDiscontinuousVertexMap::init_type(); + LwoGroupChunk::init_type(); + LwoHeader::init_type(); + LwoInputFile::init_type(); + LwoLayer::init_type(); + LwoPoints::init_type(); + LwoPolygons::init_type(); + LwoPolygonTags::init_type(); + LwoTags::init_type(); + LwoVertexMap::init_type(); +} + diff --git a/pandatool/src/lwo/config_lwo.h b/pandatool/src/lwo/config_lwo.h new file mode 100644 index 0000000000..3a46ababb5 --- /dev/null +++ b/pandatool/src/lwo/config_lwo.h @@ -0,0 +1,11 @@ +// Filename: config_lwo.h +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef CONFIG_LWO_H +#define CONFIG_LWO_H + +#include + +#endif diff --git a/pandatool/src/lwo/iffChunk.I b/pandatool/src/lwo/iffChunk.I new file mode 100644 index 0000000000..39ec88826e --- /dev/null +++ b/pandatool/src/lwo/iffChunk.I @@ -0,0 +1,34 @@ +// Filename: iffChunk.I +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: IffChunk::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE IffChunk:: +IffChunk() { +} + +//////////////////////////////////////////////////////////////////// +// Function: IffChunk::get_id +// Access: Public +// Description: Returns the ID associated with this chunk. +//////////////////////////////////////////////////////////////////// +INLINE IffId IffChunk:: +get_id() const { + return _id; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffChunk::set_id +// Access: Public +// Description: Changes the ID associated with this chunk. +//////////////////////////////////////////////////////////////////// +INLINE void IffChunk:: +set_id(IffId id) { + _id = id; +} diff --git a/pandatool/src/lwo/iffChunk.cxx b/pandatool/src/lwo/iffChunk.cxx new file mode 100644 index 0000000000..a330008a41 --- /dev/null +++ b/pandatool/src/lwo/iffChunk.cxx @@ -0,0 +1,43 @@ +// Filename: iffChunk.cxx +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "iffChunk.h" +#include "iffInputFile.h" + +#include + +TypeHandle IffChunk::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: IffChunk::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void IffChunk:: +output(ostream &out) const { + out << _id << " (" << get_type() << ")"; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffChunk::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void IffChunk:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) << _id << " { ... }\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffChunk::make_new_chunk +// Access: Public, Virtual +// Description: Allocates and returns a new chunk of the appropriate +// type based on the given ID, according to the context +// given by this chunk itself. +//////////////////////////////////////////////////////////////////// +IffChunk *IffChunk:: +make_new_chunk(IffInputFile *in, IffId id) { + return in->make_new_chunk(id); +} diff --git a/pandatool/src/lwo/iffChunk.h b/pandatool/src/lwo/iffChunk.h new file mode 100644 index 0000000000..600ab42f90 --- /dev/null +++ b/pandatool/src/lwo/iffChunk.h @@ -0,0 +1,67 @@ +// Filename: iffChunk.h +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef IFFCHUNK_H +#define IFFCHUNK_H + +#include + +#include "iffId.h" + +#include +#include + +class IffInputFile; + +//////////////////////////////////////////////////////////////////// +// Class : IffChunk +// Description : The basic kind of record in an EA "IFF" file, which +// the LightWave object file is based on. +//////////////////////////////////////////////////////////////////// +class IffChunk : public TypedReferenceCount { +public: + INLINE IffChunk(); + + INLINE IffId get_id() const; + INLINE void set_id(IffId id); + + virtual bool read_iff(IffInputFile *in, size_t stop_at)=0; + + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level = 0) const; + + virtual IffChunk *make_new_chunk(IffInputFile *in, IffId id); + +private: + IffId _id; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "IffChunk", + TypedReferenceCount::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "iffChunk.I" + +INLINE ostream &operator << (ostream &out, const IffChunk &chunk) { + chunk.output(out); + return out; +} + +#endif + + diff --git a/pandatool/src/lwo/iffGenericChunk.I b/pandatool/src/lwo/iffGenericChunk.I new file mode 100644 index 0000000000..ae62749669 --- /dev/null +++ b/pandatool/src/lwo/iffGenericChunk.I @@ -0,0 +1,34 @@ +// Filename: iffGenericChunk.I +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: IffGenericChunk::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE IffGenericChunk:: +IffGenericChunk() { +} + +//////////////////////////////////////////////////////////////////// +// Function: IffGenericChunk::get_data +// Access: Public +// Description: Returns the data in the chunk. +//////////////////////////////////////////////////////////////////// +INLINE const Datagram &IffGenericChunk:: +get_data() const { + return _data; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffGenericChunk::set_data +// Access: Public +// Description: Changes the data in the chunk +//////////////////////////////////////////////////////////////////// +INLINE void IffGenericChunk:: +set_data(const Datagram &data) { + _data = data; +} diff --git a/pandatool/src/lwo/iffGenericChunk.cxx b/pandatool/src/lwo/iffGenericChunk.cxx new file mode 100644 index 0000000000..ef700299a5 --- /dev/null +++ b/pandatool/src/lwo/iffGenericChunk.cxx @@ -0,0 +1,42 @@ +// Filename: iffGenericChunk.cxx +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "iffGenericChunk.h" +#include "iffInputFile.h" + +#include + +TypeHandle IffGenericChunk::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: IffGenericChunk::read_iff +// Access: Public, Virtual +// Description: Reads the data of the chunk in from the given input +// file, if possible. The ID and length of the chunk +// have already been read. stop_at is the byte position +// of the file to stop at (based on the current position +// at in->get_bytes_read()). Returns true on success, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool IffGenericChunk:: +read_iff(IffInputFile *in, size_t stop_at) { + size_t length = stop_at - in->get_bytes_read(); + bool result = in->read_bytes(_data, length); + in->align(); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffGenericChunk::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void IffGenericChunk:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << get_id() << " { " << _data.get_length() << " bytes }\n"; +} + diff --git a/pandatool/src/lwo/iffGenericChunk.h b/pandatool/src/lwo/iffGenericChunk.h new file mode 100644 index 0000000000..2bdc675981 --- /dev/null +++ b/pandatool/src/lwo/iffGenericChunk.h @@ -0,0 +1,57 @@ +// Filename: iffGenericChunk.h +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef IFFGENERICCHUNK_H +#define IFFGENERICCHUNK_H + +#include + +#include "iffChunk.h" + +#include + + +//////////////////////////////////////////////////////////////////// +// Class : IffGenericChunk +// Description : A class for a generic kind of IffChunk that is not +// understood by a particular IffReader. It remembers +// its entire contents. +//////////////////////////////////////////////////////////////////// +class IffGenericChunk : public IffChunk { +public: + INLINE IffGenericChunk(); + + INLINE const Datagram &get_data() const; + INLINE void set_data(const Datagram &data); + + virtual bool read_iff(IffInputFile *in, size_t stop_at); + virtual void write(ostream &out, int indent_level = 0) const; + +private: + Datagram _data; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + IffChunk::init_type(); + register_type(_type_handle, "IffGenericChunk", + IffChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "iffGenericChunk.I" + +#endif + + diff --git a/pandatool/src/lwo/iffId.I b/pandatool/src/lwo/iffId.I new file mode 100644 index 0000000000..92110f12ea --- /dev/null +++ b/pandatool/src/lwo/iffId.I @@ -0,0 +1,96 @@ +// Filename: iffId.I +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: IffId::Default Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE IffId:: +IffId() { + _id._c[0] = 0; + _id._c[1] = 0; + _id._c[2] = 0; + _id._c[3] = 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffId::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE IffId:: +IffId(const char id[4]) { + _id._c[0] = id[0]; + _id._c[1] = id[1]; + _id._c[2] = id[2]; + _id._c[3] = id[3]; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffId::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE IffId:: +IffId(const IffId ©) { + _id._n = copy._id._n; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffId::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void IffId:: +operator = (const IffId ©) { + _id._n = copy._id._n; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffId::Equivalence Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool IffId:: +operator == (const IffId &other) const { + return (_id._n == other._id._n); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffId::Nonequivalence Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool IffId:: +operator != (const IffId &other) const { + return (_id._n != other._id._n); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffId::Ordering Operator +// Access: Public +// Description: The ordering is arbitrary, and may not even be +// consistent between different architectures +// (e.g. big-endian and little-endian). It is useful +// mainly for putting IffId's into a sorted container, +// like sets and maps. +//////////////////////////////////////////////////////////////////// +INLINE bool IffId:: +operator < (const IffId &other) const { + return (_id._n < other._id._n); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffId::get_name +// Access: Public +// Description: Returns the four-character name of the Id, for +// outputting. +//////////////////////////////////////////////////////////////////// +INLINE string IffId:: +get_name() const { + return string(_id._c, 4); +} diff --git a/pandatool/src/lwo/iffId.cxx b/pandatool/src/lwo/iffId.cxx new file mode 100644 index 0000000000..45d6b2a3b0 --- /dev/null +++ b/pandatool/src/lwo/iffId.cxx @@ -0,0 +1,6 @@ +// Filename: iffId.cxx +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "iffId.h" diff --git a/pandatool/src/lwo/iffId.h b/pandatool/src/lwo/iffId.h new file mode 100644 index 0000000000..b578a63c95 --- /dev/null +++ b/pandatool/src/lwo/iffId.h @@ -0,0 +1,46 @@ +// Filename: iffId.h +// Created by: drose (23Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef IFFID_H +#define IFFID_H + +#include + +#include + +//////////////////////////////////////////////////////////////////// +// Class : IffId +// Description : A four-byte chunk ID appearing in an "IFF" file. +// This is used to identify the meaning of each chunk, +// and can be treated either as a concrete object or as +// a string, something like a TypeHandle. +//////////////////////////////////////////////////////////////////// +class IffId { +public: + INLINE IffId(); + INLINE IffId(const char id[4]); + INLINE IffId(const IffId ©); + INLINE void operator = (const IffId ©); + + INLINE bool operator == (const IffId &other) const; + INLINE bool operator != (const IffId &other) const; + INLINE bool operator < (const IffId &other) const; + + INLINE string get_name() const; + +private: + union { + PN_uint32 _n; + char _c[4]; + } _id; +}; + +#include "iffId.I" + +INLINE ostream &operator << (ostream &out, const IffId &id) { + return out << id.get_name(); +} + +#endif diff --git a/pandatool/src/lwo/iffInputFile.I b/pandatool/src/lwo/iffInputFile.I new file mode 100644 index 0000000000..75d2cde004 --- /dev/null +++ b/pandatool/src/lwo/iffInputFile.I @@ -0,0 +1,63 @@ +// Filename: iffInputFile.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::set_filename +// Access: Public +// Description: Indicates the filename that the InputFile is +// currently opened on. +//////////////////////////////////////////////////////////////////// +INLINE void IffInputFile:: +set_filename(const Filename &filename) { + _filename = filename; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_filename +// Access: Public +// Description: Returns the filename that the InputFile is +// currently opened on, if available. +//////////////////////////////////////////////////////////////////// +INLINE const Filename &IffInputFile:: +get_filename() const { + return _filename; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::is_eof +// Access: Public +// Description: Returns true if the last read operation failed +// because of reaching EOF, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool IffInputFile:: +is_eof() const { + return _eof; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_bytes_read +// Access: Public +// Description: Returns the number of bytes read so far from the +// input file. +//////////////////////////////////////////////////////////////////// +INLINE size_t IffInputFile:: +get_bytes_read() const { + return _bytes_read; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::align +// Access: Public +// Description: If the current file pointer is not positioned on an +// even-byte boundary, reads and discards one byte so +// that it is. +//////////////////////////////////////////////////////////////////// +INLINE void IffInputFile:: +align() { + if ((_bytes_read & 1) != 0) { + get_int8(); + } +} diff --git a/pandatool/src/lwo/iffInputFile.cxx b/pandatool/src/lwo/iffInputFile.cxx new file mode 100644 index 0000000000..36dde7e246 --- /dev/null +++ b/pandatool/src/lwo/iffInputFile.cxx @@ -0,0 +1,374 @@ +// Filename: iffInputFile.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "iffInputFile.h" +#include "iffGenericChunk.h" + +#include +#include + +TypeHandle IffInputFile::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +IffInputFile:: +IffInputFile() { + _input = (istream *)NULL; + _owns_istream = false; + _eof = true; + _bytes_read = 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +IffInputFile:: +~IffInputFile() { + if (_owns_istream) { + delete _input; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::open_read +// Access: Public +// Description: Attempts to open the indicated filename for reading. +// Returns true if successful, false otherwise. +//////////////////////////////////////////////////////////////////// +bool IffInputFile:: +open_read(Filename filename) { + filename.set_binary(); + ifstream *in = new ifstream; + if (filename.open_read(*in)) { + set_input(in, true); + set_filename(filename); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::set_input +// Access: Public +// Description: Sets up the input to use an arbitrary istream. If +// owns_istream is true, the istream will be deleted +// when the IffInputFile destructs. +//////////////////////////////////////////////////////////////////// +void IffInputFile:: +set_input(istream *input, bool owns_istream) { + if (_owns_istream) { + delete _input; + } + _input = input; + _owns_istream = owns_istream; + _eof = false; + _bytes_read = 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_int8 +// Access: Public +// Description: Extracts a signed 8-bit integer. +//////////////////////////////////////////////////////////////////// +PN_int8 IffInputFile:: +get_int8() { + Datagram dg; + if (!read_bytes(dg, 1)) { + return 0; + } + DatagramIterator dgi(dg); + return dgi.get_int8(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_uint8 +// Access: Public +// Description: Extracts an unsigned 8-bit integer. +//////////////////////////////////////////////////////////////////// +PN_uint8 IffInputFile:: +get_uint8() { + Datagram dg; + if (!read_bytes(dg, 1)) { + return 0; + } + DatagramIterator dgi(dg); + return dgi.get_int8(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_be_int16 +// Access: Public +// Description: Extracts a signed 16-bit big-endian integer. +//////////////////////////////////////////////////////////////////// +PN_int16 IffInputFile:: +get_be_int16() { + Datagram dg; + if (!read_bytes(dg, 2)) { + return 0; + } + DatagramIterator dgi(dg); + return dgi.get_be_int16(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_be_int32 +// Access: Public +// Description: Extracts a signed 32-bit big-endian integer. +//////////////////////////////////////////////////////////////////// +PN_int32 IffInputFile:: +get_be_int32() { + Datagram dg; + if (!read_bytes(dg, 4)) { + return 0; + } + DatagramIterator dgi(dg); + return dgi.get_be_int32(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_be_uint16 +// Access: Public +// Description: Extracts an unsigned 16-bit big-endian integer. +//////////////////////////////////////////////////////////////////// +PN_uint16 IffInputFile:: +get_be_uint16() { + Datagram dg; + if (!read_bytes(dg, 2)) { + return 0; + } + DatagramIterator dgi(dg); + return dgi.get_be_uint16(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_be_uint32 +// Access: Public +// Description: Extracts an unsigned 32-bit big-endian integer. +//////////////////////////////////////////////////////////////////// +PN_uint32 IffInputFile:: +get_be_uint32() { + Datagram dg; + if (!read_bytes(dg, 4)) { + return 0; + } + DatagramIterator dgi(dg); + return dgi.get_be_uint32(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_be_float32 +// Access: Public +// Description: Extracts a 32-bit big-endian single-precision +// floating-point number. +//////////////////////////////////////////////////////////////////// +float IffInputFile:: +get_be_float32() { + Datagram dg; + if (!read_bytes(dg, 4)) { + return 0; + } + DatagramIterator dgi(dg); + return dgi.get_be_float32(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_string +// Access: Public +// Description: Extracts a null-terminated string. +//////////////////////////////////////////////////////////////////// +string IffInputFile:: +get_string() { + string result; + char byte; + while (read_byte(byte)) { + if (byte == 0) { + break; + } + result += byte; + } + + align(); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_id +// Access: Public +// Description: Extracts a 4-character IFF ID. +//////////////////////////////////////////////////////////////////// +IffId IffInputFile:: +get_id() { + Datagram dg; + if (!read_bytes(dg, 4)) { + return IffId(); + } + const char *id = (const char *)dg.get_data(); + return IffId(id); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_chunk +// Access: Public +// Description: Reads a single IffChunk, determining its type based +// on its ID. Allocates and returns a new IffChunk +// object of the appropriate type. Returns NULL if EOF +// is reached before the chunk can be read completely, +// or if there is some other error in reading the chunk. +//////////////////////////////////////////////////////////////////// +PT(IffChunk) IffInputFile:: +get_chunk() { + IffId id = get_id(); + PN_uint32 length = get_be_uint32(); + + if (!is_eof()) { + PT(IffChunk) chunk = make_new_chunk(id); + chunk->set_id(id); + + size_t start_point = get_bytes_read(); + size_t end_point = start_point + length; + + if (chunk->read_iff(this, end_point)) { + size_t num_bytes_read = get_bytes_read() - start_point; + if (num_bytes_read > length) { + nout << *chunk << " read " << num_bytes_read + << " instead of " << length << " bytes.\n"; + return (IffChunk *)NULL; + + } else if (num_bytes_read < length) { + size_t skip_count = length - num_bytes_read; + nout << "Ignoring " << skip_count << " bytes at the end of " + << *chunk << "\n"; + skip_bytes(skip_count); + } + return chunk; + } + } + + return (IffChunk *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::get_sub_chunk +// Access: Public +// Description: Similar to get_chunk(), except the chunk size is only +// a 16-bit number instead of 32-bit, and it takes a +// context, which is the chunk in which this chunk is +// encountered. The parent chunk may (or may not) +// decide what kind of chunk is meant by the various +// id's encountered. +//////////////////////////////////////////////////////////////////// +PT(IffChunk) IffInputFile:: +get_sub_chunk(IffChunk *context) { + IffId id = get_id(); + PN_uint16 length = get_be_uint16(); + + if (!is_eof()) { + PT(IffChunk) chunk = context->make_new_chunk(this, id); + chunk->set_id(id); + + size_t start_point = get_bytes_read(); + size_t end_point = start_point + length; + + if (chunk->read_iff(this, end_point)) { + size_t num_bytes_read = get_bytes_read() - start_point; + if (num_bytes_read > length) { + nout << *chunk << " read " << num_bytes_read + << " instead of " << length << " bytes.\n"; + return (IffChunk *)NULL; + + } else if (num_bytes_read < length) { + size_t skip_count = length - num_bytes_read; + nout << "Ignoring " << skip_count << " bytes at the end of " + << *chunk << "\n"; + skip_bytes(skip_count); + } + return chunk; + } + } + + return (IffChunk *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::read_byte +// Access: Public +// Description: Reads a single byte. Returns true if successful, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool IffInputFile:: +read_byte(char &byte) { + if (is_eof()) { + return false; + } + + _input->get(byte); + _bytes_read++; + _eof = _input->eof() || _input->fail(); + return !is_eof(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::read_bytes +// Access: Public +// Description: Reads a series of bytes, and stores them in the +// indicated Datagram. Returns true if successful, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool IffInputFile:: +read_bytes(Datagram &datagram, size_t length) { + if (is_eof()) { + return false; + } + + char *buffer = new char[length]; + _input->read(buffer, length); + _eof = (_input->gcount() != length); + if (is_eof()) { + return false; + } + + _bytes_read += length; + datagram = Datagram(buffer, length); + delete[] buffer; + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::skip_bytes +// Access: Public +// Description: Reads a series of bytes, but does not store them. +// Returns true if successful, false otherwise. +//////////////////////////////////////////////////////////////////// +bool IffInputFile:: +skip_bytes(size_t length) { + if (is_eof()) { + return false; + } + + char byte; + while (length > 0 && !is_eof()) { + read_byte(byte); + length--; + } + + return !is_eof(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IffInputFile::make_new_chunk +// Access: Protected, Virtual +// Description: Allocates and returns a new chunk of the appropriate +// type based on the given ID. +//////////////////////////////////////////////////////////////////// +IffChunk *IffInputFile:: +make_new_chunk(IffId) { + return new IffGenericChunk; +} diff --git a/pandatool/src/lwo/iffInputFile.h b/pandatool/src/lwo/iffInputFile.h new file mode 100644 index 0000000000..3583ef7037 --- /dev/null +++ b/pandatool/src/lwo/iffInputFile.h @@ -0,0 +1,93 @@ +// Filename: iffInputFile.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef IFFINPUTFILE_H +#define IFFINPUTFILE_H + +#include + +#include "iffId.h" +#include "iffChunk.h" + +#include +#include + +class Datagram; + +//////////////////////////////////////////////////////////////////// +// Class : IffInputFile +// Description : A wrapper around an istream used for reading an IFF +// file. +//////////////////////////////////////////////////////////////////// +class IffInputFile : public TypedObject { +public: + IffInputFile(); + virtual ~IffInputFile(); + + bool open_read(Filename filename); + void set_input(istream *input, bool owns_istream); + + INLINE void set_filename(const Filename &filename); + INLINE const Filename &get_filename() const; + + INLINE bool is_eof() const; + INLINE size_t get_bytes_read() const; + + INLINE void align(); + + PN_int8 get_int8(); + PN_uint8 get_uint8(); + + PN_int16 get_be_int16(); + PN_int32 get_be_int32(); + PN_uint16 get_be_uint16(); + PN_uint32 get_be_uint32(); + float get_be_float32(); + + string get_string(); + + IffId get_id(); + + PT(IffChunk) get_chunk(); + PT(IffChunk) get_sub_chunk(IffChunk *context); + + bool read_byte(char &byte); + bool read_bytes(Datagram &datagram, size_t length); + bool skip_bytes(size_t length); + +protected: + virtual IffChunk *make_new_chunk(IffId id); + + istream *_input; + Filename _filename; + bool _owns_istream; + bool _eof; + size_t _bytes_read; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedObject::init_type(); + register_type(_type_handle, "IffInputFile", + TypedObject::get_class_type()); + } + +private: + static TypeHandle _type_handle; + + friend IffChunk; +}; + +#include "iffInputFile.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoChunk.I b/pandatool/src/lwo/lwoChunk.I new file mode 100644 index 0000000000..423029f5ea --- /dev/null +++ b/pandatool/src/lwo/lwoChunk.I @@ -0,0 +1,4 @@ +// Filename: lwoChunk.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoChunk.cxx b/pandatool/src/lwo/lwoChunk.cxx new file mode 100644 index 0000000000..751bae7764 --- /dev/null +++ b/pandatool/src/lwo/lwoChunk.cxx @@ -0,0 +1,8 @@ +// Filename: lwoChunk.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoChunk.h" + +TypeHandle LwoChunk::_type_handle; diff --git a/pandatool/src/lwo/lwoChunk.h b/pandatool/src/lwo/lwoChunk.h new file mode 100644 index 0000000000..4b001b70d3 --- /dev/null +++ b/pandatool/src/lwo/lwoChunk.h @@ -0,0 +1,46 @@ +// Filename: lwoChunk.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOCHUNK_H +#define LWOCHUNK_H + +#include + +#include "iffChunk.h" + +//////////////////////////////////////////////////////////////////// +// Class : LwoChunk +// Description : A specialization of IffChunk for Lightwave Object +// files. Each kind of chunk that is specific to a +// Lightwave file should inherit directly or indirectly +// from LwoChunk. +//////////////////////////////////////////////////////////////////// +class LwoChunk : public IffChunk { +public: + // No particular interface here. + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + IffChunk::init_type(); + register_type(_type_handle, "LwoChunk", + IffChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoChunk.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoDiscontinuousVertexMap.I b/pandatool/src/lwo/lwoDiscontinuousVertexMap.I new file mode 100644 index 0000000000..8c27fe919d --- /dev/null +++ b/pandatool/src/lwo/lwoDiscontinuousVertexMap.I @@ -0,0 +1,4 @@ +// Filename: lwoDiscontinuousVertexMap.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoDiscontinuousVertexMap.cxx b/pandatool/src/lwo/lwoDiscontinuousVertexMap.cxx new file mode 100644 index 0000000000..dc21523174 --- /dev/null +++ b/pandatool/src/lwo/lwoDiscontinuousVertexMap.cxx @@ -0,0 +1,104 @@ +// Filename: lwoDiscontinuousVertexMap.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoDiscontinuousVertexMap.h" +#include "lwoInputFile.h" + +#include + +TypeHandle LwoDiscontinuousVertexMap::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: LwoDiscontinuousVertexMap::has_value +// Access: Public +// Description: Returns true if the map has a value associated with +// the given index, false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoDiscontinuousVertexMap:: +has_value(int polygon_index, int vertex_index) const { + VMad::const_iterator di; + di = _vmad.find(polygon_index); + if (di != _vmad.end()) { + const VMap &vmap = (*di).second; + return (vmap.count(vertex_index) != 0); + } + + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoDiscontinuousVertexMap::get_value +// Access: Public +// Description: Returns the mapping value associated with the given +// index, or an empty PTA_float if there is no mapping +// value associated. +//////////////////////////////////////////////////////////////////// +PTA_float LwoDiscontinuousVertexMap:: +get_value(int polygon_index, int vertex_index) const { + VMad::const_iterator di; + di = _vmad.find(polygon_index); + if (di != _vmad.end()) { + const VMap &vmap = (*di).second; + VMap::const_iterator vi; + vi = vmap.find(vertex_index); + if (vi != vmap.end()) { + return (*vi).second; + } + } + + return PTA_float(); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoDiscontinuousVertexMap::read_iff +// Access: Public, Virtual +// Description: Reads the data of the chunk in from the given input +// file, if possible. The ID and length of the chunk +// have already been read. stop_at is the byte position +// of the file to stop at (based on the current position +// at in->get_bytes_read()). Returns true on success, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoDiscontinuousVertexMap:: +read_iff(IffInputFile *in, size_t stop_at) { + LwoInputFile *lin = DCAST(LwoInputFile, in); + + _map_type = lin->get_id(); + _dimension = lin->get_be_uint16(); + _name = lin->get_string(); + + while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { + int vertex_index = lin->get_vx(); + int polygon_index = lin->get_vx(); + + PTA_float value; + for (int i = 0; i < _dimension; i++) { + value.push_back(lin->get_be_float32()); + } + + bool inserted = _vmad[polygon_index].insert(VMap::value_type(vertex_index, value)).second; + if (!inserted) { + nout << "Duplicate pair " << polygon_index << ", " << vertex_index + << " in map.\n"; + } + } + + return (lin->get_bytes_read() == stop_at); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoDiscontinuousVertexMap::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LwoDiscontinuousVertexMap:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << get_id() << " { map_type = " << _map_type + << ", dimension = " << _dimension + << ", name = \"" << _name << "\", " + << _vmad.size() << " polygons }\n"; +} diff --git a/pandatool/src/lwo/lwoDiscontinuousVertexMap.h b/pandatool/src/lwo/lwoDiscontinuousVertexMap.h new file mode 100644 index 0000000000..3fc9f74ceb --- /dev/null +++ b/pandatool/src/lwo/lwoDiscontinuousVertexMap.h @@ -0,0 +1,61 @@ +// Filename: lwoDiscontinuousVertexMap.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWODISCONTINUOUSVERTEXMAP_H +#define LWODISCONTINUOUSVERTEXMAP_H + +#include + +#include "lwoChunk.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Class : LwoDiscontinuousVertexMap +// Description : A mapping of floating-point values per integer index. +// The meaning of these values is determined by the +// mapping type code and/or its name. +//////////////////////////////////////////////////////////////////// +class LwoDiscontinuousVertexMap : public LwoChunk { +public: + bool has_value(int polygon_index, int vertex_index) const; + PTA_float get_value(int polygon_index, int vertex_index) const; + + IffId _map_type; + int _dimension; + string _name; + +public: + virtual bool read_iff(IffInputFile *in, size_t stop_at); + virtual void write(ostream &out, int indent_level = 0) const; + +private: + typedef map VMap; + typedef map VMad; + VMad _vmad; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LwoChunk::init_type(); + register_type(_type_handle, "LwoDiscontinuousVertexMap", + LwoChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoDiscontinuousVertexMap.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoGroupChunk.I b/pandatool/src/lwo/lwoGroupChunk.I new file mode 100644 index 0000000000..4086a06a0b --- /dev/null +++ b/pandatool/src/lwo/lwoGroupChunk.I @@ -0,0 +1,4 @@ +// Filename: lwoGroupChunk.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoGroupChunk.cxx b/pandatool/src/lwo/lwoGroupChunk.cxx new file mode 100644 index 0000000000..01be93b805 --- /dev/null +++ b/pandatool/src/lwo/lwoGroupChunk.cxx @@ -0,0 +1,68 @@ +// Filename: lwoGroupChunk.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoGroupChunk.h" +#include "lwoInputFile.h" + +#include + +TypeHandle LwoGroupChunk::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: LwoGroupChunk::get_num_children +// Access: Public +// Description: Returns the number of child chunks of this group. +//////////////////////////////////////////////////////////////////// +int LwoGroupChunk:: +get_num_children() const { + return _children.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoGroupChunk::get_child +// Access: Public +// Description: Returns the nth child chunk of this group. +//////////////////////////////////////////////////////////////////// +IffChunk *LwoGroupChunk:: +get_child(int n) const { + nassertr(n >= 0 && n < (int)_children.size(), (IffChunk *)NULL); + return _children[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoGroupChunk::read_children_iff +// Access: Public +// Description: Reads a sequence of child chunks, until byte stop_at +// has been been reached, and stores them as the +// children. Returns true if successful (and exactly +// the correct number of bytes were read), or false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoGroupChunk:: +read_children_iff(IffInputFile *in, size_t stop_at) { + while (in->get_bytes_read() < stop_at && !in->is_eof()) { + PT(IffChunk) chunk = in->get_chunk(); + if (chunk == (IffChunk *)NULL) { + return false; + } + _children.push_back(chunk); + } + + return (in->get_bytes_read() == stop_at); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoGroupChunk::write_children +// Access: Public +// Description: Formats the list of children for output to the user +// (primarily for debugging), one per line. +//////////////////////////////////////////////////////////////////// +void LwoGroupChunk:: +write_children(ostream &out, int indent_level) const { + Children::const_iterator ci; + for (ci = _children.begin(); ci != _children.end(); ++ci) { + (*ci)->write(out, indent_level); + } +} diff --git a/pandatool/src/lwo/lwoGroupChunk.h b/pandatool/src/lwo/lwoGroupChunk.h new file mode 100644 index 0000000000..751cd76631 --- /dev/null +++ b/pandatool/src/lwo/lwoGroupChunk.h @@ -0,0 +1,57 @@ +// Filename: lwoGroupChunk.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOGROUPCHUNK_H +#define LWOGROUPCHUNK_H + +#include + +#include "lwoChunk.h" +#include "iffChunk.h" + +#include + +#include + +//////////////////////////////////////////////////////////////////// +// Class : LwoGroupChunk +// Description : A particular kind of LwoChunk that is expected to +// contain an arbitrary number of child chunks. +//////////////////////////////////////////////////////////////////// +class LwoGroupChunk : public LwoChunk { +public: + int get_num_children() const; + IffChunk *get_child(int n) const; + +protected: + bool read_children_iff(IffInputFile *in, size_t stop_at); + void write_children(ostream &out, int indent_level) const; + + typedef vector< PT(IffChunk) > Children; + Children _children; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LwoChunk::init_type(); + register_type(_type_handle, "LwoGroupChunk", + LwoChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoGroupChunk.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoHeader.I b/pandatool/src/lwo/lwoHeader.I new file mode 100644 index 0000000000..00049390ba --- /dev/null +++ b/pandatool/src/lwo/lwoHeader.I @@ -0,0 +1,16 @@ +// Filename: lwoHeader.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: LwoHeader::get_lwid +// Access: Public +// Description: Returns the Lightwave ID of the file. This is the +// first ID read within the header, and indicates the +// version of the Lightwave file in some mysterious way. +//////////////////////////////////////////////////////////////////// +IffId LwoHeader:: +get_lwid() const { + return _lwid; +} diff --git a/pandatool/src/lwo/lwoHeader.cxx b/pandatool/src/lwo/lwoHeader.cxx new file mode 100644 index 0000000000..a9e4bed6b7 --- /dev/null +++ b/pandatool/src/lwo/lwoHeader.cxx @@ -0,0 +1,43 @@ +// Filename: lwoHeader.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoHeader.h" +#include "iffInputFile.h" + +#include + +TypeHandle LwoHeader::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: LwoHeader::read_iff +// Access: Public, Virtual +// Description: Reads the data of the chunk in from the given input +// file, if possible. The ID and length of the chunk +// have already been read. stop_at is the byte position +// of the file to stop at (based on the current position +// at in->get_bytes_read()). Returns true on success, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoHeader:: +read_iff(IffInputFile *in, size_t stop_at) { + _lwid = in->get_id(); + return read_children_iff(in, stop_at); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoHeader::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LwoHeader:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << get_id() << " {\n"; + indent(out, indent_level + 2) + << _lwid << "\n"; + write_children(out, indent_level + 2); + indent(out, indent_level) + << "}\n"; +} diff --git a/pandatool/src/lwo/lwoHeader.h b/pandatool/src/lwo/lwoHeader.h new file mode 100644 index 0000000000..7c2a2041a6 --- /dev/null +++ b/pandatool/src/lwo/lwoHeader.h @@ -0,0 +1,50 @@ +// Filename: lwoHeader.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOHEADER_H +#define LWOHEADER_H + +#include + +#include "lwoGroupChunk.h" + +//////////////////////////////////////////////////////////////////// +// Class : LwoHeader +// Description : The first chunk in a Lightwave Object file. +//////////////////////////////////////////////////////////////////// +class LwoHeader : public LwoGroupChunk { +public: + INLINE IffId get_lwid() const; + +public: + virtual bool read_iff(IffInputFile *in, size_t stop_at); + virtual void write(ostream &out, int indent_level = 0) const; + +private: + IffId _lwid; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LwoGroupChunk::init_type(); + register_type(_type_handle, "LwoHeader", + LwoGroupChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoHeader.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoInputFile.I b/pandatool/src/lwo/lwoInputFile.I new file mode 100644 index 0000000000..093ff73a3a --- /dev/null +++ b/pandatool/src/lwo/lwoInputFile.I @@ -0,0 +1,4 @@ +// Filename: lwoInputFile.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoInputFile.cxx b/pandatool/src/lwo/lwoInputFile.cxx new file mode 100644 index 0000000000..2f5f880946 --- /dev/null +++ b/pandatool/src/lwo/lwoInputFile.cxx @@ -0,0 +1,129 @@ +// Filename: lwoInputFile.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoInputFile.h" +#include "lwoDiscontinuousVertexMap.h" +#include "lwoHeader.h" +#include "lwoLayer.h" +#include "lwoPoints.h" +#include "lwoPolygons.h" +#include "lwoPolygonTags.h" +#include "lwoVertexMap.h" +#include "lwoTags.h" + +TypeHandle LwoInputFile::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: LwoInputFile::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +LwoInputFile:: +LwoInputFile() { +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoInputFile::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +LwoInputFile:: +~LwoInputFile() { +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoInputFile::get_vx +// Access: Public +// Description: Reads a Lightwave variable-length index. This is +// either a 2-byte or 4-byte integer. +//////////////////////////////////////////////////////////////////// +int LwoInputFile:: +get_vx() { + PN_uint16 top = get_be_uint16(); + if ((top & 0xff00) == 0xff00) { + // The first byte is 0xff, which indicates we have a 4-byte + // integer. + PN_uint16 bottom = get_be_uint16(); + return ((int)(top & 0xff) << 16) | bottom; + } + + // The first byte is not 0xff, which indicates we have a 2-byte + // integer. + return top; +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoInputFile::get_vec3 +// Access: Public +// Description: Reads a three-component vector of floats. +//////////////////////////////////////////////////////////////////// +LVecBase3f LwoInputFile:: +get_vec3() { + LVecBase3f result; + result[0] = get_be_float32(); + result[1] = get_be_float32(); + result[2] = get_be_float32(); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoInputFile::get_filename +// Access: Public +// Description: Reads a Lightwave platform-neutral filename and +// converts it to a Panda platform-neutral filename. +//////////////////////////////////////////////////////////////////// +Filename LwoInputFile:: +get_filename() { + string name = get_string(); + size_t colon = name.find(':'); + if (colon == string::npos) { + // No colon; it's just a relative path. + return Filename(name); + } + + // The colon separates the device and the path. + string device = name.substr(0, colon); + string path = name.substr(colon + 1); + + nout << "Ignoring filename device " << device << "\n"; + return Filename("/", path); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoInputFile::make_new_chunk +// Access: Protected, Virtual +// Description: Allocates and returns a new chunk of the appropriate +// type based on the given ID. +//////////////////////////////////////////////////////////////////// +IffChunk *LwoInputFile:: +make_new_chunk(IffId id) { + if (id == IffId("FORM")) { + return new LwoHeader; + + } else if (id == IffId("LAYR")) { + return new LwoLayer; + + } else if (id == IffId("PNTS")) { + return new LwoPoints; + + } else if (id == IffId("VMAP")) { + return new LwoVertexMap; + + } else if (id == IffId("VMAD")) { + return new LwoDiscontinuousVertexMap; + + } else if (id == IffId("POLS")) { + return new LwoPolygons; + + } else if (id == IffId("TAGS")) { + return new LwoTags; + + } else if (id == IffId("PTAG")) { + return new LwoPolygonTags; + + } else { + return IffInputFile::make_new_chunk(id); + } +} diff --git a/pandatool/src/lwo/lwoInputFile.h b/pandatool/src/lwo/lwoInputFile.h new file mode 100644 index 0000000000..4a71088c80 --- /dev/null +++ b/pandatool/src/lwo/lwoInputFile.h @@ -0,0 +1,54 @@ +// Filename: lwoInputFile.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOINPUTFILE_H +#define LWOINPUTFILE_H + +#include + +#include "iffInputFile.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Class : LwoInputFile +// Description : A specialization of IffInputFile to handle reading a +// Lightwave Object file. +//////////////////////////////////////////////////////////////////// +class LwoInputFile : public IffInputFile { +public: + LwoInputFile(); + ~LwoInputFile(); + + int get_vx(); + LVecBase3f get_vec3(); + Filename get_filename(); + +protected: + virtual IffChunk *make_new_chunk(IffId id); + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + IffInputFile::init_type(); + register_type(_type_handle, "LwoInputFile", + IffInputFile::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoInputFile.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoLayer.I b/pandatool/src/lwo/lwoLayer.I new file mode 100644 index 0000000000..876e46a87b --- /dev/null +++ b/pandatool/src/lwo/lwoLayer.I @@ -0,0 +1,4 @@ +// Filename: lwoLayer.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoLayer.cxx b/pandatool/src/lwo/lwoLayer.cxx new file mode 100644 index 0000000000..2e729e8e65 --- /dev/null +++ b/pandatool/src/lwo/lwoLayer.cxx @@ -0,0 +1,54 @@ +// Filename: lwoLayer.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoLayer.h" +#include "lwoInputFile.h" + +#include + +TypeHandle LwoLayer::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: LwoLayer::read_iff +// Access: Public, Virtual +// Description: Reads the data of the chunk in from the given input +// file, if possible. The ID and length of the chunk +// have already been read. stop_at is the byte position +// of the file to stop at (based on the current position +// at in->get_bytes_read()). Returns true on success, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoLayer:: +read_iff(IffInputFile *in, size_t stop_at) { + LwoInputFile *lin = DCAST(LwoInputFile, in); + _number = lin->get_be_uint16(); + _flags = lin->get_be_uint16(); + _pivot = lin->get_vec3(); + _name = lin->get_string(); + + if (lin->get_bytes_read() >= stop_at) { + _parent = -1; + } else { + _parent = lin->get_be_uint16(); + if (_parent == 0xffff) { + _parent = -1; + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoLayer::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LwoLayer:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << get_id() << " { number = " << _number << ", flags = 0x" + << hex << _flags << dec << ", pivot = " << _pivot + << ", _name = \"" << _name << "\", _parent = " << _parent << " }\n"; +} diff --git a/pandatool/src/lwo/lwoLayer.h b/pandatool/src/lwo/lwoLayer.h new file mode 100644 index 0000000000..1f14f7d142 --- /dev/null +++ b/pandatool/src/lwo/lwoLayer.h @@ -0,0 +1,61 @@ +// Filename: lwoLayer.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOLAYER_H +#define LWOLAYER_H + +#include + +#include "lwoChunk.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Class : LwoLayer +// Description : Signals the start of a new layer. All the data +// chunks which follow will be included in this layer +// until another layer chunk is encountered. If data is +// encountered before a layer chunk, it goes into an +// arbitrary layer. +//////////////////////////////////////////////////////////////////// +class LwoLayer : public LwoChunk { +public: + enum Flags { + F_hidden = 0x0001 + }; + + int _number; + int _flags; + LPoint3f _pivot; + string _name; + int _parent; + +public: + virtual bool read_iff(IffInputFile *in, size_t stop_at); + virtual void write(ostream &out, int indent_level = 0) const; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LwoChunk::init_type(); + register_type(_type_handle, "LwoLayer", + LwoChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoLayer.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoPoints.I b/pandatool/src/lwo/lwoPoints.I new file mode 100644 index 0000000000..992e23ae9a --- /dev/null +++ b/pandatool/src/lwo/lwoPoints.I @@ -0,0 +1,4 @@ +// Filename: lwoPoints.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoPoints.cxx b/pandatool/src/lwo/lwoPoints.cxx new file mode 100644 index 0000000000..2d3587c2a9 --- /dev/null +++ b/pandatool/src/lwo/lwoPoints.cxx @@ -0,0 +1,65 @@ +// Filename: lwoPoints.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoPoints.h" +#include "lwoInputFile.h" + +#include + +TypeHandle LwoPoints::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: LwoPoints::get_num_points +// Access: Public +// Description: Returns the number of points of this group. +//////////////////////////////////////////////////////////////////// +int LwoPoints:: +get_num_points() const { + return _points.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoPoints::get_point +// Access: Public +// Description: Returns the nth point of this group. +//////////////////////////////////////////////////////////////////// +const LPoint3f &LwoPoints:: +get_point(int n) const { + nassertr(n >= 0 && n < (int)_points.size(), LPoint3f::zero()); + return _points[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoPoints::read_iff +// Access: Public, Virtual +// Description: Reads the data of the chunk in from the given input +// file, if possible. The ID and length of the chunk +// have already been read. stop_at is the byte position +// of the file to stop at (based on the current position +// at in->get_bytes_read()). Returns true on success, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoPoints:: +read_iff(IffInputFile *in, size_t stop_at) { + LwoInputFile *lin = DCAST(LwoInputFile, in); + + while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { + LPoint3f point = lin->get_vec3(); + _points.push_back(point); + } + + return (lin->get_bytes_read() == stop_at); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoPoints::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LwoPoints:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << get_id() << " { " << _points.size() << " points }\n"; +} diff --git a/pandatool/src/lwo/lwoPoints.h b/pandatool/src/lwo/lwoPoints.h new file mode 100644 index 0000000000..820fce92fc --- /dev/null +++ b/pandatool/src/lwo/lwoPoints.h @@ -0,0 +1,55 @@ +// Filename: lwoPoints.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOPOINTS_H +#define LWOPOINTS_H + +#include + +#include "lwoChunk.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Class : LwoPoints +// Description : An array of points that will be referenced by later +// chunks. +//////////////////////////////////////////////////////////////////// +class LwoPoints : public LwoChunk { +public: + int get_num_points() const; + const LPoint3f &get_point(int n) const; + +public: + virtual bool read_iff(IffInputFile *in, size_t stop_at); + virtual void write(ostream &out, int indent_level = 0) const; + +private: + typedef vector Points; + Points _points; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LwoChunk::init_type(); + register_type(_type_handle, "LwoPoints", + LwoChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoPoints.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoPolygonTags.I b/pandatool/src/lwo/lwoPolygonTags.I new file mode 100644 index 0000000000..a5d46822df --- /dev/null +++ b/pandatool/src/lwo/lwoPolygonTags.I @@ -0,0 +1,4 @@ +// Filename: lwoPolygonTags.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoPolygonTags.cxx b/pandatool/src/lwo/lwoPolygonTags.cxx new file mode 100644 index 0000000000..5be95d9e80 --- /dev/null +++ b/pandatool/src/lwo/lwoPolygonTags.cxx @@ -0,0 +1,81 @@ +// Filename: lwoPolygonTags.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoPolygonTags.h" +#include "lwoInputFile.h" + +#include + +TypeHandle LwoPolygonTags::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: LwoPolygonTags::has_tag +// Access: Public +// Description: Returns true if the map has a tag associated with +// the given polygon index, false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoPolygonTags:: +has_tag(int polygon_index) const { + return (_tmap.count(polygon_index) != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoPolygonTags::get_tag +// Access: Public +// Description: Returns the tag associated with the given polygon +// index, or -1 if there is no tag associated. +//////////////////////////////////////////////////////////////////// +int LwoPolygonTags:: +get_tag(int polygon_index) const { + TMap::const_iterator ti; + ti = _tmap.find(polygon_index); + if (ti != _tmap.end()) { + return (*ti).second; + } + + return -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoPolygonTags::read_iff +// Access: Public, Virtual +// Description: Reads the data of the chunk in from the given input +// file, if possible. The ID and length of the chunk +// have already been read. stop_at is the byte position +// of the file to stop at (based on the current position +// at in->get_bytes_read()). Returns true on success, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoPolygonTags:: +read_iff(IffInputFile *in, size_t stop_at) { + LwoInputFile *lin = DCAST(LwoInputFile, in); + + _tag_type = lin->get_id(); + + while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { + int polygon_index = lin->get_vx(); + int tag = lin->get_be_int16(); + + bool inserted = _tmap.insert(TMap::value_type(polygon_index, tag)).second; + if (!inserted) { + nout << "Duplicate index " << index << " in map.\n"; + } + } + + return (lin->get_bytes_read() == stop_at); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoPolygonTags::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LwoPolygonTags:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << get_id() << " { tag_type = " << _tag_type << ", " + << _tmap.size() << " values }\n"; +} diff --git a/pandatool/src/lwo/lwoPolygonTags.h b/pandatool/src/lwo/lwoPolygonTags.h new file mode 100644 index 0000000000..2522940247 --- /dev/null +++ b/pandatool/src/lwo/lwoPolygonTags.h @@ -0,0 +1,57 @@ +// Filename: lwoPolygonTags.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOPOLYGONTAGS_H +#define LWOPOLYGONTAGS_H + +#include + +#include "lwoChunk.h" + +//////////////////////////////////////////////////////////////////// +// Class : LwoPolygonTags +// Description : An association of polygons defined in the most recent +// LwoPolygons chunk to tag ids defined in the most +// recent LwoTags chunk. This associated properties +// with the polygons, depending on the tag_type. +//////////////////////////////////////////////////////////////////// +class LwoPolygonTags : public LwoChunk { +public: + bool has_tag(int polygon_index) const; + int get_tag(int polygon_index) const; + + IffId _tag_type; + +public: + virtual bool read_iff(IffInputFile *in, size_t stop_at); + virtual void write(ostream &out, int indent_level = 0) const; + +private: + typedef map TMap; + TMap _tmap; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LwoChunk::init_type(); + register_type(_type_handle, "LwoPolygonTags", + LwoChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoPolygonTags.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoPolygons.I b/pandatool/src/lwo/lwoPolygons.I new file mode 100644 index 0000000000..d4c92f29f0 --- /dev/null +++ b/pandatool/src/lwo/lwoPolygons.I @@ -0,0 +1,4 @@ +// Filename: lwoPolygons.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoPolygons.cxx b/pandatool/src/lwo/lwoPolygons.cxx new file mode 100644 index 0000000000..653b47f1fc --- /dev/null +++ b/pandatool/src/lwo/lwoPolygons.cxx @@ -0,0 +1,77 @@ +// Filename: lwoPolygons.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoPolygons.h" +#include "lwoInputFile.h" + +#include + +TypeHandle LwoPolygons::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: LwoPolygons::get_num_polygons +// Access: Public +// Description: Returns the number of polygons of this group. +//////////////////////////////////////////////////////////////////// +int LwoPolygons:: +get_num_polygons() const { + return _polygons.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoPolygons::get_polygon +// Access: Public +// Description: Returns the nth polygon of this group. +//////////////////////////////////////////////////////////////////// +LwoPolygons::Polygon *LwoPolygons:: +get_polygon(int n) const { + nassertr(n >= 0 && n < (int)_polygons.size(), (Polygon *)NULL); + return _polygons[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoPolygons::read_iff +// Access: Public, Virtual +// Description: Reads the data of the chunk in from the given input +// file, if possible. The ID and length of the chunk +// have already been read. stop_at is the byte position +// of the file to stop at (based on the current position +// at in->get_bytes_read()). Returns true on success, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoPolygons:: +read_iff(IffInputFile *in, size_t stop_at) { + LwoInputFile *lin = DCAST(LwoInputFile, in); + + _polygon_type = lin->get_id(); + + while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { + int nf = lin->get_be_int16(); + int num_vertices = nf & PF_numverts_mask; + + PT(Polygon) poly = new Polygon; + poly->_flags = nf & ~PF_numverts_mask; + + for (int i = 0; i < num_vertices; i++) { + poly->_vertices.push_back(lin->get_vx()); + } + + _polygons.push_back(poly); + } + + return (lin->get_bytes_read() == stop_at); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoPolygons::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LwoPolygons:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << get_id() << " { polygon_type = " << _polygon_type + << ", " << _polygons.size() << " polygons }\n"; +} diff --git a/pandatool/src/lwo/lwoPolygons.h b/pandatool/src/lwo/lwoPolygons.h new file mode 100644 index 0000000000..e92ab98f42 --- /dev/null +++ b/pandatool/src/lwo/lwoPolygons.h @@ -0,0 +1,72 @@ +// Filename: lwoPolygons.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOPOLYGONS_H +#define LWOPOLYGONS_H + +#include + +#include "lwoChunk.h" + +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : LwoPolygons +// Description : An array of polygons that will be referenced by later +// chunks. +//////////////////////////////////////////////////////////////////// +class LwoPolygons : public LwoChunk { +public: + enum PolygonFlags { + PF_continuity_1 = 0x0400, + PF_continuity_2 = 0x0800, + PF_numverts_mask = 0x03ff + }; + + class Polygon : public ReferenceCount { + public: + int _flags; + vector_int _vertices; + }; + + int get_num_polygons() const; + Polygon *get_polygon(int n) const; + + IffId _polygon_type; + +public: + virtual bool read_iff(IffInputFile *in, size_t stop_at); + virtual void write(ostream &out, int indent_level = 0) const; + +private: + typedef vector< PT(Polygon) > Polygons; + Polygons _polygons; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LwoChunk::init_type(); + register_type(_type_handle, "LwoPolygons", + LwoChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoPolygons.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoTags.I b/pandatool/src/lwo/lwoTags.I new file mode 100644 index 0000000000..a3c958b283 --- /dev/null +++ b/pandatool/src/lwo/lwoTags.I @@ -0,0 +1,4 @@ +// Filename: lwoTags.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoTags.cxx b/pandatool/src/lwo/lwoTags.cxx new file mode 100644 index 0000000000..1d3e8d5a10 --- /dev/null +++ b/pandatool/src/lwo/lwoTags.cxx @@ -0,0 +1,76 @@ +// Filename: lwoTags.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoTags.h" +#include "lwoInputFile.h" + +#include + +TypeHandle LwoTags::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: LwoTags::get_num_tags +// Access: Public +// Description: Returns the number of tags of this group. +//////////////////////////////////////////////////////////////////// +int LwoTags:: +get_num_tags() const { + return _tags.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoTags::get_tag +// Access: Public +// Description: Returns the nth tag of this group. +//////////////////////////////////////////////////////////////////// +string LwoTags:: +get_tag(int n) const { + nassertr(n >= 0 && n < (int)_tags.size(), string()); + return _tags[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoTags::read_iff +// Access: Public, Virtual +// Description: Reads the data of the chunk in from the given input +// file, if possible. The ID and length of the chunk +// have already been read. stop_at is the byte position +// of the file to stop at (based on the current position +// at in->get_bytes_read()). Returns true on success, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoTags:: +read_iff(IffInputFile *in, size_t stop_at) { + LwoInputFile *lin = DCAST(LwoInputFile, in); + + while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { + string tag = lin->get_string(); + _tags.push_back(tag); + } + + return (lin->get_bytes_read() == stop_at); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoTags::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LwoTags:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << get_id() << " { "; + + if (!_tags.empty()) { + Tags::const_iterator ti = _tags.begin(); + out << *ti; + ++ti; + while (ti != _tags.end()) { + out << ", " << *ti; + ++ti; + } + } + out << " }\n"; +} diff --git a/pandatool/src/lwo/lwoTags.h b/pandatool/src/lwo/lwoTags.h new file mode 100644 index 0000000000..52338e5ddc --- /dev/null +++ b/pandatool/src/lwo/lwoTags.h @@ -0,0 +1,56 @@ +// Filename: lwoTags.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOTAGS_H +#define LWOTAGS_H + +#include + +#include "lwoChunk.h" + +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : LwoTags +// Description : An array of tag strings that will be referenced by +// later chunks. +//////////////////////////////////////////////////////////////////// +class LwoTags : public LwoChunk { +public: + int get_num_tags() const; + string get_tag(int n) const; + +public: + virtual bool read_iff(IffInputFile *in, size_t stop_at); + virtual void write(ostream &out, int indent_level = 0) const; + +private: + typedef vector_string Tags; + Tags _tags; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LwoChunk::init_type(); + register_type(_type_handle, "LwoTags", + LwoChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoTags.I" + +#endif + + diff --git a/pandatool/src/lwo/lwoVertexMap.I b/pandatool/src/lwo/lwoVertexMap.I new file mode 100644 index 0000000000..b3e41b913b --- /dev/null +++ b/pandatool/src/lwo/lwoVertexMap.I @@ -0,0 +1,4 @@ +// Filename: lwoVertexMap.I +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/lwo/lwoVertexMap.cxx b/pandatool/src/lwo/lwoVertexMap.cxx new file mode 100644 index 0000000000..4eee8bc70b --- /dev/null +++ b/pandatool/src/lwo/lwoVertexMap.cxx @@ -0,0 +1,90 @@ +// Filename: lwoVertexMap.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoVertexMap.h" +#include "lwoInputFile.h" + +#include + +TypeHandle LwoVertexMap::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: LwoVertexMap::has_value +// Access: Public +// Description: Returns true if the map has a value associated with +// the given index, false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoVertexMap:: +has_value(int index) const { + return (_vmap.count(index) != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoVertexMap::get_value +// Access: Public +// Description: Returns the mapping value associated with the given +// index, or an empty PTA_float if there is no mapping +// value associated. +//////////////////////////////////////////////////////////////////// +PTA_float LwoVertexMap:: +get_value(int index) const { + VMap::const_iterator vi; + vi = _vmap.find(index); + if (vi != _vmap.end()) { + return (*vi).second; + } + + return PTA_float(); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoVertexMap::read_iff +// Access: Public, Virtual +// Description: Reads the data of the chunk in from the given input +// file, if possible. The ID and length of the chunk +// have already been read. stop_at is the byte position +// of the file to stop at (based on the current position +// at in->get_bytes_read()). Returns true on success, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool LwoVertexMap:: +read_iff(IffInputFile *in, size_t stop_at) { + LwoInputFile *lin = DCAST(LwoInputFile, in); + + _map_type = lin->get_id(); + _dimension = lin->get_be_uint16(); + _name = lin->get_string(); + + while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { + int index = lin->get_vx(); + + PTA_float value; + for (int i = 0; i < _dimension; i++) { + value.push_back(lin->get_be_float32()); + } + + bool inserted = _vmap.insert(VMap::value_type(index, value)).second; + if (!inserted) { + nout << "Duplicate index " << index << " in map.\n"; + } + } + + return (lin->get_bytes_read() == stop_at); +} + +//////////////////////////////////////////////////////////////////// +// Function: LwoVertexMap::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LwoVertexMap:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << get_id() << " { map_type = " << _map_type + << ", dimension = " << _dimension + << ", name = \"" << _name << "\", " + << _vmap.size() << " values }\n"; +} diff --git a/pandatool/src/lwo/lwoVertexMap.h b/pandatool/src/lwo/lwoVertexMap.h new file mode 100644 index 0000000000..67ea493a82 --- /dev/null +++ b/pandatool/src/lwo/lwoVertexMap.h @@ -0,0 +1,60 @@ +// Filename: lwoVertexMap.h +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LWOVERTEXMAP_H +#define LWOVERTEXMAP_H + +#include + +#include "lwoChunk.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Class : LwoVertexMap +// Description : A mapping of floating-point values per integer index. +// The meaning of these values is determined by the +// mapping type code and/or its name. +//////////////////////////////////////////////////////////////////// +class LwoVertexMap : public LwoChunk { +public: + bool has_value(int index) const; + PTA_float get_value(int index) const; + + IffId _map_type; + int _dimension; + string _name; + +public: + virtual bool read_iff(IffInputFile *in, size_t stop_at); + virtual void write(ostream &out, int indent_level = 0) const; + +private: + typedef map VMap; + VMap _vmap; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LwoChunk::init_type(); + register_type(_type_handle, "LwoVertexMap", + LwoChunk::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "lwoVertexMap.I" + +#endif + + diff --git a/pandatool/src/lwo/test_lwo.cxx b/pandatool/src/lwo/test_lwo.cxx new file mode 100644 index 0000000000..d468295b7a --- /dev/null +++ b/pandatool/src/lwo/test_lwo.cxx @@ -0,0 +1,32 @@ +// Filename: test_lwo.cxx +// Created by: drose (24Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "lwoInputFile.h" +#include "lwoChunk.h" + +int +main(int argc, char *argv[]) { + if (argc != 2) { + cerr << "test_lwo file.lwo\n"; + exit(1); + } + + LwoInputFile in; + if (!in.open_read(argv[1])) { + cerr << "Unable to open " << argv[1] << "\n"; + exit(1); + } + + PT(IffChunk) chunk = in.get_chunk(); + while (chunk != (IffChunk *)NULL) { + cerr << "Got chunk type " << chunk->get_type() << ":\n"; + chunk->write(cerr, 2); + chunk = in.get_chunk(); + } + + cerr << "EOF = " << in.is_eof() << "\n"; + + return (0); +}