From: harveynik Date: Mon, 13 Jan 2014 01:48:44 +0000 (+0100) Subject: Apply Max's iqm support patch. X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=commitdiff_plain;h=c8b1e5cc492421114e1b0e6c1b0fc26afe0f2795 Apply Max's iqm support patch. Apply Max's iqm support patch. This has only been tested on Arch and Mint linux. --- diff --git a/plugins/iqmmodel/iqm.cpp b/plugins/iqmmodel/iqm.cpp new file mode 100644 index 00000000..c1f7db89 --- /dev/null +++ b/plugins/iqmmodel/iqm.cpp @@ -0,0 +1,294 @@ +/* +Copyright (C) 2001-2006, William Joseph. +Copyright (C) 2010-2014 COR Entertainment, LLC. +All Rights Reserved. + +This file is part of GtkRadiant. + +GtkRadiant is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +GtkRadiant 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GtkRadiant; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "iqm.h" + +#include "ifilesystem.h" +#include "imodel.h" + +#include "imagelib.h" +#include "bytestreamutils.h" + +#include "../md3model/model.h" + +typedef unsigned char byte; + +/* +======================================================================== + +.IQM triangle model file format + +======================================================================== +*/ +typedef struct +{ + float s; + float t; +} iqmSt_t; + +void istream_read_iqmSt(PointerInputStream& inputStream, iqmSt_t& st) +{ + st.s = istream_read_float32_le(inputStream); + st.t = istream_read_float32_le(inputStream); +} + +typedef struct +{ + unsigned int indices[3]; +} iqmTriangle_t; + +void istream_read_iqmTriangle(PointerInputStream& inputStream, iqmTriangle_t& triangle) +{ + triangle.indices[0] = istream_read_int32_le(inputStream); + triangle.indices[1] = istream_read_int32_le(inputStream); + triangle.indices[2] = istream_read_int32_le(inputStream); +} + +typedef struct +{ + float v[3]; +} iqmPos_t; + +void istream_read_iqmPos(PointerInputStream& inputStream, iqmPos_t& iqmPos) +{ + iqmPos.v[0] = istream_read_float32_le(inputStream); + iqmPos.v[1] = istream_read_float32_le(inputStream); + iqmPos.v[2] = istream_read_float32_le(inputStream); +} + +#define IQM_POSITION 0 +#define IQM_TEXCOORD 1 +#define IQM_NORMAL 2 +#define IQM_TANGENT 3 +#define IQM_BLENDINDEXES 4 +#define IQM_BLENDWEIGHTS 5 +#define IQM_COLOR 6 +#define IQM_CUSTOM 0x10 + +#define IQM_BYTE 0 +#define IQM_UBYTE 1 +#define IQM_SHORT 2 +#define IQM_USHORT 3 +#define IQM_INT 4 +#define IQM_UINT 5 +#define IQM_HALF 6 +#define IQM_FLOAT 7 +#define IQM_DOUBLE 8 + +// animflags +#define IQM_LOOP 1 + +typedef struct iqmHeader_s +{ + byte id[16]; + unsigned int version; + unsigned int filesize; + unsigned int flags; + unsigned int num_text, ofs_text; + unsigned int num_meshes, ofs_meshes; + unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays; + unsigned int num_triangles, ofs_triangles, ofs_neighbors; + unsigned int num_joints, ofs_joints; + unsigned int num_poses, ofs_poses; + unsigned int num_anims, ofs_anims; + unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds; + unsigned int num_comment, ofs_comment; + unsigned int num_extensions, ofs_extensions; +} iqmHeader_t; + +void istream_read_iqmHeader(PointerInputStream& inputStream, iqmHeader_t& header) +{ + inputStream.read(header.id, 16); +#define READINT(x) header.x = istream_read_int32_le(inputStream); + READINT (version) + READINT (filesize) + READINT (flags) + READINT (num_text) + READINT (ofs_text) + READINT (num_meshes) + READINT (ofs_meshes) + READINT (num_vertexarrays) + READINT (num_vertexes) + READINT (ofs_vertexarrays) + READINT (num_triangles) + READINT (ofs_triangles) + READINT (ofs_neighbors) + READINT (num_joints) + READINT (ofs_joints) + READINT (num_frames) + READINT (num_framechannels) + READINT (ofs_frames) + READINT (ofs_bounds) + READINT (num_comment) + READINT (ofs_comment) + READINT (num_extensions) + READINT (ofs_extensions) +#undef READINT +} + +typedef struct iqmvertexarray_s +{ + unsigned int type; + unsigned int flags; + unsigned int format; + unsigned int size; + unsigned int offset; +} +iqmvertexarray_t; + +void istream_read_iqmVertexarray(PointerInputStream& inputStream, iqmvertexarray_t& out) +{ +#define READINT(x) out.x = istream_read_int32_le(inputStream); + READINT (type) + READINT (flags) + READINT (format) + READINT (size) + READINT (offset) +#undef READINT +} + + +ArbitraryMeshVertex IQMVertex_construct(const iqmPos_t* pos, const iqmPos_t* norm, const iqmSt_t* st) +{ + return ArbitraryMeshVertex( + Vertex3f (pos->v[0], pos->v[1], pos->v[2]), + Normal3f (norm->v[0], norm->v[1], norm->v[2]), + TexCoord2f (st->s, st->t) + ); +} + +void IQMSurface_read(Model& model, const byte* buffer, ArchiveFile& file) +{ + Surface& surface = model.newSurface(); + iqmHeader_t header; + { + PointerInputStream inputStream(buffer); + istream_read_iqmHeader(inputStream, header); + } + + { + + UniqueVertexBuffer inserter(surface.vertices()); + inserter.reserve(header.num_vertexes); + + int ofs_position = -1, ofs_st = -1, ofs_normal = -1; + PointerInputStream vaStream (buffer + header.ofs_vertexarrays); + for (int i = 0; i < header.num_vertexarrays; i++) + { + iqmvertexarray_t va; + istream_read_iqmVertexarray (vaStream, va); + + switch (va.type) + { + case IQM_POSITION: + if (va.format == IQM_FLOAT && va.size == 3) + ofs_position = va.offset; + break; + case IQM_TEXCOORD: + if (va.format == IQM_FLOAT && va.size == 2) + ofs_st = va.offset; + break; + case IQM_NORMAL: + if (va.format == IQM_FLOAT && va.size == 3) + ofs_normal = va.offset; + break; + } + } + + surface.indices().reserve(header.num_vertexes); + + PointerInputStream posStream(buffer + ofs_position); + Array iqmPos(header.num_vertexes); + for(Array::iterator i = iqmPos.begin(); i != iqmPos.end(); ++i) + { + istream_read_iqmPos(posStream, *i); + } + + PointerInputStream normStream(buffer + ofs_normal); + Array iqmNorm(header.num_vertexes); + for(Array::iterator i = iqmNorm.begin(); i != iqmNorm.end(); ++i) + { + istream_read_iqmPos(normStream, *i); + } + + Array iqmSt(header.num_vertexes); + PointerInputStream stStream(buffer + ofs_st); + for(Array::iterator i = iqmSt.begin(); i != iqmSt.end(); ++i) + { + istream_read_iqmSt(stStream, *i); + } + + PointerInputStream triangleStream(buffer + header.ofs_triangles); + for(int i = 0; i < header.num_triangles; ++i) + { + iqmTriangle_t triangle; + istream_read_iqmTriangle(triangleStream, triangle); + for (int j = 0; j < 3; j++) + surface.indices().insert(inserter.insert(IQMVertex_construct( + &iqmPos[triangle.indices[j]], + &iqmNorm[triangle.indices[j]], + &iqmSt[triangle.indices[j]]))); + } + } + + surface.setShader(""); + surface.updateAABB(); +} + +void IQMModel_read(Model& model, const byte* buffer, ArchiveFile& file) +{ + IQMSurface_read(model, buffer, file); + model.updateAABB(); +} + +scene::Node& IQMModel_new(const byte* buffer, ArchiveFile& file) +{ + ModelNode* modelNode = new ModelNode(); + IQMModel_read(modelNode->model(), buffer, file); + return modelNode->node(); +} + +scene::Node& IQMModel_default() +{ + ModelNode* modelNode = new ModelNode(); + Model_constructNull(modelNode->model()); + return modelNode->node(); +} + +scene::Node& IQMModel_fromBuffer(unsigned char* buffer, ArchiveFile& file) +{ + if (memcmp(buffer, "INTERQUAKEMODEL", 16)) + { + globalErrorStream() << "IQM read error: incorrect ident\n"; + return IQMModel_default(); + } + else + { + return IQMModel_new(buffer, file); + } +} + +scene::Node& loadIQMModel(ArchiveFile& file) +{ + ScopedArchiveBuffer buffer(file); + return IQMModel_fromBuffer(buffer.buffer, file); +} diff --git a/plugins/iqmmodel/iqm.h b/plugins/iqmmodel/iqm.h new file mode 100644 index 00000000..9362b9cf --- /dev/null +++ b/plugins/iqmmodel/iqm.h @@ -0,0 +1,30 @@ +/* +Copyright (C) 2001-2006, William Joseph. +All Rights Reserved. + +This file is part of GtkRadiant. + +GtkRadiant is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +GtkRadiant 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GtkRadiant; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#if !defined(INCLUDED_IQM_H) +#define INCLUDED_IQM_H + +namespace scene { class Node; } +class ArchiveFile; +scene::Node& loadIQMModel(ArchiveFile& file); + + +#endif diff --git a/plugins/iqmmodel/modeliqm.def b/plugins/iqmmodel/modeliqm.def new file mode 100644 index 00000000..5791cd7b --- /dev/null +++ b/plugins/iqmmodel/modeliqm.def @@ -0,0 +1,7 @@ +; modeliqm.def : Declares the module parameters for the DLL. + +LIBRARY "MODELIQM" + +EXPORTS + ; Explicit exports can go here + Radiant_RegisterModules @1 diff --git a/plugins/iqmmodel/plugin.cpp b/plugins/iqmmodel/plugin.cpp new file mode 100644 index 00000000..48ba470c --- /dev/null +++ b/plugins/iqmmodel/plugin.cpp @@ -0,0 +1,87 @@ +/* +Copyright (C) 2001-2006, William Joseph. +All Rights Reserved. + +This file is part of GtkRadiant. + +GtkRadiant is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +GtkRadiant 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GtkRadiant; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "plugin.h" + +#include "iscenegraph.h" +#include "irender.h" +#include "iselection.h" +#include "iimage.h" +#include "imodel.h" +#include "igl.h" +#include "ifilesystem.h" +#include "iundo.h" +#include "ifiletypes.h" +#include "iscriplib.h" + +#include "modulesystem/singletonmodule.h" +#include "typesystem.h" + +#include "iqm.h" + + +class IQMModelLoader : public ModelLoader +{ +public: + scene::Node& loadModel(ArchiveFile& file) + { + return loadIQMModel(file); + } +}; + +class ModelDependencies : + public GlobalFileSystemModuleRef, + public GlobalOpenGLModuleRef, + public GlobalUndoModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalSelectionModuleRef, + public GlobalFiletypesModuleRef +{ +}; + +class ModelIQMAPI : public TypeSystemRef +{ + IQMModelLoader m_modeliqm; +public: + typedef ModelLoader Type; + STRING_CONSTANT(Name, "iqm"); + + ModelIQMAPI() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("iqm models", "*.iqm")); + } + ModelLoader* getTable() + { + return &m_modeliqm; + } +}; + +typedef SingletonModule ModelIQMModule; + +ModelIQMModule g_ModelIQMModule; + +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server) +{ + initialiseModule(server); + + g_ModelIQMModule.selfRegister(); +} diff --git a/plugins/iqmmodel/plugin.h b/plugins/iqmmodel/plugin.h new file mode 100644 index 00000000..2f338b60 --- /dev/null +++ b/plugins/iqmmodel/plugin.h @@ -0,0 +1,25 @@ +/* +Copyright (C) 2001-2006, William Joseph. +All Rights Reserved. + +This file is part of GtkRadiant. + +GtkRadiant is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +GtkRadiant 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GtkRadiant; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#if !defined(INCLUDED_SAMPLE_H) +#define INCLUDED_SAMPLE_H + +#endif