]> de.git.xonotic.org Git - xonotic/netradiant.git/commitdiff
Apply Max's iqm support patch.
authorharveynik <harveynik@gmail.com>
Mon, 13 Jan 2014 01:48:44 +0000 (02:48 +0100)
committerThomas Debesse <dev@illwieckz.net>
Mon, 24 Jul 2017 01:52:14 +0000 (03:52 +0200)
Apply Max's iqm support patch.
This has only been tested on Arch and Mint linux.

plugins/iqmmodel/iqm.cpp [new file with mode: 0644]
plugins/iqmmodel/iqm.h [new file with mode: 0644]
plugins/iqmmodel/modeliqm.def [new file with mode: 0644]
plugins/iqmmodel/plugin.cpp [new file with mode: 0644]
plugins/iqmmodel/plugin.h [new file with mode: 0644]

diff --git a/plugins/iqmmodel/iqm.cpp b/plugins/iqmmodel/iqm.cpp
new file mode 100644 (file)
index 0000000..c1f7db8
--- /dev/null
@@ -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<ArbitraryMeshVertex> 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_t> iqmPos(header.num_vertexes);
+    for(Array<iqmPos_t>::iterator i = iqmPos.begin(); i != iqmPos.end(); ++i)
+    {
+      istream_read_iqmPos(posStream, *i);
+    }
+    
+    PointerInputStream normStream(buffer + ofs_normal);
+    Array<iqmPos_t> iqmNorm(header.num_vertexes);
+    for(Array<iqmPos_t>::iterator i = iqmNorm.begin(); i != iqmNorm.end(); ++i)
+    {
+      istream_read_iqmPos(normStream, *i);
+    }
+
+    Array<iqmSt_t> iqmSt(header.num_vertexes);
+    PointerInputStream stStream(buffer + ofs_st);
+    for(Array<iqmSt_t>::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 (file)
index 0000000..9362b9c
--- /dev/null
@@ -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 (file)
index 0000000..5791cd7
--- /dev/null
@@ -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 (file)
index 0000000..48ba470
--- /dev/null
@@ -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<ModelIQMAPI, ModelDependencies> 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 (file)
index 0000000..2f338b6
--- /dev/null
@@ -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