pm_3ds.c
pm_ase.c
pm_fm.c pm_fm.h
+ pm_iqm.c
pm_lwo.c
pm_md2.c
pm_md3.c
extern const picoColor_t picoColor_white;
/* types */
+#ifndef byte
+ typedef unsigned char byte;
+#endif
+
typedef struct picoParser_s
{
const char *buffer;
extern const picoModule_t picoModuleFM;
extern const picoModule_t picoModuleLWO;
extern const picoModule_t picoModuleTerrain;
+extern const picoModule_t picoModuleIQM;
&picoModuleLWO, /* lightwave object */
&picoModuleTerrain, /* picoterrain object */
&picoModuleOBJ, /* wavefront object */
+ &picoModuleIQM, /* interquake model */
NULL /* arnold */
};
#define INFO_HEIGHT 5
#define INFO_Y ( SKINPAGE_HEIGHT - INFO_HEIGHT )
-#ifndef byte
- #define byte unsigned char
-#endif
-
//
// Generic header on every chunk
--- /dev/null
+/* -----------------------------------------------------------------------------
+
+ InterQuake Model - PicoModel Library
+
+ Copyright (c) 2018-2021, FTE Team <fteqw.org>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this list
+ of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+
+ Neither the names of the copyright holders nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ----------------------------------------------------------------------------- */
+
+/* dependencies */
+#include "picointernal.h"
+
+extern const picoModule_t picoModuleIQM;
+
+#define IQM_MAGIC "INTERQUAKEMODEL" //15+null
+
+/*
+ ========================================================================
+
+ .IQM triangle model file format
+
+ ========================================================================
+ */
+
+enum
+{
+ IQM_POSITION = 0,
+ IQM_TEXCOORD = 1,
+ IQM_NORMAL = 2,
+ IQM_TANGENT = 3,
+ IQM_BLENDINDEXES = 4,
+ IQM_BLENDWEIGHTS = 5,
+ IQM_COLOR = 6,
+ IQM_CUSTOM = 0x10
+};
+
+enum
+{
+ IQM_BYTE = 0,
+ IQM_UBYTE = 1,
+ IQM_SHORT = 2,
+ IQM_USHORT = 3,
+ IQM_INT = 4,
+ IQM_UINT = 5,
+ IQM_HALF = 6,
+ IQM_FLOAT = 7,
+ 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;
+
+typedef struct iqmmesh_s {
+ unsigned int name;
+ unsigned int material;
+ unsigned int first_vertex;
+ unsigned int num_vertexes;
+ unsigned int first_triangle;
+ unsigned int num_triangles;
+} iqmmesh_t;
+
+typedef struct iqmvertexarray_s {
+ unsigned int type;
+ unsigned int flags;
+ unsigned int format;
+ unsigned int size;
+ unsigned int offset;
+} iqmvertexarray_t;
+
+//is anyone actually going to run this on a big-endian cpu?
+static iqmHeader_t SwapHeader(const iqmHeader_t *h)
+{
+ iqmHeader_t r = *h;
+ r.version = _pico_little_long(h->version);
+ r.filesize = _pico_little_long(h->filesize);
+ r.flags = _pico_little_long(h->flags);
+ r.num_text = _pico_little_long(h->num_text);
+ r.ofs_text = _pico_little_long(h->ofs_text);
+ r.num_meshes = _pico_little_long(h->num_meshes);
+ r.ofs_meshes = _pico_little_long(h->ofs_meshes);
+ r.num_vertexarrays = _pico_little_long(h->num_vertexarrays);
+ r.num_vertexes = _pico_little_long(h->num_vertexes);
+ r.ofs_vertexarrays = _pico_little_long(h->ofs_vertexarrays);
+ r.num_triangles = _pico_little_long(h->num_triangles);
+ r.ofs_triangles = _pico_little_long(h->ofs_triangles);
+ r.ofs_neighbors = _pico_little_long(h->ofs_neighbors);
+ r.num_joints = _pico_little_long(h->num_joints);
+ r.ofs_joints = _pico_little_long(h->ofs_joints);
+ r.num_poses = _pico_little_long(h->num_poses);
+ r.ofs_poses = _pico_little_long(h->ofs_poses);
+ r.num_anims = _pico_little_long(h->num_anims);
+ r.ofs_anims = _pico_little_long(h->ofs_anims);
+ r.num_frames = _pico_little_long(h->num_frames);
+ r.num_framechannels = _pico_little_long(h->num_framechannels);
+ r.ofs_frames = _pico_little_long(h->ofs_frames);
+ r.ofs_bounds = _pico_little_long(h->ofs_bounds);
+ r.num_comment = _pico_little_long(h->num_comment);
+ r.ofs_comment = _pico_little_long(h->ofs_comment);
+ r.num_extensions = _pico_little_long(h->num_extensions);
+ r.ofs_extensions = _pico_little_long(h->ofs_extensions);
+ return r;
+}
+
+// _iqm_canload()
+static int _iqm_canload( PM_PARAMS_CANLOAD ){
+ iqmHeader_t h;
+
+ //make sure there's enough data for the header...
+ if ((size_t)bufSize < sizeof(h))
+ return PICO_PMV_ERROR_SIZE;
+ h = SwapHeader(buffer);
+
+ //make sure its actually an iqm
+ if (memcmp(h.id, IQM_MAGIC, sizeof(h.id)))
+ return PICO_PMV_ERROR_IDENT;
+ //v1 is flawed, we don't know about anything higher either.
+ if (h.version != 2)
+ return PICO_PMV_ERROR_VERSION;
+ //make sure its not truncated
+ if ((size_t)h.filesize != (size_t)bufSize)
+ return PICO_PMV_ERROR_SIZE;
+
+ //looks like we can probably use it.
+ return PICO_PMV_OK;
+}
+
+// _iqm_load() loads an interquake model file.
+static picoModel_t *_iqm_load( PM_PARAMS_LOAD ){
+ picoModel_t *picoModel;
+ picoSurface_t *picoSurface;
+ picoShader_t *picoShader;
+ const float *inf;
+ const byte *inb;
+ picoVec3_t xyz, normal;
+ picoVec2_t st;
+ picoColor_t color;
+
+ iqmHeader_t h;
+ iqmmesh_t m;
+ iqmvertexarray_t a;
+ size_t s, t, j, i;
+ const char *stringtable;
+ char skinname[512];
+ const unsigned int *tri;
+
+ //just in case
+ if (_iqm_canload(fileName, buffer, bufSize) != PICO_PMV_OK)
+ {
+ _pico_printf( PICO_ERROR, "%s is not an IQM File!", fileName );
+ return NULL;
+ }
+ h = SwapHeader(buffer);
+ stringtable = (const char*)buffer + h.ofs_text;
+
+ // do frame check
+ if ( h.num_anims != 0 ) {
+ _pico_printf( PICO_WARNING, "%s has animations! Using base pose only.", fileName );
+ }
+
+ /* create new pico model */
+ picoModel = PicoNewModel();
+ if ( picoModel == NULL ) {
+ _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
+ return NULL;
+ }
+
+ /* do model setup */
+ PicoSetModelFrameNum( picoModel, frameNum );
+ PicoSetModelNumFrames( picoModel, 1 ); /* sea */
+ PicoSetModelName( picoModel, fileName );
+ PicoSetModelFileName( picoModel, fileName );
+
+ for (s = 0; s < h.num_meshes; s++)
+ {
+ m = ((const iqmmesh_t*)((const char*)buffer + h.ofs_meshes))[s];
+ m.first_triangle = _pico_little_long(m.first_triangle);
+ m.first_vertex = _pico_little_long(m.first_vertex);
+ m.material = _pico_little_long(m.material);
+ m.name = _pico_little_long(m.name);
+ m.num_triangles = _pico_little_long(m.num_triangles);
+ m.num_vertexes = _pico_little_long(m.num_vertexes);
+
+ // allocate new pico surface
+ picoSurface = PicoNewSurface( picoModel );
+ if ( picoSurface == NULL ) {
+ _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
+ PicoFreeModel( picoModel );
+ return NULL;
+ }
+
+ // detox Skin name
+ memcpy(skinname, stringtable+m.material, sizeof(skinname));
+ _pico_setfext( skinname, "" );
+ _pico_unixify( skinname );
+
+ PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
+ PicoSetSurfaceName( picoSurface, stringtable+m.name );
+ picoShader = PicoNewShader( picoModel );
+ if ( picoShader == NULL ) {
+ _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
+ PicoFreeModel( picoModel );
+ return NULL;
+ }
+
+ PicoSetShaderName( picoShader, skinname );
+
+ // associate current surface with newly created shader
+ PicoSetSurfaceShader( picoSurface, picoShader );
+
+
+ // spew the surface's indexes
+ tri = (const unsigned int *)((const char *)buffer+h.ofs_triangles) + m.first_triangle*3;
+ for (t = 0; t < m.num_triangles*3; t++)
+ PicoSetSurfaceIndex( picoSurface, t, _pico_little_long(*tri++) - m.first_vertex );
+
+ for ( j = 0; j < h.num_vertexarrays; j++)
+ {
+ a = ((const iqmvertexarray_t*)((const char*)buffer + h.ofs_vertexarrays))[j];
+ a.flags = _pico_little_long(a.flags);
+ a.format = _pico_little_long(a.format);
+ a.offset = _pico_little_long(a.offset);
+ a.size = _pico_little_long(a.size);
+ a.type = _pico_little_long(a.type);
+
+ switch(a.type)
+ {
+ case IQM_POSITION:
+ if (a.format == IQM_FLOAT && a.size >= 3)
+ {
+ inf = (const float*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+ for ( i = 0; i < m.num_vertexes; i++, inf += a.size )
+ {
+ xyz[0] = _pico_little_float(inf[0]);
+ xyz[1] = _pico_little_float(inf[1]);
+ xyz[2] = _pico_little_float(inf[2]);
+ PicoSetSurfaceXYZ( picoSurface, i, xyz );
+ }
+ }
+ break;
+ case IQM_TEXCOORD:
+ if (a.format == IQM_FLOAT && a.size >= 2)
+ {
+ inf = (const float*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+ for ( i = 0; i < m.num_vertexes; i++, inf += a.size )
+ {
+ st[0] = _pico_little_float(inf[0]);
+ st[1] = _pico_little_float(inf[1]);
+ PicoSetSurfaceST( picoSurface, 0, i, st );
+ }
+ }
+ break;
+ case IQM_NORMAL:
+ if (a.format == IQM_FLOAT && a.size >= 3)
+ {
+ inf = (const float*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+ for ( i = 0; i < m.num_vertexes; i++, inf += a.size )
+ {
+ normal[0] = _pico_little_float(inf[0]);
+ normal[1] = _pico_little_float(inf[1]);
+ normal[2] = _pico_little_float(inf[2]);
+ PicoSetSurfaceNormal( picoSurface, i, normal );
+ }
+ }
+ break;
+ case IQM_COLOR:
+ if (a.format == IQM_UBYTE && a.size >= 3)
+ {
+ inb = (const byte*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+ for ( i = 0; i < m.num_vertexes; i++, inb += a.size )
+ {
+ color[0] = inb[0];
+ color[1] = inb[1];
+ color[2] = inb[2];
+ color[3] = (a.size>=4)?inb[3]:255;
+ PicoSetSurfaceColor( picoSurface, 0, i, color );
+ }
+ }
+ else if (a.format == IQM_FLOAT && a.size >= 3)
+ {
+ inf = (const float*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+ for ( i = 0; i < m.num_vertexes; i++, inf += a.size )
+ {
+ color[0] = inf[0]*255;
+ color[1] = inf[1]*255;
+ color[2] = inf[2]*255;
+ color[3] = (a.size>=4)?inf[3]*255:255;
+ PicoSetSurfaceColor( picoSurface, 0, i, color );
+ }
+ }
+ break;
+ case IQM_TANGENT:
+ case IQM_BLENDINDEXES:
+ case IQM_BLENDWEIGHTS:
+ case IQM_CUSTOM:
+ break; // these attributes are not relevant.
+ }
+ }
+ }
+
+ return picoModel;
+}
+
+/* pico file format module definition */
+const picoModule_t picoModuleIQM =
+{
+ "0.1", /* module version string */
+ "InterQuake Model", /* module display name */
+ "Spoike", /* author's name */
+ "2018-2021 FTE Team", /* module copyright */
+ {
+ "iqm", NULL, NULL, NULL /* default extensions to use */
+ },
+ _iqm_canload, /* validation routine */
+ _iqm_load, /* load routine */
+ NULL, /* save validation routine */
+ NULL /* save routine */
+};
add_subdirectory(imagepng)
add_subdirectory(imageq2)
add_subdirectory(imagewebp)
-add_subdirectory(iqmmodel)
add_subdirectory(mapq3)
add_subdirectory(mapxml)
add_subdirectory(md3model)
+++ /dev/null
-radiant_plugin(iqmmodel
- iqm.cpp iqm.h
- plugin.cpp plugin.h
- )
+++ /dev/null
-/*
- 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 );
-}
-
-const int IQM_POSITION = 0;
-const int IQM_TEXCOORD = 1;
-const int IQM_NORMAL = 2;
-const int IQM_TANGENT = 3;
-const int IQM_BLENDINDEXES = 4;
-const int IQM_BLENDWEIGHTS = 5;
-const int IQM_COLOR = 6;
-const int IQM_CUSTOM = 0x10;
-
-const int IQM_BYTE = 0;
-const int IQM_UBYTE = 1;
-const int IQM_SHORT = 2;
-const int IQM_USHORT = 3;
-const int IQM_INT = 4;
-const int IQM_UINT = 5;
-const int IQM_HALF = 6;
-const int IQM_FLOAT = 7;
-const int IQM_DOUBLE = 8;
-
-// animflags
-const int 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 iqmmesh_s {
- unsigned int name;
- unsigned int material;
- unsigned int first_vertex;
- unsigned int num_vertexes;
- unsigned int first_triangle;
- unsigned int num_triangles;
-} iqmmesh_t;
-
-void istream_read_iqmMesh( PointerInputStream &inputStream, iqmmesh_t &iqmmesh ){
-#define READUINT( x ) iqmmesh.x = istream_read_uint32_le( inputStream );
- READUINT( name )
- READUINT( material )
- READUINT( first_vertex )
- READUINT( num_vertexes )
- READUINT( first_triangle )
- READUINT( num_triangles )
-#undef READUINT
-}
-
-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 &vertexarray ){
-#define READINT( x ) vertexarray.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 ){
- iqmHeader_t header;
- {
- PointerInputStream inputStream( buffer );
- istream_read_iqmHeader( inputStream, header );
- }
-
- int ofs_position = -1, ofs_st = -1, ofs_normal = -1;
- PointerInputStream vaStream( buffer + header.ofs_vertexarrays );
- for ( unsigned 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;
- }
- }
-
- 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 iqmMesh( buffer + header.ofs_meshes );
- for ( unsigned int m = 0; m < header.num_meshes; m++ ) {
- Surface &surface = model.newSurface();
-
- iqmmesh_t iqmmesh;
- istream_read_iqmMesh( iqmMesh, iqmmesh );
-
- bool material_found = false;
- // if not malformed data neither missing string
- if ( iqmmesh.material <= header.num_text && iqmmesh.material > 0 ) {
- char *material;
- material = (char*) buffer + header.ofs_text + iqmmesh.material;
-
- if ( material[0] != '\0' ) {
- surface.setShader( material );
- material_found = true;
- }
- }
-
- if ( !material_found ) {
- // empty string will trigger "textures/shader/notex" on display
- surface.setShader( "" );
- }
-
- UniqueVertexBuffer<ArbitraryMeshVertex> inserter( surface.vertices() );
- inserter.reserve( iqmmesh.num_vertexes );
-
- surface.indices().reserve( iqmmesh.num_vertexes );
-
- unsigned int triangle_offset = header.ofs_triangles + iqmmesh.first_triangle * sizeof( iqmTriangle_t );
- PointerInputStream triangleStream( buffer + triangle_offset );
- for ( unsigned int i = 0; i < iqmmesh.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.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 );
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-; modeliqm.def : Declares the module parameters for the DLL.
-
-LIBRARY "MODELIQM"
-
-EXPORTS
- ; Explicit exports can go here
- Radiant_RegisterModules @1
+++ /dev/null
-/*
- 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( "InterQuake 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();
-}
+++ /dev/null
-/*
- 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