mirror of
https://github.com/id-Software/GtkRadiant.git
synced 2026-03-19 16:39:26 +01:00
The GtkRadiant sources as originally released under the GPL license.
This commit is contained in:
172
plugins/md3model/doc/md3-design.txt
Normal file
172
plugins/md3model/doc/md3-design.txt
Normal file
@@ -0,0 +1,172 @@
|
||||
map objects module
|
||||
==================
|
||||
|
||||
Objective:
|
||||
----------
|
||||
|
||||
#1 Turn the md3 code into a module. That is handle all aspects of map objects in
|
||||
a module. This involves:
|
||||
- the rendering of the model (sleep mode / shader reload are associated issues)
|
||||
- the manipulation in the editor (moving, rotating, (scaling?))
|
||||
|
||||
#2 Have an API generic enough to support other formats than md3. (md1 / md2 for
|
||||
multiple games support, any other formats).
|
||||
|
||||
What we have:
|
||||
-------------
|
||||
|
||||
What is the current implementation of md3 support? Were are the important
|
||||
features that we will need to work with?
|
||||
|
||||
"misc_model" is the required classname for any map object
|
||||
|
||||
entity_t::md3Class
|
||||
eclass_t *md3Class;
|
||||
This holds the actual md3 object and the rendering information (tri soup,
|
||||
shader etc.)
|
||||
entity_t also has vRotation and vScale which are particular to the model
|
||||
|
||||
for selection of the brush (selection is preliminary step before any
|
||||
manipulation operation), we create a bounding box from the md3 information
|
||||
and use the entity's brush list as storage for it.
|
||||
|
||||
Requirements:
|
||||
-------------
|
||||
|
||||
Some technical requirements go on top of our objective given the existing
|
||||
implementation. The most important one is that the changes applied to the
|
||||
core must remain focused around the md3 functionality, and must also lay
|
||||
out the basics of some wider changes. We can identify some of those changes:
|
||||
|
||||
- introducing a more generalized way of selecting and manipulation things
|
||||
in the editor.
|
||||
|
||||
- introducing a more generic way of rendering objects in the editor.
|
||||
|
||||
More specifically, the details of rendering and manipulation:
|
||||
|
||||
transformation
|
||||
translate&rotate:
|
||||
A transformation increment is provided
|
||||
The object is transformed by a specified increment.
|
||||
Depending on the object type, the transformations may affect
|
||||
the local coordinate space transformation instead of the object.
|
||||
This local transformation is used in selection and rendering.
|
||||
|
||||
selection:
|
||||
ray:
|
||||
Radiant asks model for its world-relative axis-alignedbounding box.
|
||||
Radiant does intersection test with this bounding box.
|
||||
If test shows intersection, radiant gives model a ray_t, model tests
|
||||
for intersection with ray, model returns bool true if intersection
|
||||
A selection ray in world-space (origin+direction) is provided.
|
||||
The object must say whether or not it intersects with the ray.
|
||||
map objects have a special configuration to test on bounding box or trisoup
|
||||
this is set in preferences independently from the true/false selection tests
|
||||
area:
|
||||
radiant uses a bounding box for area selection. (bounding box can be
|
||||
infinite in some directions for the 'select tall' operations, in practice
|
||||
we just make them big enough).
|
||||
|
||||
rendering:
|
||||
geometry:
|
||||
Radiant tells the object what combination of 4 opengl states is currently active:
|
||||
none - draw as wireframe
|
||||
fill - draw as filled
|
||||
alpha blend - provide an opacity value
|
||||
texture_2d - provide a texture and texture coordinates
|
||||
lighting - provide normals, enable/disable smooth shading
|
||||
The object uses opengl to set up its geometry and to draw itself.
|
||||
material:
|
||||
The object provides a material name and is assigned a reference to
|
||||
a shader that matches the name.
|
||||
The shader contains the texture ID and the opacity value.
|
||||
The shader is a reference to an external script and must be refreshed
|
||||
on request.
|
||||
|
||||
|
||||
Proposed implementation:
|
||||
========================
|
||||
|
||||
changes in shared interfaces (include/ directory):
|
||||
--------------------------------------------------
|
||||
|
||||
The following new interfaces will be added:
|
||||
most likely those interfaces will be implemented in the module
|
||||
|
||||
/*!
|
||||
something that can be selected
|
||||
*/
|
||||
class ISelect
|
||||
{
|
||||
bool TestRay(ray_t) = 0
|
||||
bool TestBox(vec3_t vec_min, vec3_t vec_max) = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
something that can be selected for edition
|
||||
this must be synced with entity epairs
|
||||
(such as origin and angles keys)
|
||||
*/
|
||||
class IEdit
|
||||
{
|
||||
void Translate(vec3_t v) = 0;
|
||||
void Rotate(vec3_t origin, vec3_t angles) = 0;
|
||||
}
|
||||
|
||||
for rendering, the existing IGL2DWindow and IGL3DWindow APIs
|
||||
we can define
|
||||
class IRender : public IGL2DWindow, public IGL3DWindow
|
||||
so that we have the Render2D and Render3D on the same class
|
||||
|
||||
entity_t will have to be modified, adding the following struct:
|
||||
typedef struct entity_interfaces_s
|
||||
{
|
||||
ISelect *pSelect
|
||||
IEdit *pEdit
|
||||
IRender *pRender
|
||||
}
|
||||
entity_interfaces_t;
|
||||
|
||||
When one of the pointers inside entity_t::entity_interfaces
|
||||
is != we will handle the entity differently that what we are
|
||||
doing by default. We will rely on these APIs for rendering,
|
||||
manipulation etc.
|
||||
|
||||
the AABB issue:
|
||||
|
||||
|
||||
changes in the core:
|
||||
--------------------
|
||||
|
||||
In all cases where the entity_t has to be drawn, tested for selection,
|
||||
manipulated (translation and rotation), add new code to go through the APIs.
|
||||
|
||||
|
||||
md3 module:
|
||||
-----------
|
||||
|
||||
static function table API
|
||||
|
||||
- registering of "model" module
|
||||
need some minors? "md3" etc.
|
||||
|
||||
- BuildEntity(entity_t)
|
||||
if an entity involved with models is found, core will call this
|
||||
entity_t::entity_interfaces will be filled with the relevant classes
|
||||
|
||||
(NOTE:L we don't have a need right now to manipulate a model that
|
||||
would not be part of an entity. so let's not try to guess what it
|
||||
would be like)
|
||||
|
||||
CModel
|
||||
stores the trisoup, local AABBs, references to shaders
|
||||
(CModel potentially needs a CModelManager to handle
|
||||
model loads and cached models queries)
|
||||
|
||||
CModelEntity implements IRender ISelect IEdit
|
||||
stores an entity_t*
|
||||
implements the interfaces pointed to in the entity_t
|
||||
is reference counted obviously
|
||||
stores a CModel*, calls up to it with entity information for rendering
|
||||
|
||||
33
plugins/md3model/ident.h
Normal file
33
plugins/md3model/ident.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
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_IDENT_H)
|
||||
#define INCLUDED_IDENT_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// equality comparison for two 4-byte ident strings
|
||||
inline bool ident_equal(const unsigned char* ident, const unsigned char* other)
|
||||
{
|
||||
return ident[0] == other[0] && ident[1] == other[1] && ident[2] == other[2] && ident[3] == other[3];
|
||||
}
|
||||
|
||||
#endif
|
||||
285
plugins/md3model/md2.cpp
Normal file
285
plugins/md3model/md2.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
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 "md2.h"
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "imodel.h"
|
||||
|
||||
#include "imagelib.h"
|
||||
#include "bytestreamutils.h"
|
||||
|
||||
#include "model.h"
|
||||
#include "ident.h"
|
||||
#include "mdlnormals.h"
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
.MD2 triangle model file format
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
#define MD2_NUMVERTEXNORMALS 162
|
||||
#define MD2_MAX_SKINNAME 64
|
||||
|
||||
const unsigned char MD2_IDENT[4] = { 'I', 'D', 'P', '2', };
|
||||
#define MD2_VERSION 8
|
||||
|
||||
#define MD2_MAX_TRIANGLES 4096
|
||||
#define MD2_MAX_VERTS 2048
|
||||
#define MD2_MAX_FRAMES 512
|
||||
#define MD2_MAX_MD2SKINS 32
|
||||
#define MD2_MAX_SKINNAME 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short s;
|
||||
short t;
|
||||
} md2St_t;
|
||||
|
||||
void istream_read_md2St(PointerInputStream& inputStream, md2St_t& st)
|
||||
{
|
||||
st.s = istream_read_int16_le(inputStream);
|
||||
st.t = istream_read_int16_le(inputStream);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short index_xyz[3];
|
||||
short index_st[3];
|
||||
} md2Triangle_t;
|
||||
|
||||
void istream_read_md2Triangle(PointerInputStream& inputStream, md2Triangle_t& triangle)
|
||||
{
|
||||
triangle.index_xyz[0] = istream_read_int16_le(inputStream);
|
||||
triangle.index_xyz[1] = istream_read_int16_le(inputStream);
|
||||
triangle.index_xyz[2] = istream_read_int16_le(inputStream);
|
||||
triangle.index_st[0] = istream_read_int16_le(inputStream);
|
||||
triangle.index_st[1] = istream_read_int16_le(inputStream);
|
||||
triangle.index_st[2] = istream_read_int16_le(inputStream);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte v[3]; // scaled byte to fit in frame mins/maxs
|
||||
byte lightnormalindex;
|
||||
} md2XyzNormal_t;
|
||||
|
||||
void istream_read_md2XyzNormal(PointerInputStream& inputStream, md2XyzNormal_t& xyz)
|
||||
{
|
||||
inputStream.read(xyz.v, 3);
|
||||
inputStream.read(&xyz.lightnormalindex, 1);
|
||||
}
|
||||
|
||||
#define MD2_XYZNORMAL_V0 0
|
||||
#define MD2_XYZNORMAL_V1 1
|
||||
#define MD2_XYZNORMAL_V2 2
|
||||
#define MD2_XYZNORMAL_LNI 3
|
||||
#define MD2_XYZNORMAL_SIZE 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float scale[3]; // multiply byte verts by this
|
||||
float translate[3]; // then add this
|
||||
char name[16]; // frame name from grabbing
|
||||
md2XyzNormal_t verts[1]; // variable sized
|
||||
} md2Frame_t;
|
||||
|
||||
void istream_read_md2Frame(PointerInputStream& inputStream, md2Frame_t& frame)
|
||||
{
|
||||
frame.scale[0] = istream_read_float32_le(inputStream);
|
||||
frame.scale[1] = istream_read_float32_le(inputStream);
|
||||
frame.scale[2] = istream_read_float32_le(inputStream);
|
||||
frame.translate[0] = istream_read_float32_le(inputStream);
|
||||
frame.translate[1] = istream_read_float32_le(inputStream);
|
||||
frame.translate[2] = istream_read_float32_le(inputStream);
|
||||
inputStream.read(reinterpret_cast<unsigned char*>(frame.name), 16);
|
||||
}
|
||||
|
||||
|
||||
// the glcmd format:
|
||||
// a positive integer starts a tristrip command, followed by that many
|
||||
// vertex structures.
|
||||
// a negative integer starts a trifan command, followed by -x vertexes
|
||||
// a zero indicates the end of the command list.
|
||||
// a vertex consists of a floating point s, a floating point t,
|
||||
// and an integer vertex index.
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char ident[4];
|
||||
int version;
|
||||
|
||||
int skinwidth;
|
||||
int skinheight;
|
||||
int framesize; // byte size of each frame
|
||||
|
||||
int num_skins;
|
||||
int num_xyz;
|
||||
int num_st; // greater than num_xyz for seams
|
||||
int num_tris;
|
||||
int num_glcmds; // dwords in strip/fan command list
|
||||
int num_frames;
|
||||
|
||||
int ofs_skins; // each skin is a MAX_SKINNAME string
|
||||
int ofs_st; // byte offset from start for md2St_t
|
||||
int ofs_tris; // offset for md2triangle_t
|
||||
int ofs_frames; // offset for first md2Frame_t
|
||||
int ofs_glcmds;
|
||||
int ofs_end; // end of file
|
||||
|
||||
} md2Header_t;
|
||||
|
||||
void istream_read_md2Header(PointerInputStream& inputStream, md2Header_t& header)
|
||||
{
|
||||
inputStream.read(header.ident, 4);
|
||||
header.version = istream_read_int32_le(inputStream);
|
||||
header.skinwidth = istream_read_int32_le(inputStream);
|
||||
header.skinheight = istream_read_int32_le(inputStream);
|
||||
header.framesize = istream_read_int32_le(inputStream);
|
||||
header.num_skins = istream_read_int32_le(inputStream);
|
||||
header.num_xyz = istream_read_int32_le(inputStream);
|
||||
header.num_st = istream_read_int32_le(inputStream);
|
||||
header.num_tris = istream_read_int32_le(inputStream);
|
||||
header.num_glcmds = istream_read_int32_le(inputStream);
|
||||
header.num_frames = istream_read_int32_le(inputStream);
|
||||
header.ofs_skins = istream_read_int32_le(inputStream);
|
||||
header.ofs_st = istream_read_int32_le(inputStream);
|
||||
header.ofs_tris = istream_read_int32_le(inputStream);
|
||||
header.ofs_frames = istream_read_int32_le(inputStream);
|
||||
header.ofs_glcmds = istream_read_int32_le(inputStream);
|
||||
header.ofs_end = istream_read_int32_le(inputStream);
|
||||
}
|
||||
|
||||
|
||||
ArbitraryMeshVertex MD2Vertex_construct(const md2Header_t* pHeader, const md2Frame_t* pFrame, const md2XyzNormal_t* xyz, const md2St_t* st)
|
||||
{
|
||||
return ArbitraryMeshVertex(
|
||||
Vertex3f(
|
||||
xyz->v[0] * pFrame->scale[0] + pFrame->translate[0],
|
||||
xyz->v[1] * pFrame->scale[1] + pFrame->translate[1],
|
||||
xyz->v[2] * pFrame->scale[2] + pFrame->translate[2]
|
||||
),
|
||||
Normal3f(
|
||||
g_mdl_normals[xyz->lightnormalindex][0],
|
||||
g_mdl_normals[xyz->lightnormalindex][1],
|
||||
g_mdl_normals[xyz->lightnormalindex][2]
|
||||
),
|
||||
TexCoord2f(
|
||||
(float)st->s / pHeader->skinwidth,
|
||||
(float)st->t / pHeader->skinheight
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void MD2Surface_read(Surface& surface, const byte* buffer)
|
||||
{
|
||||
md2Header_t header;
|
||||
{
|
||||
PointerInputStream inputStream(buffer);
|
||||
istream_read_md2Header(inputStream, header);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
md2Frame_t frame;
|
||||
PointerInputStream frameStream(buffer + header.ofs_frames);
|
||||
istream_read_md2Frame(frameStream, frame);
|
||||
|
||||
|
||||
surface.indices().reserve(header.num_tris * 3);
|
||||
|
||||
Array<md2XyzNormal_t> md2Xyz(header.num_xyz);
|
||||
for(Array<md2XyzNormal_t>::iterator i = md2Xyz.begin(); i != md2Xyz.end(); ++i)
|
||||
{
|
||||
istream_read_md2XyzNormal(frameStream, *i);
|
||||
}
|
||||
|
||||
Array<md2St_t> md2St(header.num_st);
|
||||
PointerInputStream stStream(buffer + header.ofs_st);
|
||||
for(Array<md2St_t>::iterator i = md2St.begin(); i != md2St.end(); ++i)
|
||||
{
|
||||
istream_read_md2St(stStream, *i);
|
||||
}
|
||||
|
||||
UniqueVertexBuffer<ArbitraryMeshVertex> inserter(surface.vertices());
|
||||
inserter.reserve(header.num_st);
|
||||
|
||||
PointerInputStream triangleStream(buffer + header.ofs_tris);
|
||||
for(int i = 0; i < header.num_tris; ++i)
|
||||
{
|
||||
md2Triangle_t triangle;
|
||||
istream_read_md2Triangle(triangleStream, triangle);
|
||||
surface.indices().insert(inserter.insert(MD2Vertex_construct(&header, &frame, &md2Xyz[triangle.index_xyz[0]], &md2St[triangle.index_st[0]])));
|
||||
surface.indices().insert(inserter.insert(MD2Vertex_construct(&header, &frame, &md2Xyz[triangle.index_xyz[1]], &md2St[triangle.index_st[1]])));
|
||||
surface.indices().insert(inserter.insert(MD2Vertex_construct(&header, &frame, &md2Xyz[triangle.index_xyz[2]], &md2St[triangle.index_st[2]])));
|
||||
}
|
||||
}
|
||||
|
||||
char skinname[MD2_MAX_SKINNAME];
|
||||
PointerInputStream inputStream(buffer + header.ofs_skins);
|
||||
inputStream.read(reinterpret_cast<byte*>(skinname), MD2_MAX_SKINNAME);
|
||||
surface.setShader(skinname);
|
||||
surface.updateAABB();
|
||||
}
|
||||
|
||||
void MD2Model_read(Model& model, const byte* buffer)
|
||||
{
|
||||
MD2Surface_read(model.newSurface(), buffer);
|
||||
model.updateAABB();
|
||||
}
|
||||
|
||||
scene::Node& MD2Model_new(const byte* buffer)
|
||||
{
|
||||
ModelNode* modelNode = new ModelNode();
|
||||
MD2Model_read(modelNode->model(), buffer);
|
||||
return modelNode->node();
|
||||
}
|
||||
|
||||
scene::Node& MD2Model_default()
|
||||
{
|
||||
ModelNode* modelNode = new ModelNode();
|
||||
Model_constructNull(modelNode->model());
|
||||
return modelNode->node();
|
||||
}
|
||||
|
||||
scene::Node& MD2Model_fromBuffer(unsigned char* buffer)
|
||||
{
|
||||
if (!ident_equal(buffer, MD2_IDENT))
|
||||
{
|
||||
globalErrorStream() << "MD2 read error: incorrect ident\n";
|
||||
return MD2Model_default();
|
||||
}
|
||||
else
|
||||
{
|
||||
return MD2Model_new(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
scene::Node& loadMD2Model(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return MD2Model_fromBuffer(buffer.buffer);
|
||||
}
|
||||
30
plugins/md3model/md2.h
Normal file
30
plugins/md3model/md2.h
Normal file
@@ -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_MD2_H)
|
||||
#define INCLUDED_MD2_H
|
||||
|
||||
namespace scene { class Node; }
|
||||
class ArchiveFile;
|
||||
scene::Node& loadMD2Model(ArchiveFile& file);
|
||||
|
||||
|
||||
#endif
|
||||
340
plugins/md3model/md3.cpp
Normal file
340
plugins/md3model/md3.cpp
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
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 "md3.h"
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "imodel.h"
|
||||
|
||||
#include "imagelib.h"
|
||||
#include "bytestreamutils.h"
|
||||
|
||||
#include "model.h"
|
||||
#include "ident.h"
|
||||
#include "md3normals.h"
|
||||
|
||||
// the maximum size of game reletive pathnames
|
||||
#define MAX_QPATH 64
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
.MD3 triangle model file format
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
const unsigned char MD3_IDENT[4] = { 'I', 'D', 'P', '3', };
|
||||
#define MD3_VERSION 15
|
||||
|
||||
// limits
|
||||
#define MD3_MAX_LODS 4
|
||||
#define MD3_MAX_TRIANGLES 8192 // per surface
|
||||
#define MD3_MAX_VERTS 4096 // per surface
|
||||
#define MD3_MAX_SHADERS 256 // per surface
|
||||
#define MD3_MAX_FRAMES 1024 // per model
|
||||
#define MD3_MAX_SURFACES 32 // per model
|
||||
#define MD3_MAX_TAGS 16 // per frame
|
||||
|
||||
// vertex scales
|
||||
#define MD3_XYZ_SCALE (1.f / 64)
|
||||
|
||||
typedef float float3[3];
|
||||
|
||||
void istream_read_float3(PointerInputStream& inputStream, float3 f)
|
||||
{
|
||||
f[0] = istream_read_float32_le(inputStream);
|
||||
f[1] = istream_read_float32_le(inputStream);
|
||||
f[2] = istream_read_float32_le(inputStream);
|
||||
}
|
||||
|
||||
typedef struct md3Frame_s {
|
||||
float3 bounds[2];
|
||||
float3 localOrigin;
|
||||
float radius;
|
||||
char name[16];
|
||||
} md3Frame_t;
|
||||
|
||||
void istream_read_md3Frame(PointerInputStream& inputStream, md3Frame_t& frame)
|
||||
{
|
||||
istream_read_float3(inputStream, frame.bounds[0]);
|
||||
istream_read_float3(inputStream, frame.bounds[1]);
|
||||
istream_read_float3(inputStream, frame.localOrigin);
|
||||
frame.radius = istream_read_float32_le(inputStream);
|
||||
inputStream.read(reinterpret_cast<unsigned char*>(frame.name), 16);
|
||||
}
|
||||
|
||||
typedef struct md3Tag_s {
|
||||
char name[MAX_QPATH]; // tag name
|
||||
float3 origin;
|
||||
float3 axis[3];
|
||||
} md3Tag_t;
|
||||
|
||||
void istream_read_md3Shader(PointerInputStream& inputStream, md3Tag_t& tag)
|
||||
{
|
||||
inputStream.read(reinterpret_cast<unsigned char*>(tag.name), MAX_QPATH);
|
||||
istream_read_float3(inputStream, tag.origin);
|
||||
istream_read_float3(inputStream, tag.axis[0]);
|
||||
istream_read_float3(inputStream, tag.axis[1]);
|
||||
istream_read_float3(inputStream, tag.axis[2]);
|
||||
}
|
||||
|
||||
/*
|
||||
** md3Surface_t
|
||||
**
|
||||
** CHUNK SIZE
|
||||
** header sizeof( md3Surface_t )
|
||||
** shaders sizeof( md3Shader_t ) * numShaders
|
||||
** triangles[0] sizeof( md3Triangle_t ) * numTriangles
|
||||
** st sizeof( md3St_t ) * numVerts
|
||||
** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames
|
||||
*/
|
||||
typedef struct {
|
||||
char ident[4]; //
|
||||
|
||||
char name[MAX_QPATH]; // polyset name
|
||||
|
||||
int flags;
|
||||
int numFrames; // all surfaces in a model should have the same
|
||||
|
||||
int numShaders; // all surfaces in a model should have the same
|
||||
int numVerts;
|
||||
|
||||
int numTriangles;
|
||||
int ofsTriangles;
|
||||
|
||||
int ofsShaders; // offset from start of md3Surface_t
|
||||
int ofsSt; // texture coords are common for all frames
|
||||
int ofsXyzNormals; // numVerts * numFrames
|
||||
|
||||
int ofsEnd; // next surface follows
|
||||
} md3Surface_t;
|
||||
|
||||
void istream_read_md3Surface(PointerInputStream& inputStream, md3Surface_t& surface)
|
||||
{
|
||||
inputStream.read(reinterpret_cast<unsigned char*>(surface.ident), 4);
|
||||
inputStream.read(reinterpret_cast<unsigned char*>(surface.name), MAX_QPATH);
|
||||
surface.flags = istream_read_int32_le(inputStream);
|
||||
surface.numFrames = istream_read_int32_le(inputStream);
|
||||
surface.numShaders = istream_read_int32_le(inputStream);
|
||||
surface.numVerts = istream_read_int32_le(inputStream);
|
||||
surface.numTriangles = istream_read_int32_le(inputStream);
|
||||
surface.ofsTriangles = istream_read_int32_le(inputStream);
|
||||
surface.ofsShaders = istream_read_int32_le(inputStream);
|
||||
surface.ofsSt = istream_read_int32_le(inputStream);
|
||||
surface.ofsXyzNormals = istream_read_int32_le(inputStream);
|
||||
surface.ofsEnd = istream_read_int32_le(inputStream);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_QPATH];
|
||||
int shaderIndex; // for in-game use
|
||||
} md3Shader_t;
|
||||
|
||||
void istream_read_md3Shader(PointerInputStream& inputStream, md3Shader_t& shader)
|
||||
{
|
||||
inputStream.read(reinterpret_cast<unsigned char*>(shader.name), MAX_QPATH);
|
||||
shader.shaderIndex = istream_read_int32_le(inputStream);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int indexes[3];
|
||||
} md3Triangle_t;
|
||||
|
||||
void istream_read_md3Triangle(PointerInputStream& inputStream, md3Triangle_t& triangle)
|
||||
{
|
||||
triangle.indexes[0] = istream_read_int32_le(inputStream);
|
||||
triangle.indexes[1] = istream_read_int32_le(inputStream);
|
||||
triangle.indexes[2] = istream_read_int32_le(inputStream);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
float st[2];
|
||||
} md3St_t;
|
||||
|
||||
void istream_read_md3St(PointerInputStream& inputStream, md3St_t& st)
|
||||
{
|
||||
st.st[0] = istream_read_float32_le(inputStream);
|
||||
st.st[1] = istream_read_float32_le(inputStream);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
short xyz[3];
|
||||
short normal;
|
||||
} md3XyzNormal_t;
|
||||
|
||||
void istream_read_md3XyzNormal(PointerInputStream& inputStream, md3XyzNormal_t& xyz)
|
||||
{
|
||||
xyz.xyz[0] = istream_read_int16_le(inputStream);
|
||||
xyz.xyz[1] = istream_read_int16_le(inputStream);
|
||||
xyz.xyz[2] = istream_read_int16_le(inputStream);
|
||||
xyz.normal = istream_read_int16_le(inputStream);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char ident[4];
|
||||
int version;
|
||||
|
||||
char name[MAX_QPATH]; // model name
|
||||
|
||||
int flags;
|
||||
|
||||
int numFrames;
|
||||
int numTags;
|
||||
int numSurfaces;
|
||||
|
||||
int numSkins;
|
||||
|
||||
int ofsFrames; // offset for first frame
|
||||
int ofsTags; // numFrames * numTags
|
||||
int ofsSurfaces; // first surface, others follow
|
||||
|
||||
int ofsEnd; // end of file
|
||||
} md3Header_t;
|
||||
|
||||
void istream_read_md3Header(PointerInputStream& inputStream, md3Header_t& header)
|
||||
{
|
||||
inputStream.read(reinterpret_cast<unsigned char*>(header.ident), 4);
|
||||
header.version = istream_read_int32_le(inputStream);
|
||||
inputStream.read(reinterpret_cast<unsigned char*>(header.name), MAX_QPATH);
|
||||
header.flags = istream_read_int32_le(inputStream);
|
||||
header.numFrames = istream_read_int32_le(inputStream);
|
||||
header.numTags = istream_read_int32_le(inputStream);
|
||||
header.numSurfaces = istream_read_int32_le(inputStream);
|
||||
header.numSkins = istream_read_int32_le(inputStream);
|
||||
header.ofsFrames = istream_read_int32_le(inputStream);
|
||||
header.ofsTags = istream_read_int32_le(inputStream);
|
||||
header.ofsSurfaces = istream_read_int32_le(inputStream);
|
||||
header.ofsEnd = istream_read_int32_le(inputStream);
|
||||
}
|
||||
|
||||
int MD3Surface_read(Surface& surface, unsigned char* buffer)
|
||||
{
|
||||
md3Surface_t md3Surface;
|
||||
{
|
||||
PointerInputStream inputStream(buffer);
|
||||
istream_read_md3Surface(inputStream, md3Surface);
|
||||
}
|
||||
|
||||
{
|
||||
surface.vertices().reserve(md3Surface.numVerts);
|
||||
|
||||
PointerInputStream xyzNormalStream(buffer + md3Surface.ofsXyzNormals);
|
||||
PointerInputStream stStream(buffer + md3Surface.ofsSt);
|
||||
|
||||
// read verts into vertex array - xyz, st, normal
|
||||
for(int i = 0; i < md3Surface.numVerts; i++)
|
||||
{
|
||||
md3XyzNormal_t md3Xyz;
|
||||
istream_read_md3XyzNormal(xyzNormalStream, md3Xyz);
|
||||
|
||||
md3St_t md3St;
|
||||
istream_read_md3St(stStream, md3St);
|
||||
|
||||
surface.vertices().push_back(
|
||||
ArbitraryMeshVertex(
|
||||
Vertex3f( md3Xyz.xyz[0] * MD3_XYZ_SCALE, md3Xyz.xyz[1] * MD3_XYZ_SCALE, md3Xyz.xyz[2] * MD3_XYZ_SCALE),
|
||||
DecodeNormal(reinterpret_cast<byte*>(&md3Xyz.normal)),
|
||||
TexCoord2f(md3St.st[0], md3St.st[1])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
surface.indices().reserve(md3Surface.numTriangles * 3);
|
||||
|
||||
PointerInputStream inputStream(buffer + md3Surface.ofsTriangles);
|
||||
for(int i = 0; i < md3Surface.numTriangles; i++)
|
||||
{
|
||||
md3Triangle_t md3Triangle;
|
||||
istream_read_md3Triangle(inputStream, md3Triangle);
|
||||
surface.indices().insert(md3Triangle.indexes[0]);
|
||||
surface.indices().insert(md3Triangle.indexes[1]);
|
||||
surface.indices().insert(md3Triangle.indexes[2]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
md3Shader_t md3Shader;
|
||||
{
|
||||
PointerInputStream inputStream(buffer + md3Surface.ofsShaders);
|
||||
istream_read_md3Shader(inputStream, md3Shader);
|
||||
}
|
||||
surface.setShader(md3Shader.name);
|
||||
}
|
||||
|
||||
surface.updateAABB();
|
||||
|
||||
return md3Surface.ofsEnd;
|
||||
}
|
||||
|
||||
void MD3Model_read(Model& model, unsigned char* buffer)
|
||||
{
|
||||
md3Header_t md3Header;
|
||||
{
|
||||
PointerInputStream inputStream(buffer);
|
||||
istream_read_md3Header(inputStream, md3Header);
|
||||
}
|
||||
|
||||
unsigned char* surfacePosition = buffer + md3Header.ofsSurfaces;
|
||||
|
||||
for(int i = 0; i != md3Header.numSurfaces; ++i)
|
||||
{
|
||||
surfacePosition += MD3Surface_read(model.newSurface(), surfacePosition);
|
||||
}
|
||||
|
||||
model.updateAABB();
|
||||
}
|
||||
|
||||
scene::Node& MD3Model_new(unsigned char* buffer)
|
||||
{
|
||||
ModelNode* modelNode = new ModelNode();
|
||||
MD3Model_read(modelNode->model(), buffer);
|
||||
return modelNode->node();
|
||||
}
|
||||
|
||||
scene::Node& MD3Model_default()
|
||||
{
|
||||
ModelNode* modelNode = new ModelNode();
|
||||
Model_constructNull(modelNode->model());
|
||||
return modelNode->node();
|
||||
}
|
||||
|
||||
scene::Node& MD3Model_fromBuffer(unsigned char* buffer)
|
||||
{
|
||||
if (!ident_equal(buffer, MD3_IDENT))
|
||||
{
|
||||
globalErrorStream() << "MD3 read error: incorrect ident\n";
|
||||
return MD3Model_default();
|
||||
}
|
||||
else
|
||||
{
|
||||
return MD3Model_new(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
scene::Node& loadMD3Model(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return MD3Model_fromBuffer(buffer.buffer);
|
||||
}
|
||||
|
||||
29
plugins/md3model/md3.h
Normal file
29
plugins/md3model/md3.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
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_MD3_H)
|
||||
#define INCLUDED_MD3_H
|
||||
|
||||
namespace scene { class Node; }
|
||||
class ArchiveFile;
|
||||
scene::Node& loadMD3Model(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
218
plugins/md3model/md3model.dsp
Normal file
218
plugins/md3model/md3model.dsp
Normal file
@@ -0,0 +1,218 @@
|
||||
# Microsoft Developer Studio Project File - Name="md3model" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=md3model - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "md3model.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "md3model.mak" CFG="md3model - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "md3model - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "md3model - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "md3model"
|
||||
# PROP Scc_LocalPath "..\.."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "md3model - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAP_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\common" /I "..\..\libs" /I "..\..\..\libxml2\include\\" /I "..\..\..\STLPort\stlport" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAP_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD RSC /l 0x40c /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 mathlib.lib glib-2.0.lib /nologo /dll /machine:I386 /def:".\md3model.def" /libpath:"..\..\libs\mathlib\release" /libpath:"..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Release\md3model.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "md3model - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAP_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\shared" /I "..\common" /I "..\..\libs" /I "..\..\..\libxml2\include" /I "..\..\..\STLPort\stlport" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "../../../gtk2-win32/lib/glib-2.0/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAP_EXPORTS" /FR /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x40c /d "_DEBUG"
|
||||
# ADD RSC /l 0x40c /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 mathlib.lib glib-2.0.lib /nologo /dll /debug /machine:I386 /def:".\md3model.def" /pdbtype:sept /libpath:"..\..\libs\mathlib\debug" /libpath:"..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Debug\md3model.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "md3model - Win32 Release"
|
||||
# Name "md3model - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md2.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md3.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md3model.def
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mdc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mdl.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mdlimage.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Group "API"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\ifilesystem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\igl.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\imodel.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\ishaders.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\isurface.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\qerplugin.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\qertypes.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ident.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md3.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md3normals.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mdc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mdl.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mdlnormals.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\model.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Conscript
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
23
plugins/md3model/md3normals.cpp
Normal file
23
plugins/md3model/md3normals.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
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 "md3normals.h"
|
||||
|
||||
45
plugins/md3model/md3normals.h
Normal file
45
plugins/md3model/md3normals.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
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_MD3NORMALS_H)
|
||||
#define INCLUDED_MD3NORMALS_H
|
||||
|
||||
#include "render.h"
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
// latitude-longditude to normal conversion
|
||||
inline Normal3f DecodeNormal(const byte bytes[2])
|
||||
{
|
||||
double lat = bytes[0] * (c_pi/128.0);
|
||||
double lng = bytes[1] * (c_pi/128.0);
|
||||
|
||||
return Normal3f(
|
||||
static_cast<float>(cos(lat) * sin(lng)),
|
||||
static_cast<float>(sin(lat) * sin(lng)),
|
||||
static_cast<float>(cos(lng))
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
454
plugins/md3model/md5.cpp
Normal file
454
plugins/md3model/md5.cpp
Normal file
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
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 "md5.h"
|
||||
|
||||
#include "iscriplib.h"
|
||||
#include "imodel.h"
|
||||
|
||||
#include "archivelib.h"
|
||||
#include "stringio.h"
|
||||
|
||||
#include "model.h"
|
||||
|
||||
#define MD5_RETURN_FALSE_IF_FAIL(expression) if(!(expression)) { globalErrorStream() << "md5 parse failed: " #expression "\n"; return false; } else
|
||||
|
||||
bool MD5_parseToken(Tokeniser& tokeniser, const char* string)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
MD5_RETURN_FALSE_IF_FAIL(token != 0);
|
||||
return string_equal(token, string);
|
||||
}
|
||||
|
||||
bool MD5_parseFloat(Tokeniser& tokeniser, float& f)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
MD5_RETURN_FALSE_IF_FAIL(token != 0);
|
||||
return string_parse_float(token, f);
|
||||
}
|
||||
|
||||
bool MD5_parseString(Tokeniser& tokeniser, const char*& s)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
MD5_RETURN_FALSE_IF_FAIL(token != 0);
|
||||
s = token;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MD5_parseInteger(Tokeniser& tokeniser, int& i)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
MD5_RETURN_FALSE_IF_FAIL(token != 0);
|
||||
return string_parse_int(token, i);
|
||||
}
|
||||
|
||||
bool MD5_parseSize(Tokeniser& tokeniser, std::size_t& i)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
MD5_RETURN_FALSE_IF_FAIL(token != 0);
|
||||
return string_parse_size(token, i);
|
||||
}
|
||||
|
||||
bool MD5_parseVector3(Tokeniser& tokeniser, Vector3& v)
|
||||
{
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "("));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.x()));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.y()));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.z()));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, ")"));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Element>
|
||||
inline Element float_squared(const Element& f)
|
||||
{
|
||||
return f * f;
|
||||
}
|
||||
|
||||
class MD5Joint
|
||||
{
|
||||
public:
|
||||
int parent;
|
||||
Vector3 position;
|
||||
Vector4 rotation;
|
||||
};
|
||||
|
||||
typedef Array<MD5Joint> MD5Joints;
|
||||
|
||||
class MD5Vert
|
||||
{
|
||||
public:
|
||||
std::size_t index;
|
||||
float u;
|
||||
float v;
|
||||
std::size_t weight_index;
|
||||
std::size_t weight_count;
|
||||
};
|
||||
|
||||
typedef Array<MD5Vert> MD5Verts;
|
||||
|
||||
class MD5Tri
|
||||
{
|
||||
public:
|
||||
std::size_t index;
|
||||
std::size_t a;
|
||||
std::size_t b;
|
||||
std::size_t c;
|
||||
};
|
||||
|
||||
typedef Array<MD5Tri> MD5Tris;
|
||||
|
||||
class MD5Weight
|
||||
{
|
||||
public:
|
||||
std::size_t index;
|
||||
std::size_t joint;
|
||||
float t;
|
||||
Vector3 v;
|
||||
};
|
||||
|
||||
typedef Array<MD5Weight> MD5Weights;
|
||||
|
||||
typedef float MD5Component;
|
||||
typedef Array<MD5Component> MD5Components;
|
||||
|
||||
class MD5Frame
|
||||
{
|
||||
public:
|
||||
MD5Components m_components;
|
||||
};
|
||||
|
||||
typedef Array<MD5Weight> MD5Weights;
|
||||
|
||||
bool MD5_parseVersion(Tokeniser& tokeniser)
|
||||
{
|
||||
{
|
||||
const char* versionKey = tokeniser.getToken();
|
||||
if(versionKey == 0 || !string_equal(versionKey, "MD5Version"))
|
||||
{
|
||||
globalErrorStream() << "not a valid md5 file\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
{
|
||||
const char* versionValue = tokeniser.getToken();
|
||||
if(versionValue == 0 || !string_equal(versionValue, "10"))
|
||||
{
|
||||
globalErrorStream() << "only md5 version 10 supported\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MD5Anim_parse(Tokeniser& tokeniser)
|
||||
{
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseVersion(tokeniser));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "commandline"));
|
||||
const char* commandline;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, commandline));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numFrames"));
|
||||
std::size_t numFrames;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numFrames));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numJoints"));
|
||||
std::size_t numJoints;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numJoints));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "frameRate"));
|
||||
std::size_t frameRate;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, frameRate));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numAnimatedComponents"));
|
||||
std::size_t numAnimatedComponents;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numAnimatedComponents));
|
||||
tokeniser.nextLine();
|
||||
|
||||
// parse heirarchy
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "hierarchy"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(std::size_t i = 0; i < numJoints; ++i)
|
||||
{
|
||||
const char* name;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, name));
|
||||
int parent;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, parent));
|
||||
std::size_t flags;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, flags));
|
||||
std::size_t index;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, index));
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
// parse bounds
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "bounds"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(std::size_t i = 0; i < numFrames; ++i)
|
||||
{
|
||||
Vector3 mins;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, mins));
|
||||
Vector3 maxs;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, maxs));
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
// parse baseframe
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "baseframe"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(std::size_t i = 0; i < numJoints; ++i)
|
||||
{
|
||||
Vector3 position;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, position));
|
||||
Vector3 rotation;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, rotation));
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
// parse frames
|
||||
for(std::size_t i = 0; i < numFrames; ++i)
|
||||
{
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "frame"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(std::size_t i = 0; i < numAnimatedComponents; ++i)
|
||||
{
|
||||
float component;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, component));
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MD5Model_parse(Model& model, Tokeniser& tokeniser)
|
||||
{
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseVersion(tokeniser));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "commandline"));
|
||||
const char* commandline;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, commandline));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numJoints"));
|
||||
std::size_t numJoints;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numJoints));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numMeshes"));
|
||||
std::size_t numMeshes;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numMeshes));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5Joints joints(numJoints);
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "joints"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(MD5Joints::iterator i = joints.begin(); i != joints.end(); ++i)
|
||||
{
|
||||
const char* jointName;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, jointName));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, (*i).parent));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*i).position));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*i).rotation));
|
||||
(*i).rotation.w() = -static_cast<float>(sqrt(1.0f - (float_squared((*i).rotation.x()) + float_squared((*i).rotation.y()) + float_squared((*i).rotation.z()))));
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(std::size_t i = 0; i < numMeshes; ++i)
|
||||
{
|
||||
Surface& surface = model.newSurface();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "mesh"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "shader"));
|
||||
const char* shader;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, shader));
|
||||
surface.setShader(shader);
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numverts"));
|
||||
std::size_t numVerts;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numVerts));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5Verts verts(numVerts);
|
||||
|
||||
for(MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j)
|
||||
{
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "vert"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index));
|
||||
MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - verts.begin()));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "("));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).u));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).v));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, ")"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_index));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_count));
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numtris"));
|
||||
std::size_t numTris;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numTris));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5Tris tris(numTris);
|
||||
|
||||
for(MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j)
|
||||
{
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "tri"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index));
|
||||
MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - tris.begin()));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).a));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).b));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).c));
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numweights"));
|
||||
std::size_t numWeights;
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numWeights));
|
||||
tokeniser.nextLine();
|
||||
|
||||
MD5Weights weights(numWeights);
|
||||
|
||||
for(MD5Weights::iterator j = weights.begin(); j != weights.end(); ++j)
|
||||
{
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "weight"));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index));
|
||||
MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - weights.begin()));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).joint));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).t));
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*j).v));
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}"));
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j)
|
||||
{
|
||||
MD5Vert& vert = (*j);
|
||||
|
||||
Vector3 skinned(0, 0, 0);
|
||||
for(std::size_t k = 0; k != vert.weight_count; ++k)
|
||||
{
|
||||
MD5Weight& weight = weights[vert.weight_index + k];
|
||||
MD5Joint& joint = joints[weight.joint];
|
||||
|
||||
skinned += (quaternion_transformed_point(joint.rotation, weight.v) + joint.position) * weight.t;
|
||||
}
|
||||
|
||||
surface.vertices().push_back(ArbitraryMeshVertex(vertex3f_for_vector3(skinned), Normal3f(0, 0, 0), TexCoord2f(vert.u, vert.v)));
|
||||
}
|
||||
|
||||
for(MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j)
|
||||
{
|
||||
MD5Tri& tri = (*j);
|
||||
surface.indices().insert(RenderIndex(tri.a));
|
||||
surface.indices().insert(RenderIndex(tri.b));
|
||||
surface.indices().insert(RenderIndex(tri.c));
|
||||
}
|
||||
|
||||
for(Surface::indices_t::iterator j = surface.indices().begin(); j != surface.indices().end(); j += 3)
|
||||
{
|
||||
ArbitraryMeshVertex& a = surface.vertices()[*(j + 0)];
|
||||
ArbitraryMeshVertex& b = surface.vertices()[*(j + 1)];
|
||||
ArbitraryMeshVertex& c = surface.vertices()[*(j + 2)];
|
||||
Vector3 weightedNormal(
|
||||
vector3_cross(
|
||||
reinterpret_cast<const Vector3&>(c.vertex) - reinterpret_cast<const Vector3&>(a.vertex),
|
||||
reinterpret_cast<const Vector3&>(b.vertex) - reinterpret_cast<const Vector3&>(a.vertex)
|
||||
)
|
||||
);
|
||||
reinterpret_cast<Vector3&>(a.normal) += weightedNormal;
|
||||
reinterpret_cast<Vector3&>(b.normal) += weightedNormal;
|
||||
reinterpret_cast<Vector3&>(c.normal) += weightedNormal;
|
||||
}
|
||||
|
||||
for(Surface::vertices_t::iterator j = surface.vertices().begin(); j != surface.vertices().end(); ++j)
|
||||
{
|
||||
vector3_normalise(reinterpret_cast<Vector3&>((*j).normal));
|
||||
}
|
||||
|
||||
surface.updateAABB();
|
||||
}
|
||||
|
||||
model.updateAABB();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MD5Model_construct(Model& model, TextInputStream& inputStream)
|
||||
{
|
||||
Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(inputStream);
|
||||
MD5Model_parse(model, tokeniser);
|
||||
tokeniser.release();
|
||||
}
|
||||
|
||||
scene::Node& MD5Model_new(TextInputStream& inputStream)
|
||||
{
|
||||
ModelNode* modelNode = new ModelNode();
|
||||
MD5Model_construct(modelNode->model(), inputStream);
|
||||
return modelNode->node();
|
||||
}
|
||||
|
||||
scene::Node& loadMD5Model(ArchiveFile& file)
|
||||
{
|
||||
BinaryToTextInputStream<InputStream> inputStream(file.getInputStream());
|
||||
return MD5Model_new(inputStream);
|
||||
}
|
||||
29
plugins/md3model/md5.h
Normal file
29
plugins/md3model/md5.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
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_MD5_H)
|
||||
#define INCLUDED_MD5_H
|
||||
|
||||
namespace scene { class Node; }
|
||||
class ArchiveFile;
|
||||
scene::Node& loadMD5Model(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
292
plugins/md3model/mdc.cpp
Normal file
292
plugins/md3model/mdc.cpp
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
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 "mdc.h"
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "imodel.h"
|
||||
|
||||
#include "imagelib.h"
|
||||
#include "bytestreamutils.h"
|
||||
|
||||
#include "model.h"
|
||||
#include "ident.h"
|
||||
#include "md3normals.h"
|
||||
|
||||
|
||||
const unsigned char MDC_IDENT[4] = { 'I', 'D', 'P', 'C', };
|
||||
const float MDC_XYZ_SCALE = 0.015625f;
|
||||
#define MAX_QPATH 64 // max length of a quake game pathname
|
||||
|
||||
typedef float float3[3];
|
||||
|
||||
struct mdcTriangle_t
|
||||
{
|
||||
unsigned int indexes[3]; // not my spelling
|
||||
};
|
||||
|
||||
void istream_read_mdcTriangle(PointerInputStream& inputStream, mdcTriangle_t& triangle)
|
||||
{
|
||||
triangle.indexes[0] = istream_read_uint32_le(inputStream);
|
||||
triangle.indexes[1] = istream_read_uint32_le(inputStream);
|
||||
triangle.indexes[2] = istream_read_uint32_le(inputStream);
|
||||
}
|
||||
|
||||
struct mdcXyzNormal_t
|
||||
{
|
||||
short xyz[3]; // divide by 64
|
||||
short normal; // packed same way as md3
|
||||
};
|
||||
|
||||
void istream_read_mdcXyzNormal(PointerInputStream& inputStream, mdcXyzNormal_t& xyz)
|
||||
{
|
||||
xyz.xyz[0] = istream_read_int16_le(inputStream);
|
||||
xyz.xyz[1] = istream_read_int16_le(inputStream);
|
||||
xyz.xyz[2] = istream_read_int16_le(inputStream);
|
||||
xyz.normal = istream_read_int16_le(inputStream);
|
||||
}
|
||||
|
||||
struct mdcSt_t
|
||||
{
|
||||
float st[2]; // may need to reverse t
|
||||
};
|
||||
|
||||
void istream_read_mdcSt(PointerInputStream& inputStream, mdcSt_t& st)
|
||||
{
|
||||
st.st[0] = istream_read_float32_le(inputStream);
|
||||
st.st[1] = istream_read_float32_le(inputStream);
|
||||
}
|
||||
|
||||
struct mdcShader_t
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
void istream_read_mdcShader(PointerInputStream& inputStream, mdcShader_t& shader)
|
||||
{
|
||||
inputStream.read(reinterpret_cast<byte*>(shader.name), MAX_QPATH);
|
||||
shader.flags = istream_read_uint32_le(inputStream);
|
||||
}
|
||||
|
||||
struct mdcTagName_t
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
};
|
||||
|
||||
struct mdcTagFrame_t
|
||||
{
|
||||
short xyz[3]; // divide by 64
|
||||
short angles[3]; // euler in z x y order... deg = * (360.0 / 32767.0) .. rad = * (PI / 32767.0)
|
||||
};
|
||||
|
||||
struct mdcFrame_t
|
||||
{
|
||||
float3 bboxMin;
|
||||
float3 bboxMax;
|
||||
float3 localOrigin;
|
||||
float radius;
|
||||
char name[16];
|
||||
};
|
||||
|
||||
struct mdcSurface_t
|
||||
{
|
||||
byte ident[4];
|
||||
char name[MAX_QPATH];
|
||||
unsigned int flags;
|
||||
unsigned int numCompFrames;
|
||||
unsigned int numBaseFrames;
|
||||
unsigned int numShaders;
|
||||
unsigned int numVerts;
|
||||
unsigned int numTriangles;
|
||||
unsigned int ofsTriangles;
|
||||
unsigned int ofsShaders;
|
||||
unsigned int ofsSt;
|
||||
unsigned int ofsXyzNormals;
|
||||
unsigned int ofsCompVerts;
|
||||
unsigned int ofsFrameBaseFrames;
|
||||
unsigned int ofsFrameCompFrames;
|
||||
unsigned int ofsEnd;
|
||||
};
|
||||
|
||||
void istream_read_mdcSurface(PointerInputStream& inputStream, mdcSurface_t& surface)
|
||||
{
|
||||
inputStream.read(surface.ident, 4);
|
||||
inputStream.read(reinterpret_cast<byte*>(surface.name), MAX_QPATH);
|
||||
surface.flags = istream_read_uint32_le(inputStream);
|
||||
surface.numCompFrames = istream_read_uint32_le(inputStream);
|
||||
surface.numBaseFrames = istream_read_uint32_le(inputStream);
|
||||
surface.numShaders = istream_read_uint32_le(inputStream);
|
||||
surface.numVerts = istream_read_uint32_le(inputStream);
|
||||
surface.numTriangles = istream_read_uint32_le(inputStream);
|
||||
surface.ofsTriangles = istream_read_uint32_le(inputStream);
|
||||
surface.ofsShaders = istream_read_uint32_le(inputStream);
|
||||
surface.ofsSt = istream_read_uint32_le(inputStream);
|
||||
surface.ofsXyzNormals = istream_read_uint32_le(inputStream);
|
||||
surface.ofsCompVerts = istream_read_uint32_le(inputStream);
|
||||
surface.ofsFrameBaseFrames = istream_read_uint32_le(inputStream);
|
||||
surface.ofsFrameCompFrames = istream_read_uint32_le(inputStream);
|
||||
surface.ofsEnd = istream_read_uint32_le(inputStream);
|
||||
}
|
||||
|
||||
struct mdcHeader_t
|
||||
{
|
||||
byte ident[4];
|
||||
unsigned int version;
|
||||
char name[MAX_QPATH];
|
||||
unsigned int flags;
|
||||
unsigned int numFrames;
|
||||
unsigned int numTags;
|
||||
unsigned int numSurfaces;
|
||||
unsigned int numSkins;
|
||||
unsigned int ofsFrames;
|
||||
unsigned int ofsTagNames;
|
||||
unsigned int ofsTags;
|
||||
unsigned int ofsSurfaces;
|
||||
unsigned int ofsEnd;
|
||||
};
|
||||
|
||||
void istream_read_mdcHeader(PointerInputStream& inputStream, mdcHeader_t& header)
|
||||
{
|
||||
inputStream.read(header.ident, 4);
|
||||
header.version = istream_read_uint32_le(inputStream);
|
||||
inputStream.read(reinterpret_cast<byte*>(header.name), MAX_QPATH);
|
||||
header.flags = istream_read_uint32_le(inputStream);
|
||||
header.numFrames = istream_read_uint32_le(inputStream);
|
||||
header.numTags = istream_read_uint32_le(inputStream);
|
||||
header.numSurfaces = istream_read_uint32_le(inputStream);
|
||||
header.numSkins = istream_read_uint32_le(inputStream);
|
||||
header.ofsFrames = istream_read_uint32_le(inputStream);
|
||||
header.ofsTagNames = istream_read_uint32_le(inputStream);
|
||||
header.ofsTags = istream_read_uint32_le(inputStream);
|
||||
header.ofsSurfaces = istream_read_uint32_le(inputStream);
|
||||
header.ofsEnd = istream_read_uint32_le(inputStream);
|
||||
}
|
||||
|
||||
unsigned int MDCSurface_read(Surface& surface, const byte* buffer)
|
||||
{
|
||||
mdcSurface_t mdcSurface;
|
||||
{
|
||||
PointerInputStream inputStream(buffer);
|
||||
istream_read_mdcSurface(inputStream, mdcSurface);
|
||||
}
|
||||
|
||||
{
|
||||
surface.vertices().reserve(mdcSurface.numVerts);
|
||||
|
||||
PointerInputStream xyzStream(buffer + mdcSurface.ofsXyzNormals);
|
||||
PointerInputStream stStream(buffer + mdcSurface.ofsSt);
|
||||
// read verts into vertex array - xyz, st, normal
|
||||
for(std::size_t i = 0; i < mdcSurface.numVerts; i++)
|
||||
{
|
||||
mdcXyzNormal_t mdcXyzNormal;
|
||||
istream_read_mdcXyzNormal(xyzStream, mdcXyzNormal);
|
||||
mdcSt_t mdcSt;
|
||||
istream_read_mdcSt(stStream, mdcSt);
|
||||
|
||||
surface.vertices().push_back(
|
||||
ArbitraryMeshVertex(
|
||||
Vertex3f( mdcXyzNormal.xyz[0] * MDC_XYZ_SCALE, mdcXyzNormal.xyz[1] * MDC_XYZ_SCALE, mdcXyzNormal.xyz[2] * MDC_XYZ_SCALE),
|
||||
DecodeNormal(reinterpret_cast<byte*>(&mdcXyzNormal.normal)),
|
||||
TexCoord2f(mdcSt.st[0], mdcSt.st[1])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
surface.indices().reserve(mdcSurface.numTriangles * 3);
|
||||
|
||||
PointerInputStream triangleStream(buffer + mdcSurface.ofsTriangles);
|
||||
|
||||
for(std::size_t i = 0; i < mdcSurface.numTriangles; i++)
|
||||
{
|
||||
mdcTriangle_t triangle;
|
||||
istream_read_mdcTriangle(triangleStream, triangle);
|
||||
surface.indices().insert(triangle.indexes[0]);
|
||||
surface.indices().insert(triangle.indexes[1]);
|
||||
surface.indices().insert(triangle.indexes[2]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
mdcShader_t shader;
|
||||
PointerInputStream inputStream(buffer + mdcSurface.ofsShaders);
|
||||
istream_read_mdcShader(inputStream, shader);
|
||||
surface.setShader(shader.name);
|
||||
}
|
||||
|
||||
surface.updateAABB();
|
||||
|
||||
return mdcSurface.ofsEnd;
|
||||
}
|
||||
|
||||
void MDCModel_read(Model& model, const byte* buffer)
|
||||
{
|
||||
mdcHeader_t header;
|
||||
{
|
||||
PointerInputStream inputStream(buffer);
|
||||
istream_read_mdcHeader(inputStream, header);
|
||||
}
|
||||
|
||||
const byte* surfacePosition = buffer + header.ofsSurfaces;
|
||||
|
||||
for(std::size_t i = 0; i < header.numSurfaces; i++)
|
||||
{
|
||||
surfacePosition += MDCSurface_read(model.newSurface(), surfacePosition);
|
||||
}
|
||||
|
||||
model.updateAABB();
|
||||
}
|
||||
|
||||
scene::Node& MDCModel_new(const byte* buffer)
|
||||
{
|
||||
ModelNode* modelNode = new ModelNode();
|
||||
MDCModel_read(modelNode->model(), buffer);
|
||||
return modelNode->node();
|
||||
}
|
||||
|
||||
scene::Node& MDCModel_default()
|
||||
{
|
||||
ModelNode* modelNode = new ModelNode();
|
||||
Model_constructNull(modelNode->model());
|
||||
return modelNode->node();
|
||||
}
|
||||
|
||||
scene::Node& MDCModel_fromBuffer(unsigned char* buffer)
|
||||
{
|
||||
if (!ident_equal(buffer, MDC_IDENT))
|
||||
{
|
||||
globalErrorStream() << "MDC read error: incorrect ident\n";
|
||||
return MDCModel_default();
|
||||
}
|
||||
else
|
||||
{
|
||||
return MDCModel_new(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
scene::Node& loadMDCModel(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return MDCModel_fromBuffer(buffer.buffer);
|
||||
}
|
||||
|
||||
30
plugins/md3model/mdc.h
Normal file
30
plugins/md3model/mdc.h
Normal file
@@ -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_MDC_H)
|
||||
#define INCLUDED_MDC_H
|
||||
|
||||
namespace scene { class Node; }
|
||||
class ArchiveFile;
|
||||
scene::Node& loadMDCModel(ArchiveFile& file);
|
||||
|
||||
|
||||
#endif
|
||||
241
plugins/md3model/mdl.cpp
Normal file
241
plugins/md3model/mdl.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
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 "mdl.h"
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "imodel.h"
|
||||
|
||||
#include "imagelib.h"
|
||||
#include "bytestreamutils.h"
|
||||
|
||||
#include "model.h"
|
||||
#include "ident.h"
|
||||
#include "mdlnormals.h"
|
||||
#include "mdlformat.h"
|
||||
|
||||
void istream_read_mdlHeader(PointerInputStream& inputStream, mdlHeader_t& header)
|
||||
{
|
||||
inputStream.read(header.ident, 4);
|
||||
header.version = istream_read_int32_le(inputStream);
|
||||
header.scale[0] = istream_read_float32_le(inputStream);
|
||||
header.scale[1] = istream_read_float32_le(inputStream);
|
||||
header.scale[2] = istream_read_float32_le(inputStream);
|
||||
header.scale_origin[0] = istream_read_float32_le(inputStream);
|
||||
header.scale_origin[1] = istream_read_float32_le(inputStream);
|
||||
header.scale_origin[2] = istream_read_float32_le(inputStream);
|
||||
header.boundingradius = istream_read_float32_le(inputStream);
|
||||
header.eyeposition[0] = istream_read_float32_le(inputStream);
|
||||
header.eyeposition[1] = istream_read_float32_le(inputStream);
|
||||
header.eyeposition[2] = istream_read_float32_le(inputStream);
|
||||
header.numskins = istream_read_int32_le(inputStream);
|
||||
header.skinwidth = istream_read_int32_le(inputStream);
|
||||
header.skinheight = istream_read_int32_le(inputStream);
|
||||
header.numverts = istream_read_int32_le(inputStream);
|
||||
header.numtris = istream_read_int32_le(inputStream);
|
||||
header.numframes = istream_read_int32_le(inputStream);
|
||||
header.synctype = istream_read_int32_le(inputStream);
|
||||
header.flags = istream_read_int32_le(inputStream);
|
||||
header.size = istream_read_float32_le(inputStream);
|
||||
}
|
||||
|
||||
inline ArbitraryMeshVertex MDLVertex_construct(const mdlHeader_t& header, const mdlXyzNormal_t& xyz, const mdlSt_t& st, bool facesfront)
|
||||
{
|
||||
return ArbitraryMeshVertex(
|
||||
Vertex3f(
|
||||
xyz.v[0] * header.scale[0] + header.scale_origin[0],
|
||||
xyz.v[1] * header.scale[1] + header.scale_origin[1],
|
||||
xyz.v[2] * header.scale[2] + header.scale_origin[2]
|
||||
),
|
||||
Normal3f(
|
||||
g_mdl_normals[xyz.lightnormalindex][0],
|
||||
g_mdl_normals[xyz.lightnormalindex][1],
|
||||
g_mdl_normals[xyz.lightnormalindex][2]
|
||||
),
|
||||
TexCoord2f(
|
||||
((float)st.s / header.skinwidth) + ((st.onseam == MDL_ONSEAM && !facesfront) ? 0.5f : 0.0f),
|
||||
(float)st.t / header.skinheight
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
class mdlVertex_t
|
||||
{
|
||||
public:
|
||||
inline mdlVertex_t(int vertindex, int facesfront)
|
||||
: m_vertindex(vertindex), m_facesfront(facesfront)
|
||||
{}
|
||||
inline bool operator<(const mdlVertex_t& other) const
|
||||
{
|
||||
if(m_facesfront < other.m_facesfront)
|
||||
return true;
|
||||
if(other.m_facesfront < m_facesfront)
|
||||
return false;
|
||||
|
||||
if(m_vertindex < other.m_vertindex)
|
||||
return true;
|
||||
if(other.m_vertindex < m_vertindex)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
inline bool operator==(const mdlVertex_t& other) const
|
||||
{
|
||||
return m_vertindex == other.m_vertindex
|
||||
&& m_facesfront == other.m_facesfront;
|
||||
}
|
||||
|
||||
int m_vertindex;
|
||||
int m_facesfront;
|
||||
};
|
||||
|
||||
typedef const mdlTriangle_t* mdlTriangleIterator;
|
||||
|
||||
void MDLSurface_read(Surface& surface, const byte* buffer, const char* name)
|
||||
{
|
||||
mdlHeader_t header;
|
||||
|
||||
PointerInputStream inputStream(buffer);
|
||||
istream_read_mdlHeader(inputStream, header);
|
||||
|
||||
for(int i = 0; i < header.numskins; ++i)
|
||||
{
|
||||
switch(istream_read_int32_le(inputStream))
|
||||
{
|
||||
case MDL_SKIN_SINGLE:
|
||||
inputStream.seek(header.skinwidth * header.skinheight);
|
||||
break;
|
||||
case MDL_SKIN_GROUP:
|
||||
int numskins = istream_read_int32_le(inputStream);
|
||||
inputStream.seek(numskins * (4 + (header.skinwidth * header.skinheight)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Array<mdlSt_t> mdlSts(header.numverts);
|
||||
for(Array<mdlSt_t>::iterator i = mdlSts.begin(); i != mdlSts.end(); ++i)
|
||||
{
|
||||
(*i).onseam = istream_read_int32_le(inputStream);
|
||||
(*i).s = istream_read_int32_le(inputStream);
|
||||
(*i).t = istream_read_int32_le(inputStream);
|
||||
}
|
||||
|
||||
Array<mdlTriangle_t> mdlTriangles(header.numtris);
|
||||
for(Array<mdlTriangle_t>::iterator i = mdlTriangles.begin(); i != mdlTriangles.end(); ++i)
|
||||
{
|
||||
(*i).facesfront = istream_read_int32_le(inputStream);
|
||||
(*i).vertindex[0] = istream_read_int32_le(inputStream);
|
||||
(*i).vertindex[1] = istream_read_int32_le(inputStream);
|
||||
(*i).vertindex[2] = istream_read_int32_le(inputStream);
|
||||
}
|
||||
|
||||
{
|
||||
bool found = false;
|
||||
for(int i = 0; i < header.numframes && found == false; i++)
|
||||
{
|
||||
switch(istream_read_int32_le(inputStream))
|
||||
{
|
||||
case MDL_FRAME_SINGLE:
|
||||
inputStream.seek(MDL_FRAME_SIZE);
|
||||
found = true;
|
||||
break;
|
||||
case MDL_FRAME_GROUP:
|
||||
int numframes = istream_read_int32_le(inputStream);
|
||||
inputStream.seek((MDL_XYZNORMAL_SIZE * 2) + (numframes * 4));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array<mdlXyzNormal_t> mdlXyzNormals(header.numtris);
|
||||
for(Array<mdlXyzNormal_t>::iterator i = mdlXyzNormals.begin(); i != mdlXyzNormals.end(); ++i)
|
||||
{
|
||||
inputStream.read((*i).v, 3);
|
||||
inputStream.read(&(*i).lightnormalindex, 1);
|
||||
}
|
||||
|
||||
{
|
||||
VertexBuffer<mdlVertex_t> mdl_vertices;
|
||||
|
||||
{
|
||||
UniqueVertexBuffer<mdlVertex_t> inserter(mdl_vertices);
|
||||
for(Array<mdlTriangle_t>::iterator i = mdlTriangles.begin(); i != mdlTriangles.end(); ++i)
|
||||
{
|
||||
surface.indices().insert(inserter.insert(mdlVertex_t((*i).vertindex[0], (*i).facesfront)));
|
||||
surface.indices().insert(inserter.insert(mdlVertex_t((*i).vertindex[1], (*i).facesfront)));
|
||||
surface.indices().insert(inserter.insert(mdlVertex_t((*i).vertindex[2], (*i).facesfront)));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
surface.vertices().reserve(mdl_vertices.size());
|
||||
|
||||
for(VertexBuffer<mdlVertex_t>::iterator i = mdl_vertices.begin(); i != mdl_vertices.end(); ++i)
|
||||
{
|
||||
surface.vertices().push_back(MDLVertex_construct(header, mdlXyzNormals[(*i).m_vertindex], mdlSts[(*i).m_vertindex], (*i).m_facesfront == MDL_FACES_FRONT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
surface.setShader(name);
|
||||
surface.updateAABB();
|
||||
}
|
||||
|
||||
void MDLModel_read(Model& model, const byte* buffer, const char* name)
|
||||
{
|
||||
MDLSurface_read(model.newSurface(), buffer, name);
|
||||
model.updateAABB();
|
||||
}
|
||||
|
||||
scene::Node& MDLModel_new(const byte* buffer, const char* name)
|
||||
{
|
||||
ModelNode* modelNode = new ModelNode();
|
||||
MDLModel_read(modelNode->model(), buffer, name);
|
||||
return modelNode->node();
|
||||
}
|
||||
|
||||
scene::Node& MDLModel_default()
|
||||
{
|
||||
ModelNode* modelNode = new ModelNode();
|
||||
Model_constructNull(modelNode->model());
|
||||
return modelNode->node();
|
||||
}
|
||||
|
||||
scene::Node& MDLModel_fromBuffer(unsigned char* buffer, const char* name)
|
||||
{
|
||||
if (!ident_equal(buffer, MDL_IDENT))
|
||||
{
|
||||
globalErrorStream() << "MDL read error: incorrect ident\n";
|
||||
return MDLModel_default();
|
||||
}
|
||||
else
|
||||
{
|
||||
return MDLModel_new(buffer, name);
|
||||
}
|
||||
}
|
||||
|
||||
scene::Node& loadMDLModel(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return MDLModel_fromBuffer(buffer.buffer, file.getName());
|
||||
}
|
||||
|
||||
29
plugins/md3model/mdl.h
Normal file
29
plugins/md3model/mdl.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
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_MDL_H)
|
||||
#define INCLUDED_MDL_H
|
||||
|
||||
namespace scene { class Node; }
|
||||
class ArchiveFile;
|
||||
scene::Node& loadMDLModel(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
23
plugins/md3model/mdlformat.cpp
Normal file
23
plugins/md3model/mdlformat.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
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 "mdlformat.h"
|
||||
|
||||
118
plugins/md3model/mdlformat.h
Normal file
118
plugins/md3model/mdlformat.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
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_MDLFORMAT_H)
|
||||
#define INCLUDED_MDLFORMAT_H
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
const unsigned char MDL_IDENT[4] = { 'I', 'D', 'P', 'O', };
|
||||
|
||||
#define MDL_VERSION 6
|
||||
|
||||
#define MDL_ONSEAM 0x0020
|
||||
|
||||
typedef enum { MDL_FRAME_SINGLE=0, MDL_FRAME_GROUP } aliasframetype_t;
|
||||
|
||||
typedef enum { MDL_SKIN_SINGLE=0, MDL_SKIN_GROUP } aliasskintype_t;
|
||||
|
||||
typedef float float3[3];
|
||||
|
||||
typedef struct {
|
||||
byte ident[4];
|
||||
int version;
|
||||
float3 scale;
|
||||
float3 scale_origin;
|
||||
float boundingradius;
|
||||
float3 eyeposition;
|
||||
int numskins;
|
||||
int skinwidth;
|
||||
int skinheight;
|
||||
int numverts;
|
||||
int numtris;
|
||||
int numframes;
|
||||
int synctype;
|
||||
int flags;
|
||||
float size;
|
||||
} mdlHeader_t;
|
||||
|
||||
// TODO: could be shorts
|
||||
|
||||
typedef struct {
|
||||
int onseam;
|
||||
int s;
|
||||
int t;
|
||||
} mdlSt_t;
|
||||
|
||||
typedef struct dtriangle_s {
|
||||
int facesfront;
|
||||
int vertindex[3];
|
||||
} mdlTriangle_t;
|
||||
|
||||
#define MDL_FACES_FRONT 1
|
||||
|
||||
// This mirrors trivert_t in trilib.h, is present so Quake knows how to
|
||||
// load this data
|
||||
|
||||
typedef struct {
|
||||
byte v[3];
|
||||
byte lightnormalindex;
|
||||
} mdlXyzNormal_t;
|
||||
|
||||
const int MDL_XYZNORMAL_SIZE = 4;
|
||||
|
||||
typedef struct {
|
||||
mdlXyzNormal_t bboxmin; // lightnormal isn't used
|
||||
mdlXyzNormal_t bboxmax; // lightnormal isn't used
|
||||
char name[16]; // frame name from grabbing
|
||||
} mdlFrame_t;
|
||||
|
||||
const int MDL_FRAME_SIZE = (MDL_XYZNORMAL_SIZE * 2) + 16;
|
||||
|
||||
typedef struct {
|
||||
int numframes;
|
||||
mdlXyzNormal_t bboxmin; // lightnormal isn't used
|
||||
mdlXyzNormal_t bboxmax; // lightnormal isn't used
|
||||
} mdlFrameGroup_t;
|
||||
|
||||
const int MDL_FRAMEGROUP_SIZE = 4 + (MDL_XYZNORMAL_SIZE * 2);
|
||||
|
||||
typedef struct {
|
||||
int numskins;
|
||||
} mdlSkinGroup_t;
|
||||
|
||||
typedef struct {
|
||||
float interval;
|
||||
} mdlFrameInterval_t;
|
||||
|
||||
typedef struct {
|
||||
float interval;
|
||||
} mdlSkinInterval_t;
|
||||
|
||||
typedef struct {
|
||||
aliasframetype_t type;
|
||||
} mdlFrameType_t;
|
||||
|
||||
typedef struct {
|
||||
aliasskintype_t type;
|
||||
} mdlSkinType_t;
|
||||
|
||||
#endif
|
||||
160
plugins/md3model/mdlimage.cpp
Normal file
160
plugins/md3model/mdlimage.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
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 "mdlimage.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "bytestreamutils.h"
|
||||
|
||||
#include "stream/textstream.h"
|
||||
#include "imagelib.h"
|
||||
|
||||
#include "mdlformat.h"
|
||||
#include "ident.h"
|
||||
|
||||
|
||||
unsigned char mdl_palette[768];
|
||||
/*
|
||||
==============
|
||||
Texture_InitPalette
|
||||
==============
|
||||
*/
|
||||
void Texture_InitPalette (byte *pal)
|
||||
{
|
||||
int r,g,b;
|
||||
int i;
|
||||
int inf;
|
||||
byte gammatable[256];
|
||||
double gamma;
|
||||
|
||||
gamma = 1.0;//g_qeglobals.d_savedinfo.fGamma;
|
||||
|
||||
if (gamma == 1.0)
|
||||
{
|
||||
for (i=0 ; i<256 ; i++)
|
||||
gammatable[i] = i;
|
||||
} else
|
||||
{
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
inf = (int)(255 * pow ( (i+0.5)/255.5 , gamma ) + 0.5);
|
||||
if (inf < 0)
|
||||
inf = 0;
|
||||
if (inf > 255)
|
||||
inf = 255;
|
||||
gammatable[i] = inf;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
r = gammatable[pal[0]];
|
||||
g = gammatable[pal[1]];
|
||||
b = gammatable[pal[2]];
|
||||
pal += 3;
|
||||
|
||||
//v = (r<<24) + (g<<16) + (b<<8) + 255;
|
||||
//v = BigLong (v);
|
||||
|
||||
//mdl_palette[i] = v;
|
||||
mdl_palette[i*3+0] = r;
|
||||
mdl_palette[i*3+1] = g;
|
||||
mdl_palette[i*3+2] = b;
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadPalette()
|
||||
{
|
||||
unsigned char* buffer;
|
||||
//int len =
|
||||
vfsLoadFile ("gfx/palette.lmp", (void **) &buffer);
|
||||
if (buffer == 0)
|
||||
return false;
|
||||
|
||||
Texture_InitPalette(buffer);
|
||||
|
||||
vfsFreeFile(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Image* LoadMDLImageBuff(byte* buffer)
|
||||
{
|
||||
if(!LoadPalette())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!ident_equal(buffer, MDL_IDENT))
|
||||
{
|
||||
globalErrorStream() << "LoadMDLImage: data has wrong ident\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
PointerInputStream inputStream(buffer);
|
||||
inputStream.seek(4 + 4 + 12 + 12 + 4 + 12);
|
||||
//int numskins =
|
||||
istream_read_int32_le(inputStream);
|
||||
int skinwidth = istream_read_int32_le(inputStream);
|
||||
int skinheight = istream_read_int32_le(inputStream);
|
||||
inputStream.seek(4 + 4 + 4 + 4 + 4 + 4);
|
||||
|
||||
switch(istream_read_int32_le(inputStream))
|
||||
{
|
||||
case MDL_SKIN_SINGLE:
|
||||
break;
|
||||
case MDL_SKIN_GROUP:
|
||||
int numskins = istream_read_int32_le(inputStream);
|
||||
inputStream.seek(numskins * 4);
|
||||
break;
|
||||
}
|
||||
|
||||
RGBAImage* image = new RGBAImage(skinwidth, skinheight);
|
||||
unsigned char* pRGBA = image->getRGBAPixels();
|
||||
|
||||
for(int i=0; i<(skinheight); i++)
|
||||
{
|
||||
for(int j=0; j<(skinwidth); j++)
|
||||
{
|
||||
byte index = istream_read_byte(inputStream);
|
||||
*pRGBA++ = mdl_palette[index * 3 + 0];
|
||||
*pRGBA++ = mdl_palette[index * 3 + 1];
|
||||
*pRGBA++ = mdl_palette[index * 3 + 2];
|
||||
*pRGBA++ = 255;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
Image* LoadMDLImage(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return LoadMDLImageBuff( buffer.buffer );
|
||||
}
|
||||
|
||||
void MDLImage_Destroy(byte* pic)
|
||||
{
|
||||
free(pic);
|
||||
}
|
||||
30
plugins/md3model/mdlimage.h
Normal file
30
plugins/md3model/mdlimage.h
Normal file
@@ -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_MDLIMAGE_H)
|
||||
#define INCLUDED_MDLIMAGE_H
|
||||
|
||||
class Image;
|
||||
class ArchiveFile;
|
||||
|
||||
Image* LoadMDLImage(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
23
plugins/md3model/mdlnormals.cpp
Normal file
23
plugins/md3model/mdlnormals.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
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 "mdlnormals.h"
|
||||
|
||||
191
plugins/md3model/mdlnormals.h
Normal file
191
plugins/md3model/mdlnormals.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
typedef const float mdlNormal_t[3];
|
||||
typedef const mdlNormal_t mdlNormals_t[162];
|
||||
|
||||
const mdlNormals_t g_mdl_normals = {
|
||||
{-0.525731f, 0.000000f, 0.850651f, },
|
||||
{-0.442863f, 0.238856f, 0.864188f, },
|
||||
{-0.295242f, 0.000000f, 0.955423f, },
|
||||
{-0.309017f, 0.500000f, 0.809017f, },
|
||||
{-0.162460f, 0.262866f, 0.951056f, },
|
||||
{ 0.000000f, 0.000000f, 1.000000f, },
|
||||
{ 0.000000f, 0.850651f, 0.525731f, },
|
||||
{-0.147621f, 0.716567f, 0.681718f, },
|
||||
{ 0.147621f, 0.716567f, 0.681718f, },
|
||||
{ 0.000000f, 0.525731f, 0.850651f, },
|
||||
{ 0.309017f, 0.500000f, 0.809017f, },
|
||||
{ 0.525731f, 0.000000f, 0.850651f, },
|
||||
{ 0.295242f, 0.000000f, 0.955423f, },
|
||||
{ 0.442863f, 0.238856f, 0.864188f, },
|
||||
{ 0.162460f, 0.262866f, 0.951056f, },
|
||||
{-0.681718f, 0.147621f, 0.716567f, },
|
||||
{-0.809017f, 0.309017f, 0.500000f, },
|
||||
{-0.587785f, 0.425325f, 0.688191f, },
|
||||
{-0.850651f, 0.525731f, 0.000000f, },
|
||||
{-0.864188f, 0.442863f, 0.238856f, },
|
||||
{-0.716567f, 0.681718f, 0.147621f, },
|
||||
{-0.688191f, 0.587785f, 0.425325f, },
|
||||
{-0.500000f, 0.809017f, 0.309017f, },
|
||||
{-0.238856f, 0.864188f, 0.442863f, },
|
||||
{-0.425325f, 0.688191f, 0.587785f, },
|
||||
{-0.716567f, 0.681718f,-0.147621f, },
|
||||
{-0.500000f, 0.809017f,-0.309017f, },
|
||||
{-0.525731f, 0.850651f, 0.000000f, },
|
||||
{ 0.000000f, 0.850651f,-0.525731f, },
|
||||
{-0.238856f, 0.864188f,-0.442863f, },
|
||||
{ 0.000000f, 0.955423f,-0.295242f, },
|
||||
{-0.262866f, 0.951056f,-0.162460f, },
|
||||
{ 0.000000f, 1.000000f, 0.000000f, },
|
||||
{ 0.000000f, 0.955423f, 0.295242f, },
|
||||
{-0.262866f, 0.951056f, 0.162460f, },
|
||||
{ 0.238856f, 0.864188f, 0.442863f, },
|
||||
{ 0.262866f, 0.951056f, 0.162460f, },
|
||||
{ 0.500000f, 0.809017f, 0.309017f, },
|
||||
{ 0.238856f, 0.864188f,-0.442863f, },
|
||||
{ 0.262866f, 0.951056f,-0.162460f, },
|
||||
{ 0.500000f, 0.809017f,-0.309017f, },
|
||||
{ 0.850651f, 0.525731f, 0.000000f, },
|
||||
{ 0.716567f, 0.681718f, 0.147621f, },
|
||||
{ 0.716567f, 0.681718f,-0.147621f, },
|
||||
{ 0.525731f, 0.850651f, 0.000000f, },
|
||||
{ 0.425325f, 0.688191f, 0.587785f, },
|
||||
{ 0.864188f, 0.442863f, 0.238856f, },
|
||||
{ 0.688191f, 0.587785f, 0.425325f, },
|
||||
{ 0.809017f, 0.309017f, 0.500000f, },
|
||||
{ 0.681718f, 0.147621f, 0.716567f, },
|
||||
{ 0.587785f, 0.425325f, 0.688191f, },
|
||||
{ 0.955423f, 0.295242f, 0.000000f, },
|
||||
{ 1.000000f, 0.000000f, 0.000000f, },
|
||||
{ 0.951056f, 0.162460f, 0.262866f, },
|
||||
{ 0.850651f,-0.525731f, 0.000000f, },
|
||||
{ 0.955423f,-0.295242f, 0.000000f, },
|
||||
{ 0.864188f,-0.442863f, 0.238856f, },
|
||||
{ 0.951056f,-0.162460f, 0.262866f, },
|
||||
{ 0.809017f,-0.309017f, 0.500000f, },
|
||||
{ 0.681718f,-0.147621f, 0.716567f, },
|
||||
{ 0.850651f, 0.000000f, 0.525731f, },
|
||||
{ 0.864188f, 0.442863f,-0.238856f, },
|
||||
{ 0.809017f, 0.309017f,-0.500000f, },
|
||||
{ 0.951056f, 0.162460f,-0.262866f, },
|
||||
{ 0.525731f, 0.000000f,-0.850651f, },
|
||||
{ 0.681718f, 0.147621f,-0.716567f, },
|
||||
{ 0.681718f,-0.147621f,-0.716567f, },
|
||||
{ 0.850651f, 0.000000f,-0.525731f, },
|
||||
{ 0.809017f,-0.309017f,-0.500000f, },
|
||||
{ 0.864188f,-0.442863f,-0.238856f, },
|
||||
{ 0.951056f,-0.162460f,-0.262866f, },
|
||||
{ 0.147621f, 0.716567f,-0.681718f, },
|
||||
{ 0.309017f, 0.500000f,-0.809017f, },
|
||||
{ 0.425325f, 0.688191f,-0.587785f, },
|
||||
{ 0.442863f, 0.238856f,-0.864188f, },
|
||||
{ 0.587785f, 0.425325f,-0.688191f, },
|
||||
{ 0.688191f, 0.587785f,-0.425325f, },
|
||||
{-0.147621f, 0.716567f,-0.681718f, },
|
||||
{-0.309017f, 0.500000f,-0.809017f, },
|
||||
{ 0.000000f, 0.525731f,-0.850651f, },
|
||||
{-0.525731f, 0.000000f,-0.850651f, },
|
||||
{-0.442863f, 0.238856f,-0.864188f, },
|
||||
{-0.295242f, 0.000000f,-0.955423f, },
|
||||
{-0.162460f, 0.262866f,-0.951056f, },
|
||||
{ 0.000000f, 0.000000f,-1.000000f, },
|
||||
{ 0.295242f, 0.000000f,-0.955423f, },
|
||||
{ 0.162460f, 0.262866f,-0.951056f, },
|
||||
{-0.442863f,-0.238856f,-0.864188f, },
|
||||
{-0.309017f,-0.500000f,-0.809017f, },
|
||||
{-0.162460f,-0.262866f,-0.951056f, },
|
||||
{ 0.000000f,-0.850651f,-0.525731f, },
|
||||
{-0.147621f,-0.716567f,-0.681718f, },
|
||||
{ 0.147621f,-0.716567f,-0.681718f, },
|
||||
{ 0.000000f,-0.525731f,-0.850651f, },
|
||||
{ 0.309017f,-0.500000f,-0.809017f, },
|
||||
{ 0.442863f,-0.238856f,-0.864188f, },
|
||||
{ 0.162460f,-0.262866f,-0.951056f, },
|
||||
{ 0.238856f,-0.864188f,-0.442863f, },
|
||||
{ 0.500000f,-0.809017f,-0.309017f, },
|
||||
{ 0.425325f,-0.688191f,-0.587785f, },
|
||||
{ 0.716567f,-0.681718f,-0.147621f, },
|
||||
{ 0.688191f,-0.587785f,-0.425325f, },
|
||||
{ 0.587785f,-0.425325f,-0.688191f, },
|
||||
{ 0.000000f,-0.955423f,-0.295242f, },
|
||||
{ 0.000000f,-1.000000f, 0.000000f, },
|
||||
{ 0.262866f,-0.951056f,-0.162460f, },
|
||||
{ 0.000000f,-0.850651f, 0.525731f, },
|
||||
{ 0.000000f,-0.955423f, 0.295242f, },
|
||||
{ 0.238856f,-0.864188f, 0.442863f, },
|
||||
{ 0.262866f,-0.951056f, 0.162460f, },
|
||||
{ 0.500000f,-0.809017f, 0.309017f, },
|
||||
{ 0.716567f,-0.681718f, 0.147621f, },
|
||||
{ 0.525731f,-0.850651f, 0.000000f, },
|
||||
{-0.238856f,-0.864188f,-0.442863f, },
|
||||
{-0.500000f,-0.809017f,-0.309017f, },
|
||||
{-0.262866f,-0.951056f,-0.162460f, },
|
||||
{-0.850651f,-0.525731f, 0.000000f, },
|
||||
{-0.716567f,-0.681718f,-0.147621f, },
|
||||
{-0.716567f,-0.681718f, 0.147621f, },
|
||||
{-0.525731f,-0.850651f, 0.000000f, },
|
||||
{-0.500000f,-0.809017f, 0.309017f, },
|
||||
{-0.238856f,-0.864188f, 0.442863f, },
|
||||
{-0.262866f,-0.951056f, 0.162460f, },
|
||||
{-0.864188f,-0.442863f, 0.238856f, },
|
||||
{-0.809017f,-0.309017f, 0.500000f, },
|
||||
{-0.688191f,-0.587785f, 0.425325f, },
|
||||
{-0.681718f,-0.147621f, 0.716567f, },
|
||||
{-0.442863f,-0.238856f, 0.864188f, },
|
||||
{-0.587785f,-0.425325f, 0.688191f, },
|
||||
{-0.309017f,-0.500000f, 0.809017f, },
|
||||
{-0.147621f,-0.716567f, 0.681718f, },
|
||||
{-0.425325f,-0.688191f, 0.587785f, },
|
||||
{-0.162460f,-0.262866f, 0.951056f, },
|
||||
{ 0.442863f,-0.238856f, 0.864188f, },
|
||||
{ 0.162460f,-0.262866f, 0.951056f, },
|
||||
{ 0.309017f,-0.500000f, 0.809017f, },
|
||||
{ 0.147621f,-0.716567f, 0.681718f, },
|
||||
{ 0.000000f,-0.525731f, 0.850651f, },
|
||||
{ 0.425325f,-0.688191f, 0.587785f, },
|
||||
{ 0.587785f,-0.425325f, 0.688191f, },
|
||||
{ 0.688191f,-0.587785f, 0.425325f, },
|
||||
{-0.955423f, 0.295242f, 0.000000f, },
|
||||
{-0.951056f, 0.162460f, 0.262866f, },
|
||||
{-1.000000f, 0.000000f, 0.000000f, },
|
||||
{-0.850651f, 0.000000f, 0.525731f, },
|
||||
{-0.955423f,-0.295242f, 0.000000f, },
|
||||
{-0.951056f,-0.162460f, 0.262866f, },
|
||||
{-0.864188f, 0.442863f,-0.238856f, },
|
||||
{-0.951056f, 0.162460f,-0.262866f, },
|
||||
{-0.809017f, 0.309017f,-0.500000f, },
|
||||
{-0.864188f,-0.442863f,-0.238856f, },
|
||||
{-0.951056f,-0.162460f,-0.262866f, },
|
||||
{-0.809017f,-0.309017f,-0.500000f, },
|
||||
{-0.681718f, 0.147621f,-0.716567f, },
|
||||
{-0.681718f,-0.147621f,-0.716567f, },
|
||||
{-0.850651f, 0.000000f,-0.525731f, },
|
||||
{-0.688191f, 0.587785f,-0.425325f, },
|
||||
{-0.587785f, 0.425325f,-0.688191f, },
|
||||
{-0.425325f, 0.688191f,-0.587785f, },
|
||||
{-0.425325f,-0.688191f,-0.587785f, },
|
||||
{-0.587785f,-0.425325f,-0.688191f, },
|
||||
{-0.688191f,-0.587785f,-0.425325f, },
|
||||
};
|
||||
|
||||
|
||||
23
plugins/md3model/model.cpp
Normal file
23
plugins/md3model/model.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
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 "model.h"
|
||||
|
||||
643
plugins/md3model/model.h
Normal file
643
plugins/md3model/model.h
Normal file
@@ -0,0 +1,643 @@
|
||||
/*
|
||||
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_MODEL_H)
|
||||
#define INCLUDED_MODEL_H
|
||||
|
||||
#include "cullable.h"
|
||||
#include "renderable.h"
|
||||
#include "selectable.h"
|
||||
#include "modelskin.h"
|
||||
|
||||
#include "math/frustum.h"
|
||||
#include "string/string.h"
|
||||
#include "generic/static.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "os/path.h"
|
||||
#include "scenelib.h"
|
||||
#include "instancelib.h"
|
||||
#include "transformlib.h"
|
||||
#include "traverselib.h"
|
||||
#include "render.h"
|
||||
|
||||
class VectorLightList : public LightList
|
||||
{
|
||||
typedef std::vector<const RendererLight*> Lights;
|
||||
Lights m_lights;
|
||||
public:
|
||||
void addLight(const RendererLight& light)
|
||||
{
|
||||
m_lights.push_back(&light);
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
m_lights.clear();
|
||||
}
|
||||
void evaluateLights() const
|
||||
{
|
||||
}
|
||||
void lightsChanged() const
|
||||
{
|
||||
}
|
||||
void forEachLight(const RendererLightCallback& callback) const
|
||||
{
|
||||
for(Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i)
|
||||
{
|
||||
callback(*(*i));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline VertexPointer vertexpointer_arbitrarymeshvertex(const ArbitraryMeshVertex* array)
|
||||
{
|
||||
return VertexPointer(VertexPointer::pointer(&array->vertex), sizeof(ArbitraryMeshVertex));
|
||||
}
|
||||
|
||||
inline void parseTextureName(CopiedString& name, const char* token)
|
||||
{
|
||||
StringOutputStream cleaned(256);
|
||||
cleaned << PathCleaned(token);
|
||||
name = CopiedString(cleaned.c_str(), path_get_filename_base_end(cleaned.c_str())); // remove extension
|
||||
}
|
||||
|
||||
// generic renderable triangle surface
|
||||
class Surface :
|
||||
public OpenGLRenderable
|
||||
{
|
||||
public:
|
||||
typedef VertexBuffer<ArbitraryMeshVertex> vertices_t;
|
||||
typedef IndexBuffer indices_t;
|
||||
private:
|
||||
|
||||
AABB m_aabb_local;
|
||||
CopiedString m_shader;
|
||||
Shader* m_state;
|
||||
|
||||
vertices_t m_vertices;
|
||||
indices_t m_indices;
|
||||
|
||||
void CaptureShader()
|
||||
{
|
||||
m_state = GlobalShaderCache().capture(m_shader.c_str());
|
||||
}
|
||||
void ReleaseShader()
|
||||
{
|
||||
GlobalShaderCache().release(m_shader.c_str());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Surface()
|
||||
: m_shader(""), m_state(0)
|
||||
{
|
||||
CaptureShader();
|
||||
}
|
||||
~Surface()
|
||||
{
|
||||
ReleaseShader();
|
||||
}
|
||||
|
||||
vertices_t& vertices()
|
||||
{
|
||||
return m_vertices;
|
||||
}
|
||||
indices_t& indices()
|
||||
{
|
||||
return m_indices;
|
||||
}
|
||||
|
||||
void setShader(const char* name)
|
||||
{
|
||||
ReleaseShader();
|
||||
parseTextureName(m_shader, name);
|
||||
CaptureShader();
|
||||
}
|
||||
const char* getShader() const
|
||||
{
|
||||
return m_shader.c_str();
|
||||
}
|
||||
Shader* getState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
void updateAABB()
|
||||
{
|
||||
m_aabb_local = AABB();
|
||||
for(vertices_t::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i)
|
||||
aabb_extend_by_point_safe(m_aabb_local, reinterpret_cast<const Vector3&>((*i).vertex));
|
||||
|
||||
|
||||
|
||||
for(Surface::indices_t::iterator i = m_indices.begin(); i != m_indices.end(); i += 3)
|
||||
{
|
||||
ArbitraryMeshVertex& a = m_vertices[*(i + 0)];
|
||||
ArbitraryMeshVertex& b = m_vertices[*(i + 1)];
|
||||
ArbitraryMeshVertex& c = m_vertices[*(i + 2)];
|
||||
|
||||
ArbitraryMeshTriangle_sumTangents(a, b, c);
|
||||
}
|
||||
|
||||
for(Surface::vertices_t::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i)
|
||||
{
|
||||
vector3_normalise(reinterpret_cast<Vector3&>((*i).tangent));
|
||||
vector3_normalise(reinterpret_cast<Vector3&>((*i).bitangent));
|
||||
}
|
||||
}
|
||||
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
#if 1
|
||||
if((state & RENDER_BUMP) != 0)
|
||||
{
|
||||
if(GlobalShaderCache().useShaderLanguage())
|
||||
{
|
||||
glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->normal);
|
||||
glVertexAttribPointerARB(c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->texcoord);
|
||||
glVertexAttribPointerARB(c_attr_Tangent, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->tangent);
|
||||
glVertexAttribPointerARB(c_attr_Binormal, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->bitangent);
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertexAttribPointerARB(11, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->normal);
|
||||
glVertexAttribPointerARB(8, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->texcoord);
|
||||
glVertexAttribPointerARB(9, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->tangent);
|
||||
glVertexAttribPointerARB(10, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->bitangent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->normal);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->texcoord);
|
||||
}
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->vertex);
|
||||
glDrawElements(GL_TRIANGLES, GLsizei(m_indices.size()), RenderIndexTypeID, m_indices.data());
|
||||
#else
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(unsigned int i = 0; i < m_indices.size(); ++i)
|
||||
{
|
||||
glTexCoord2fv(&m_vertices[m_indices[i]].texcoord.s);
|
||||
glNormal3fv(&m_vertices[m_indices[i]].normal.x);
|
||||
glVertex3fv(&m_vertices[m_indices[i]].vertex.x);
|
||||
}
|
||||
glEnd();
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG)
|
||||
glBegin(GL_LINES);
|
||||
|
||||
for(VertexBuffer<ArbitraryMeshVertex>::const_iterator i = m_vertices.begin(); i != m_vertices.end(); ++i)
|
||||
{
|
||||
Vector3 normal = vector3_added(vertex3f_to_vector3((*i).vertex), vector3_scaled(normal3f_to_vector3((*i).normal), 8));
|
||||
glVertex3fv(vertex3f_to_array((*i).vertex));
|
||||
glVertex3fv(vector3_to_array(normal));
|
||||
}
|
||||
glEnd();
|
||||
#endif
|
||||
}
|
||||
|
||||
VolumeIntersectionValue intersectVolume(const VolumeTest& test, const Matrix4& localToWorld) const
|
||||
{
|
||||
return test.TestAABB(m_aabb_local, localToWorld);
|
||||
}
|
||||
|
||||
const AABB& localAABB() const
|
||||
{
|
||||
return m_aabb_local;
|
||||
}
|
||||
|
||||
void render(Renderer& renderer, const Matrix4& localToWorld, Shader* state) const
|
||||
{
|
||||
renderer.SetState(state, Renderer::eFullMaterials);
|
||||
renderer.addRenderable(*this, localToWorld);
|
||||
}
|
||||
|
||||
void render(Renderer& renderer, const Matrix4& localToWorld) const
|
||||
{
|
||||
render(renderer, localToWorld, m_state);
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test, const Matrix4& localToWorld)
|
||||
{
|
||||
test.BeginMesh(localToWorld);
|
||||
|
||||
SelectionIntersection best;
|
||||
test.TestTriangles(
|
||||
vertexpointer_arbitrarymeshvertex(m_vertices.data()),
|
||||
IndexPointer(m_indices.data(), IndexPointer::index_type(m_indices.size())),
|
||||
best
|
||||
);
|
||||
if(best.valid())
|
||||
{
|
||||
selector.addIntersection(best);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// generic model node
|
||||
class Model :
|
||||
public Cullable,
|
||||
public Bounded
|
||||
{
|
||||
typedef std::vector<Surface*> surfaces_t;
|
||||
surfaces_t m_surfaces;
|
||||
|
||||
AABB m_aabb_local;
|
||||
public:
|
||||
Callback m_lightsChanged;
|
||||
|
||||
~Model()
|
||||
{
|
||||
for(surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i)
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
||||
typedef surfaces_t::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_surfaces.begin();
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_surfaces.end();
|
||||
}
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_surfaces.size();
|
||||
}
|
||||
|
||||
Surface& newSurface()
|
||||
{
|
||||
m_surfaces.push_back(new Surface);
|
||||
return *m_surfaces.back();
|
||||
}
|
||||
void updateAABB()
|
||||
{
|
||||
m_aabb_local = AABB();
|
||||
for(surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i)
|
||||
{
|
||||
aabb_extend_by_aabb_safe(m_aabb_local, (*i)->localAABB());
|
||||
}
|
||||
}
|
||||
|
||||
VolumeIntersectionValue intersectVolume(const VolumeTest& test, const Matrix4& localToWorld) const
|
||||
{
|
||||
return test.TestAABB(m_aabb_local, localToWorld);
|
||||
}
|
||||
|
||||
virtual const AABB& localAABB() const
|
||||
{
|
||||
return m_aabb_local;
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test, const Matrix4& localToWorld)
|
||||
{
|
||||
for(surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i)
|
||||
{
|
||||
if((*i)->intersectVolume(test.getVolume(), localToWorld) != c_volumeOutside)
|
||||
{
|
||||
(*i)->testSelect(selector, test, localToWorld);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline void Surface_addLight(const Surface& surface, VectorLightList& lights, const Matrix4& localToWorld, const RendererLight& light)
|
||||
{
|
||||
if(light.testAABB(aabb_for_oriented_aabb(surface.localAABB(), localToWorld)))
|
||||
{
|
||||
lights.addLight(light);
|
||||
}
|
||||
}
|
||||
|
||||
class ModelInstance :
|
||||
public scene::Instance,
|
||||
public Renderable,
|
||||
public SelectionTestable,
|
||||
public LightCullable,
|
||||
public SkinnedModel
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
InstanceContainedCast<ModelInstance, Bounded>::install(m_casts);
|
||||
InstanceContainedCast<ModelInstance, Cullable>::install(m_casts);
|
||||
InstanceStaticCast<ModelInstance, Renderable>::install(m_casts);
|
||||
InstanceStaticCast<ModelInstance, SelectionTestable>::install(m_casts);
|
||||
InstanceStaticCast<ModelInstance, SkinnedModel>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
Model& m_model;
|
||||
|
||||
const LightList* m_lightList;
|
||||
typedef Array<VectorLightList> SurfaceLightLists;
|
||||
SurfaceLightLists m_surfaceLightLists;
|
||||
|
||||
class Remap
|
||||
{
|
||||
public:
|
||||
CopiedString first;
|
||||
Shader* second;
|
||||
Remap() : second(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
typedef Array<Remap> SurfaceRemaps;
|
||||
SurfaceRemaps m_skins;
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
Bounded& get(NullType<Bounded>)
|
||||
{
|
||||
return m_model;
|
||||
}
|
||||
Cullable& get(NullType<Cullable>)
|
||||
{
|
||||
return m_model;
|
||||
}
|
||||
|
||||
void lightsChanged()
|
||||
{
|
||||
m_lightList->lightsChanged();
|
||||
}
|
||||
typedef MemberCaller<ModelInstance, &ModelInstance::lightsChanged> LightsChangedCaller;
|
||||
|
||||
void constructRemaps()
|
||||
{
|
||||
ModelSkin* skin = NodeTypeCast<ModelSkin>::cast(path().parent());
|
||||
if(skin != 0 && skin->realised())
|
||||
{
|
||||
SurfaceRemaps::iterator j = m_skins.begin();
|
||||
for(Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i, ++j)
|
||||
{
|
||||
const char* remap = skin->getRemap((*i)->getShader());
|
||||
if(!string_empty(remap))
|
||||
{
|
||||
(*j).first = remap;
|
||||
(*j).second = GlobalShaderCache().capture(remap);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*j).second = 0;
|
||||
}
|
||||
}
|
||||
SceneChangeNotify();
|
||||
}
|
||||
}
|
||||
void destroyRemaps()
|
||||
{
|
||||
for(SurfaceRemaps::iterator i = m_skins.begin(); i != m_skins.end(); ++i)
|
||||
{
|
||||
if((*i).second != 0)
|
||||
{
|
||||
GlobalShaderCache().release((*i).first.c_str());
|
||||
(*i).second = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
void skinChanged()
|
||||
{
|
||||
ASSERT_MESSAGE(m_skins.size() == m_model.size(), "ERROR");
|
||||
destroyRemaps();
|
||||
constructRemaps();
|
||||
}
|
||||
|
||||
ModelInstance(const scene::Path& path, scene::Instance* parent, Model& model) :
|
||||
Instance(path, parent, this, StaticTypeCasts::instance().get()),
|
||||
m_model(model),
|
||||
m_surfaceLightLists(m_model.size()),
|
||||
m_skins(m_model.size())
|
||||
{
|
||||
m_lightList = &GlobalShaderCache().attach(*this);
|
||||
m_model.m_lightsChanged = LightsChangedCaller(*this);
|
||||
|
||||
Instance::setTransformChangedCallback(LightsChangedCaller(*this));
|
||||
|
||||
constructRemaps();
|
||||
}
|
||||
~ModelInstance()
|
||||
{
|
||||
destroyRemaps();
|
||||
|
||||
Instance::setTransformChangedCallback(Callback());
|
||||
|
||||
m_model.m_lightsChanged = Callback();
|
||||
GlobalShaderCache().detach(*this);
|
||||
}
|
||||
|
||||
void render(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
SurfaceLightLists::const_iterator j = m_surfaceLightLists.begin();
|
||||
SurfaceRemaps::const_iterator k = m_skins.begin();
|
||||
for(Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i, ++j, ++k)
|
||||
{
|
||||
if((*i)->intersectVolume(volume, localToWorld) != c_volumeOutside)
|
||||
{
|
||||
renderer.setLights(*j);
|
||||
(*i)->render(renderer, localToWorld, (*k).second != 0 ? (*k).second : (*i)->getState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_lightList->evaluateLights();
|
||||
|
||||
render(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
renderSolid(renderer, volume);
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test)
|
||||
{
|
||||
m_model.testSelect(selector, test, Instance::localToWorld());
|
||||
}
|
||||
|
||||
bool testLight(const RendererLight& light) const
|
||||
{
|
||||
return light.testAABB(worldAABB());
|
||||
}
|
||||
void insertLight(const RendererLight& light)
|
||||
{
|
||||
const Matrix4& localToWorld = Instance::localToWorld();
|
||||
SurfaceLightLists::iterator j = m_surfaceLightLists.begin();
|
||||
for(Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i)
|
||||
{
|
||||
Surface_addLight(*(*i), *j++, localToWorld, light);
|
||||
}
|
||||
}
|
||||
void clearLights()
|
||||
{
|
||||
for(SurfaceLightLists::iterator i = m_surfaceLightLists.begin(); i != m_surfaceLightLists.end(); ++i)
|
||||
{
|
||||
(*i).clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ModelNode : public scene::Node::Symbiot, public scene::Instantiable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<ModelNode, scene::Instantiable>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
Model m_model;
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
ModelNode() : m_node(this, this, StaticTypeCasts::instance().get())
|
||||
{
|
||||
}
|
||||
|
||||
Model& model()
|
||||
{
|
||||
return m_model;
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new ModelInstance(path, parent, m_model);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline void Surface_constructQuad(Surface& surface, const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d, const Vector3& normal)
|
||||
{
|
||||
surface.vertices().push_back(
|
||||
ArbitraryMeshVertex(
|
||||
vertex3f_for_vector3(a),
|
||||
normal3f_for_vector3(normal),
|
||||
texcoord2f_from_array(aabb_texcoord_topleft)
|
||||
)
|
||||
);
|
||||
surface.vertices().push_back(
|
||||
ArbitraryMeshVertex(
|
||||
vertex3f_for_vector3(b),
|
||||
normal3f_for_vector3(normal),
|
||||
texcoord2f_from_array(aabb_texcoord_topright)
|
||||
)
|
||||
);
|
||||
surface.vertices().push_back(
|
||||
ArbitraryMeshVertex(
|
||||
vertex3f_for_vector3(c),
|
||||
normal3f_for_vector3(normal),
|
||||
texcoord2f_from_array(aabb_texcoord_botright)
|
||||
)
|
||||
);
|
||||
surface.vertices().push_back(
|
||||
ArbitraryMeshVertex(
|
||||
vertex3f_for_vector3(d),
|
||||
normal3f_for_vector3(normal),
|
||||
texcoord2f_from_array(aabb_texcoord_botleft)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
inline void Model_constructNull(Model& model)
|
||||
{
|
||||
Surface& surface = model.newSurface();
|
||||
|
||||
AABB aabb(Vector3(0, 0, 0), Vector3(8, 8, 8));
|
||||
|
||||
Vector3 points[8];
|
||||
aabb_corners(aabb, points);
|
||||
|
||||
surface.vertices().reserve(24);
|
||||
|
||||
Surface_constructQuad(surface, points[2], points[1], points[5], points[6], aabb_normals[0]);
|
||||
Surface_constructQuad(surface, points[1], points[0], points[4], points[5], aabb_normals[1]);
|
||||
Surface_constructQuad(surface, points[0], points[1], points[2], points[3], aabb_normals[2]);
|
||||
Surface_constructQuad(surface, points[0], points[3], points[7], points[4], aabb_normals[3]);
|
||||
Surface_constructQuad(surface, points[3], points[2], points[6], points[7], aabb_normals[4]);
|
||||
Surface_constructQuad(surface, points[7], points[6], points[5], points[4], aabb_normals[5]);
|
||||
|
||||
surface.indices().reserve(36);
|
||||
|
||||
RenderIndex indices[36] = {
|
||||
0, 1, 2, 0, 2, 3,
|
||||
4, 5, 6, 4, 6, 7,
|
||||
8, 9, 10, 8, 10, 11,
|
||||
12, 13, 14, 12, 14, 15,
|
||||
16, 17, 18, 16, 18, 19,
|
||||
20, 21, 22, 10, 22, 23,
|
||||
};
|
||||
|
||||
for(RenderIndex* i = indices; i != indices+(sizeof(indices)/sizeof(RenderIndex)); ++i)
|
||||
{
|
||||
surface.indices().insert(*i);
|
||||
}
|
||||
|
||||
surface.setShader("");
|
||||
|
||||
surface.updateAABB();
|
||||
|
||||
model.updateAABB();
|
||||
}
|
||||
|
||||
#endif
|
||||
7
plugins/md3model/modelmd3.def
Normal file
7
plugins/md3model/modelmd3.def
Normal file
@@ -0,0 +1,7 @@
|
||||
; modelmd3.def : Declares the module parameters for the DLL.
|
||||
|
||||
LIBRARY "MODELMD3"
|
||||
|
||||
EXPORTS
|
||||
; Explicit exports can go here
|
||||
Radiant_RegisterModules @1
|
||||
270
plugins/md3model/modelmd3.vcproj
Normal file
270
plugins/md3model/modelmd3.vcproj
Normal file
@@ -0,0 +1,270 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="modelmd3"
|
||||
ProjectGUID="{C2A5530D-C2DB-4503-A651-4B92AEC5FE74}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport";"../../../gtk2-2.4/include/glib-2.0";"../../../gtk2-2.4/lib/glib-2.0/include""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MODELMD3_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
MinimalRebuild="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="glib-2.0.lib"
|
||||
OutputFile="$(OutDir)/modelmd3.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""../../../gtk2-2.4/lib""
|
||||
IgnoreDefaultLibraryNames="msvcprtd.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/modelmd3.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/modelmd3.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OptimizeForWindowsApplication="FALSE"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport";"../../../gtk2-2.4/include/glib-2.0";"../../../gtk2-2.4/lib/glib-2.0/include""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MODELMD3_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="glib-2.0.lib"
|
||||
OutputFile="$(OutDir)/modelmd3.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""../../../gtk2-2.4/lib""
|
||||
IgnoreDefaultLibraryNames="msvcprt.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
ImportLibrary="$(OutDir)/modelmd3.lib"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="0"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\plugin.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="modules"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\md2.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\md2.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\md3.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\md3.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\md5.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\md5.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdc.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdc.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdl.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdl.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdlimage.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdlimage.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="components"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\ident.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\md3normals.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\md3normals.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdlformat.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdlformat.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdlnormals.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdlnormals.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\model.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\model.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\..\debug.py">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\modelmd3.def">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
250
plugins/md3model/plugin.cpp
Normal file
250
plugins/md3model/plugin.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
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 "md3.h"
|
||||
#include "mdl.h"
|
||||
#include "md2.h"
|
||||
#include "mdc.h"
|
||||
#include "mdlimage.h"
|
||||
#include "md5.h"
|
||||
|
||||
|
||||
class MD3ModelLoader : public ModelLoader
|
||||
{
|
||||
public:
|
||||
scene::Node& loadModel(ArchiveFile& file)
|
||||
{
|
||||
return loadMD3Model(file);
|
||||
}
|
||||
};
|
||||
|
||||
class ModelDependencies :
|
||||
public GlobalFileSystemModuleRef,
|
||||
public GlobalOpenGLModuleRef,
|
||||
public GlobalUndoModuleRef,
|
||||
public GlobalSceneGraphModuleRef,
|
||||
public GlobalShaderCacheModuleRef,
|
||||
public GlobalSelectionModuleRef,
|
||||
public GlobalFiletypesModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class ModelMD3API : public TypeSystemRef
|
||||
{
|
||||
MD3ModelLoader m_modelmd3;
|
||||
public:
|
||||
typedef ModelLoader Type;
|
||||
STRING_CONSTANT(Name, "md3");
|
||||
|
||||
ModelMD3API()
|
||||
{
|
||||
GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("md3 models", "*.md3"));
|
||||
}
|
||||
ModelLoader* getTable()
|
||||
{
|
||||
return &m_modelmd3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ModelMD3API, ModelDependencies> ModelMD3Module;
|
||||
|
||||
ModelMD3Module g_ModelMD3Module;
|
||||
|
||||
|
||||
|
||||
class MD2ModelLoader : public ModelLoader
|
||||
{
|
||||
public:
|
||||
scene::Node& loadModel(ArchiveFile& file)
|
||||
{
|
||||
return loadMD2Model(file);
|
||||
}
|
||||
};
|
||||
|
||||
class ModelMD2API : public TypeSystemRef
|
||||
{
|
||||
MD2ModelLoader m_modelmd2;
|
||||
public:
|
||||
typedef ModelLoader Type;
|
||||
STRING_CONSTANT(Name, "md2");
|
||||
|
||||
ModelMD2API()
|
||||
{
|
||||
GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("md2 models", "*.md2"));
|
||||
}
|
||||
ModelLoader* getTable()
|
||||
{
|
||||
return &m_modelmd2;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ModelMD2API, ModelDependencies> ModelMD2Module;
|
||||
|
||||
ModelMD2Module g_ModelMD2Module;
|
||||
|
||||
class MDLModelLoader : public ModelLoader
|
||||
{
|
||||
public:
|
||||
scene::Node& loadModel(ArchiveFile& file)
|
||||
{
|
||||
return loadMDLModel(file);
|
||||
}
|
||||
};
|
||||
|
||||
class ModelMDLAPI : public TypeSystemRef
|
||||
{
|
||||
MDLModelLoader m_modelmdl;
|
||||
public:
|
||||
typedef ModelLoader Type;
|
||||
STRING_CONSTANT(Name, "mdl");
|
||||
|
||||
ModelMDLAPI()
|
||||
{
|
||||
GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("mdl models", "*.mdl"));
|
||||
}
|
||||
ModelLoader* getTable()
|
||||
{
|
||||
return &m_modelmdl;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ModelMDLAPI, ModelDependencies> ModelMDLModule;
|
||||
|
||||
ModelMDLModule g_ModelMDLModule;
|
||||
|
||||
class MDCModelLoader : public ModelLoader
|
||||
{
|
||||
public:
|
||||
scene::Node& loadModel(ArchiveFile& file)
|
||||
{
|
||||
return loadMDCModel(file);
|
||||
}
|
||||
};
|
||||
|
||||
class ModelMDCAPI : public TypeSystemRef
|
||||
{
|
||||
MDCModelLoader m_modelmdc;
|
||||
public:
|
||||
typedef ModelLoader Type;
|
||||
STRING_CONSTANT(Name, "mdc");
|
||||
|
||||
ModelMDCAPI()
|
||||
{
|
||||
GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("mdc models", "*.mdc"));
|
||||
}
|
||||
ModelLoader* getTable()
|
||||
{
|
||||
return &m_modelmdc;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ModelMDCAPI, ModelDependencies> ModelMDCModule;
|
||||
|
||||
ModelMDCModule g_ModelMDCModule;
|
||||
|
||||
|
||||
class ImageMDLAPI
|
||||
{
|
||||
_QERPlugImageTable m_imagemdl;
|
||||
public:
|
||||
typedef _QERPlugImageTable Type;
|
||||
STRING_CONSTANT(Name, "mdl");
|
||||
|
||||
ImageMDLAPI()
|
||||
{
|
||||
m_imagemdl.loadImage = &LoadMDLImage;
|
||||
}
|
||||
_QERPlugImageTable* getTable()
|
||||
{
|
||||
return &m_imagemdl;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ImageMDLAPI, GlobalFileSystemModuleRef> ImageMDLModule;
|
||||
|
||||
ImageMDLModule g_ImageMDLModule;
|
||||
|
||||
|
||||
class MD5ModelLoader : public ModelLoader
|
||||
{
|
||||
public:
|
||||
scene::Node& loadModel(ArchiveFile& file)
|
||||
{
|
||||
return loadMD5Model(file);
|
||||
}
|
||||
};
|
||||
|
||||
class ModelMD5Dependencies : public ModelDependencies, public GlobalScripLibModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class ModelMD5API : public TypeSystemRef
|
||||
{
|
||||
MD5ModelLoader m_modelmd5;
|
||||
public:
|
||||
typedef ModelLoader Type;
|
||||
STRING_CONSTANT(Name, "md5mesh");
|
||||
|
||||
ModelMD5API()
|
||||
{
|
||||
GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("md5 meshes", "*.md5mesh"));
|
||||
}
|
||||
ModelLoader* getTable()
|
||||
{
|
||||
return &m_modelmd5;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ModelMD5API, ModelMD5Dependencies> ModelMD5Module;
|
||||
|
||||
ModelMD5Module g_ModelMD5Module;
|
||||
|
||||
|
||||
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
|
||||
{
|
||||
GlobalErrorStream::instance().setOutputStream(server.getErrorStream());
|
||||
GlobalOutputStream::instance().setOutputStream(server.getOutputStream());
|
||||
GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler());
|
||||
GlobalModuleServer::instance().set(server);
|
||||
|
||||
g_ModelMD3Module.selfRegister();
|
||||
g_ModelMD2Module.selfRegister();
|
||||
g_ModelMDLModule.selfRegister();
|
||||
g_ModelMDCModule.selfRegister();
|
||||
g_ImageMDLModule.selfRegister();
|
||||
g_ModelMD5Module.selfRegister();
|
||||
}
|
||||
25
plugins/md3model/plugin.h
Normal file
25
plugins/md3model/plugin.h
Normal file
@@ -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_PLUGIN_H)
|
||||
#define INCLUDED_PLUGIN_H
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user