remove q3data and dependencies

looks like it has no any use today
This commit is contained in:
Garux 2021-10-07 21:10:12 +03:00
parent d897de13d5
commit 5c67990859
33 changed files with 0 additions and 11116 deletions

View File

@ -459,14 +459,8 @@ binaries-h2data: \
.PHONY: binaries-tools-quake3
binaries-tools-quake3: \
binaries-q3data \
binaries-q3map2 \
.PHONY: binaries-q3data
binaries-q3data: \
$(INSTALLDIR)/q3data.$(EXE) \
$(INSTALLDIR)/q3data \
.PHONY: binaries-q3map2
binaries-q3map2: \
$(INSTALLDIR)/q3map2.$(EXE) \
@ -821,36 +815,6 @@ libetclib.$(A): CPPFLAGS_EXTRA := -Ilibs
libetclib.$(A): \
libs/etclib.o \
$(INSTALLDIR)/q3data.$(EXE): LIBS_EXTRA := $(LIBS_XML) $(LIBS_GLIB) $(LIBS_ZLIB)
$(INSTALLDIR)/q3data.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) $(CPPFLAGS_GLIB) $(CPPFLAGS_ZLIB) -Itools/quake3/common -Ilibs -Iinclude
$(INSTALLDIR)/q3data.$(EXE): \
tools/quake3/common/aselib.o \
tools/quake3/common/bspfile.o \
tools/quake3/common/cmdlib.o \
tools/quake3/common/imagelib.o \
tools/quake3/common/inout.o \
tools/quake3/common/md4.o \
tools/quake3/common/scriplib.o \
tools/quake3/common/trilib.o \
tools/quake3/common/unzip.o \
tools/quake3/common/vfs.o \
tools/quake3/common/miniz.o \
tools/quake3/q3data/3dslib.o \
tools/quake3/q3data/compress.o \
tools/quake3/q3data/images.o \
tools/quake3/q3data/md3lib.o \
tools/quake3/q3data/models.o \
tools/quake3/q3data/p3dlib.o \
tools/quake3/q3data/polyset.o \
tools/quake3/q3data/q3data.o \
tools/quake3/q3data/stripper.o \
tools/quake3/q3data/video.o \
libfilematch.$(A) \
libetclib.$(A) \
libl_net.$(A) \
libmathlib.$(A) \
$(if $(findstring Win32,$(OS)),icons/q3data.o,) \
$(INSTALLDIR)/radiant.$(EXE): LDFLAGS_EXTRA := $(MWINDOWS)
$(INSTALLDIR)/radiant.$(EXE): LIBS_EXTRA := $(LIBS_GL) $(LIBS_DL) $(LIBS_XML) $(LIBS_GLIB) $(LIBS_GTK) $(LIBS_GTKGLEXT) $(LIBS_ZLIB) $(LIBS_PANGOFT2)
$(INSTALLDIR)/radiant.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_GL) $(CPPFLAGS_DL) $(CPPFLAGS_XML) $(CPPFLAGS_GLIB) $(CPPFLAGS_GTK) $(CPPFLAGS_GTKGLEXT) $(CPPFLAGS_PANGOFT2) -Ilibs -Iinclude

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

View File

@ -64,7 +64,6 @@ bundle:
dylibbundler -b \
-x $(BINDIR)/radiant.x86_64 \
-x $(BINDIR)/q2map.x86_64 \
-x $(BINDIR)/q3data.x86_64 \
-x $(BINDIR)/q3map2.x86_64 \
-x $(BINDIR)/qdata3.x86_64 \
`find $(BINDIR)/modules -name "*.dylib" | xargs -I {} echo -x {}` \

View File

@ -1,552 +0,0 @@
$aseconvert models/mapobjects/spotlamp/spotlamp_x.ase
$exit
$aseconvert models/weapons2/machinegun/machinegun.ase -weapon
$aseconvert models/weapons2/bfg/bfg.ase -weapon
$aseconvert models/weapons2/railgun/railgun.ase -weapon
$aseconvert models/weapons2/shotgun/shotgun.ase -weapon
$aseconvert models/weapons2/meshes/chaingun.ase -weapon
$aseconvert models/weapons2/meshes/flamethrower.ase -weapon
$aseconvert models/weapons2/meshes/grapple.ase -weapon
$aseconvert models/weapons2/meshes/grenadel.ase -weapon
$aseconvert models/weapons2/meshes/lightning.ase -weapon
$aseconvert models/weapons2/meshes/plasma.ase -weapon
$aseconvert models/weapons2/meshes/railgun.ase -weapon
$aseconvert models/weapons2/meshes/ricochet.ase -weapon
$aseconvert models/weapons2/meshes/rocketl.ase -weapon
$aseconvert models/weapons2/meshes/shotgun.ase -weapon
$aseconvert models/mapobjects/chain1.ase
$aseconvert models/mapobjects/chain2.ase
$aseconvert models/mapobjects/chain3.ase
$aseconvert models/mapobjects/chain4.ase
$exit
$aseanimconvert models/players/light/bandolier/bandolier.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/light/brandon/4brandon.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/light/cash/4cash.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/light/doom/doom.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/light/shauna/shauna.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/tim/4tim.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/visor/4visor.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/xian/4xian.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/carmack/carmack.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/heavy/paulj/4paulj.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/heavy/brock/brock.ase -origin 0 0 24 -playerparms 75 138 140 1
$exit
// note: playerparms are "skipStart skipEnd maxUpperFrames maxHeadFrames"
$aseanimconvert models/players/medium/visor/4visor.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/visor/4visor.ase -lod 1 0 -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/visor/4visor.ase -lod 2 0 -origin 0 0 24 -playerparms 75 138 140 1
$aseconvert models/powerups/ammo/backpack.ase
$aseconvert models/weapons2/meshes/assault.ase -weapon
$aseconvert models/weapons2/meshes/chaingun.ase -weapon
$aseconvert models/weapons2/meshes/flamethrower.ase -weapon
$aseconvert models/weapons2/meshes/grapple.ase -weapon
$aseconvert models/weapons2/meshes/grenadel.ase -weapon
$aseconvert models/weapons2/meshes/lightning.ase -weapon
$aseconvert models/weapons2/meshes/plasma.ase -weapon
$aseconvert models/weapons2/meshes/railgun.ase -weapon
$aseconvert models/weapons2/meshes/ricochet.ase -weapon
$aseconvert models/weapons2/meshes/rocketl.ase -weapon
$aseconvert models/weapons2/meshes/shotgun.ase -weapon
$aseconvert models/mapobjects/arenalogo.ase
//
// talk sprite
//
$modelname sprites/balloon
$cd sprites
$spritebase -8 -8 16 16
$spriteshader sprites/balloon3.tga
// plasma ball sprite
$modelname sprites/plasma
$cd sprites
$spritebase -16 -16 32 32
$spriteshader sprites/plasma1.tga
$spriteshader sprites/plasma2.tga
//
// player models
// note: playerparms are "skipStart skipEnd maxUpperFrames maxHeadFrames"
//
$aseanimconvert models/players/light/bandolier/bandolier.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/light/brandon/4brandon.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/light/cash/4cash.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/light/doom/doom.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/light/shauna/shauna.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/tim/4tim.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/visor/4visor.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/xian/4xian.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/medium/carmack/carmack.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/heavy/paulj/4paulj.ase -origin 0 0 24 -playerparms 75 138 140 1
$aseanimconvert models/players/heavy/brock/brock.ase -origin 0 0 24 -playerparms 75 138 140 1
//
// weaphits
//
$modelname models/weaphits/bullet
$cd models/weaphits
$base bullet01.3ds
$frame bullet01.3ds
$frame bullet02.3ds
$frame bullet03.3ds
$frame bullet04.3ds
$frame bullet05.3ds
$frame bullet06.3ds
$skin bullet01.3ds
$skin bullet03.3ds
$skin bullet05.3ds
$modelname models/weaphits/ring01
$cd models/weaphits
$base ring01_1.3ds
$frame ring01_1.3ds
$frame ring01_2.3ds
$frame ring01_3.3ds
$frame ring01_4.3ds
$frame ring01_5.3ds
$frame ring01_6.3ds
$skin ring01_1.3ds
$skin ring01_3.3ds
$skin ring01_5.3ds
$modelname models/weaphits/ring02
$cd models/weaphits
$base ring02_1.3ds
$frame ring02_1.3ds
$frame ring02_2.3ds
$frame ring02_3.3ds
$frame ring02_4.3ds
$frame ring02_5.3ds
$frame ring02_6.3ds
$skin ring02_1.3ds
$skin ring02_3.3ds
$skin ring02_5.3ds
$modelname models/weaphits/boomgra
$cd models/weaphits
$base boomgra1.3ds
$frame boomgra1.3ds
$frame boomgra2.3ds
$frame boomgra3.3ds
$frame boomgra4.3ds
$frame boomgra5.3ds
$frame boomgra6.3ds
$skin boomgra1.3ds
$skin boomgra3.3ds
$skin boomgra5.3ds
$modelname models/weaphits/boom01
$cd models/weaphits
$base boom01_1.3ds
$frame boom01_1.3ds
$frame boom01_2.3ds
$frame boom01_3.3ds
$frame boom01_4.3ds
$frame boom01_5.3ds
$frame boom01_6.3ds
$skin boom01_1.3ds
$skin boom01_3.3ds
$skin boom01_5.3ds
$modelname models/weaphits/boom02
$cd models/weaphits
$base boom02_1.3ds
$frame boom02_1.3ds
$frame boom02_2.3ds
$frame boom02_3.3ds
$frame boom02_4.3ds
$frame boom02_5.3ds
$frame boom02_6.3ds
$skin boom02_1.3ds
$skin boom02_3.3ds
$skin boom02_5.3ds
$modelname models/weaphits/boom03
$cd models/weaphits
$base boom03_1.3ds
$frame boom03_1.3ds
$frame boom03_2.3ds
$frame boom03_3.3ds
$frame boom03_4.3ds
$frame boom03_5.3ds
$frame boom03_6.3ds
$skin boom03_1.3ds
$skin boom03_3.3ds
$skin boom03_5.3ds
$modelname models/weaphits/boom04
$cd models/weaphits
$base boom04_1.3ds
$frame boom04_1.3ds
$frame boom04_2.3ds
$frame boom04_3.3ds
$frame boom04_4.3ds
$frame boom04_5.3ds
$frame boom04_6.3ds
$skin boom04_1.3ds
$skin boom04_3.3ds
$skin boom04_5.3ds
$modelname models/weaphits/boom05
$cd models/weaphits
$base boom05_1.3ds
$frame boom05_1.3ds
$frame boom05_2.3ds
$frame boom05_3.3ds
$frame boom05_4.3ds
$frame boom05_5.3ds
$frame boom05_6.3ds
$skin boom05_1.3ds
$skin boom05_3.3ds
$skin boom05_5.3ds
//
// point powerups
//
$aseconvert models/powerups/points/small.ase
$aseconvert models/powerups/points/medium.ase
$aseconvert models/powerups/points/large.ase
//
// ammo
//
$aseconvert models\powerups\ammo\bfgam.ASE
$aseconvert models\powerups\ammo\bfgam_1.ASE
$aseconvert models\powerups\ammo\bouncyam.ASE
$aseconvert models\powerups\ammo\bouncyam_1.ASE
$aseconvert models\powerups\ammo\carbineam.ASE
$aseconvert models\powerups\ammo\carbineam_1.ASE
$aseconvert models\powerups\ammo\flameam.ASE
$aseconvert models\powerups\ammo\flameam_1.ASE
$aseconvert models\powerups\ammo\grenadeam.ASE
$aseconvert models\powerups\ammo\grenadeam_1.ASE
$aseconvert models\powerups\ammo\lightningam.ASE
$aseconvert models\powerups\ammo\lightningam_1.ASE
$aseconvert models\powerups\ammo\machinegunam.ASE
$aseconvert models\powerups\ammo\machinegunam_1.ASE
$aseconvert models\powerups\ammo\plasmaam.ASE
$aseconvert models\powerups\ammo\plasmaam_1.ASE
$aseconvert models\powerups\ammo\railgunam.ASE
$aseconvert models\powerups\ammo\railgunam_1.ASE
$aseconvert models\powerups\ammo\rocketam.ASE
$aseconvert models\powerups\ammo\rocketam_1.ASE
$aseconvert models\powerups\ammo\shotgunam.ASE
$aseconvert models\powerups\ammo\shotgunam_1.ASE
$aseconvert models/powerups/ammo/backpack.ase
//
// missiles
//
$modelname models/ammo/plasma/plasma
$cd models/ammo/plasma
$base plasma1.3ds
$frame plasma1.3ds
$skin plasma1.3ds
$modelname models/ammo/laser/laser
$cd models/ammo/laser
$base laser1.3ds
$frame laser1.3ds
$skin laser1.3ds
$modelname models/ammo/rocket/rocket
$cd models/ammo/rocket
$base rocket1.3ds
$frame rocket1.3ds
$skin rocket1.3ds
$skin rocket2.3ds
$aseconvert models/ammo/grenade1.ase
$aseconvert models/explosions/smoke2.ase
//
// map objects
//
$aseconvert models/mapobjects/ceilinglamp1.ase
$aseconvert models/mapobjects/ceilinglamp2.ase
$aseconvert models/mapobjects/chain1.ase
$aseconvert models/mapobjects/chain2.ase
$aseconvert models/mapobjects/chain3.ase
$aseconvert models/mapobjects/chain4.ase
$aseconvert models/mapobjects/crux.ase
$aseconvert models/mapobjects/floorlamp1.ase
$aseconvert models/mapobjects/floorlamp2.ase
$aseconvert models/mapobjects/hook.ase
$aseconvert models/mapobjects/impale.ase
$aseconvert models/mapobjects/standinglamp1.ase
$aseconvert models/mapobjects/standinglamp2.ase
$aseconvert models/mapobjects/standinglamp3.ase
$aseconvert models/mapobjects/walllamp1.ase
$aseconvert models/mapobjects/walllamp2.ase
$aseconvert models/mapobjects/walllamp3.ase
//
// objects
//
$aseconvert models/objects/dmspot.ase -origin 0 0 24
$aseconvert models/objects/box01.ase
//
// weapons
//
$aseconvert models/weapons2/meshes/assault.ase -weapon
$aseconvert models/weapons2/meshes/bfg.ase -weapon
$aseconvert models/weapons2/meshes/chaingun.ase -weapon
$aseconvert models/weapons2/meshes/flamethrower.ase -weapon
$aseconvert models/weapons2/meshes/grapple.ase -weapon
$aseconvert models/weapons2/meshes/grenadel.ase -weapon
$aseconvert models/weapons2/meshes/lightning.ase -weapon
$aseconvert models/weapons2/meshes/plasma.ase -weapon
$aseconvert models/weapons2/meshes/railgun.ase -weapon
$aseconvert models/weapons2/meshes/ricochet.ase -weapon
$aseconvert models/weapons2/meshes/rocketl.ase -weapon
$aseconvert models/weapons2/meshes/shotgun.ase -weapon
//
// blood
//
$modelname models/weaphits/blood
$cd models/weaphits
$spritebase -16 -16 32 32
$spriteshader models/weaphits/blood201.tga
$spriteshader models/weaphits/blood202.tga
$spriteshader models/weaphits/blood203.tga
$spriteshader models/weaphits/blood204.tga
$spriteshader models/weaphits/blood205.tga
//
// missiles
//
$modelname models/ammo/plasma/plasma
$cd models/ammo/plasma
$base plasma1.3ds
$frame plasma1.3ds
$skin plasma1.3ds
$modelname models/ammo/laser/laser
$cd models/ammo/laser
$base laser1.3ds
$frame laser1.3ds
$skin laser1.3ds
$modelname models/ammo/rocket/rocket
$cd models/ammo/rocket
$base rocket1.3ds
$frame rocket1.3ds
$skin rocket1.3ds
$skin rocket2.3ds
// weaphits
$modelname models/weaphits/bullet
$cd models/weaphits
$base bullet01.3ds
$frame bullet01.3ds
$frame bullet02.3ds
$frame bullet03.3ds
$frame bullet04.3ds
$frame bullet05.3ds
$frame bullet06.3ds
$skin bullet01.3ds
$skin bullet03.3ds
$skin bullet05.3ds
$modelname models/weaphits/ring01
$cd models/weaphits
$base ring01_1.3ds
$frame ring01_1.3ds
$frame ring01_2.3ds
$frame ring01_3.3ds
$frame ring01_4.3ds
$frame ring01_5.3ds
$frame ring01_6.3ds
$skin ring01_1.3ds
$skin ring01_3.3ds
$skin ring01_5.3ds
$modelname models/weaphits/ring02
$cd models/weaphits
$base ring02_1.3ds
$frame ring02_1.3ds
$frame ring02_2.3ds
$frame ring02_3.3ds
$frame ring02_4.3ds
$frame ring02_5.3ds
$frame ring02_6.3ds
$skin ring02_1.3ds
$skin ring02_3.3ds
$skin ring02_5.3ds
$modelname models/weaphits/boomgra
$cd models/weaphits
$base boomgra1.3ds
$frame boomgra1.3ds
$frame boomgra2.3ds
$frame boomgra3.3ds
$frame boomgra4.3ds
$frame boomgra5.3ds
$frame boomgra6.3ds
$skin boomgra1.3ds
$skin boomgra3.3ds
$skin boomgra5.3ds
$modelname models/weaphits/boom01
$cd models/weaphits
$base boom01_1.3ds
$frame boom01_1.3ds
$frame boom01_2.3ds
$frame boom01_3.3ds
$frame boom01_4.3ds
$frame boom01_5.3ds
$frame boom01_6.3ds
$skin boom01_1.3ds
$skin boom01_3.3ds
$skin boom01_5.3ds
$modelname models/weaphits/boom02
$cd models/weaphits
$base boom02_1.3ds
$frame boom02_1.3ds
$frame boom02_2.3ds
$frame boom02_3.3ds
$frame boom02_4.3ds
$frame boom02_5.3ds
$frame boom02_6.3ds
$skin boom02_1.3ds
$skin boom02_3.3ds
$skin boom02_5.3ds
$modelname models/weaphits/boom03
$cd models/weaphits
$base boom03_1.3ds
$frame boom03_1.3ds
$frame boom03_2.3ds
$frame boom03_3.3ds
$frame boom03_4.3ds
$frame boom03_5.3ds
$frame boom03_6.3ds
$skin boom03_1.3ds
$skin boom03_3.3ds
$skin boom03_5.3ds
$modelname models/weaphits/boom04
$cd models/weaphits
$base boom04_1.3ds
$frame boom04_1.3ds
$frame boom04_2.3ds
$frame boom04_3.3ds
$frame boom04_4.3ds
$frame boom04_5.3ds
$frame boom04_6.3ds
$skin boom04_1.3ds
$skin boom04_3.3ds
$skin boom04_5.3ds
$modelname models/weaphits/boom05
$cd models/weaphits
$base boom05_1.3ds
$frame boom05_1.3ds
$frame boom05_2.3ds
$frame boom05_3.3ds
$frame boom05_4.3ds
$frame boom05_5.3ds
$frame boom05_6.3ds
$skin boom05_1.3ds
$skin boom05_3.3ds
$skin boom05_5.3ds
//
// armor
//
$aseconvert models/powerups/armor/armor_red.ase
$aseconvert models/powerups/armor/armor_yel.ase
$aseconvert models/powerups/armor/armor_grn.ase
$aseconvert models/powerups/armor/shard.ase
$aseconvert models/powerups/armor/shard_sphere.ase
$aseconvert models/powerups/armor/shard_sphere_1.ase
//
// health
//
$aseconvert models/powerups/health/small.ase
$aseconvert models/powerups/health/small_1.ase
$aseconvert models/powerups/health/medium.ase
$aseconvert models/powerups/health/medium_1.ase
$aseconvert models/powerups/health/large.ase
$aseconvert models/powerups/health/large_1.ase
$aseconvert models/powerups/health/mega.ase
$aseconvert models/powerups/health/mega_1.ase
//
// holdable powerups
//
$aseconvert models/powerups/holdable/ringodeth.ase
$aseconvert models/powerups/holdable/medkit.ase
$aseconvert models/powerups/holdable/teleporter.ase
//
// instant powerups
//
$aseconvert models/powerups/instant/enviro.ase
$aseconvert models/powerups/instant/enviro_1.ase
$aseconvert models/powerups/instant/enviro_ring.ase
$aseconvert models/powerups/instant/enviro_ring_1.ase
$aseconvert models/powerups/instant/flight.ase
$aseconvert models/powerups/instant/flight_1.ase
$aseconvert models/powerups/instant/flight_ring.ase
$aseconvert models/powerups/instant/flight_ring_1.ase
$aseconvert models/powerups/instant/haste.ase
$aseconvert models/powerups/instant/haste_1.ase
$aseconvert models/powerups/instant/haste_ring.ase
$aseconvert models/powerups/instant/haste_ring_1.ase
$aseconvert models/powerups/instant/invis.ase
$aseconvert models/powerups/instant/invis_1.ase
$aseconvert models/powerups/instant/invis_ring.ase
$aseconvert models/powerups/instant/invis_ring_1.ase
$aseconvert models/powerups/instant/scan.ase
$aseconvert models/powerups/instant/scan_1.ase
$aseconvert models/powerups/instant/scan_ring.ase
$aseconvert models/powerups/instant/scan_ring_1.ase
$aseconvert models/powerups/instant/quad.ase
$aseconvert models/powerups/instant/quad_1.ase
$aseconvert models/powerups/instant/quad_ring.ase
$aseconvert models/powerups/instant/quad_ring_1.ase
$aseconvert models/powerups/instant/regen.ase
$aseconvert models/powerups/instant/regen_1.ase
$aseconvert models/powerups/instant/regen_ring.ase
$aseconvert models/powerups/instant/regen_ring_1.ase
$exit
//
// maps
//
$maps test_box test_items mirror mirror2
//
// misc
//
$file q3default.cfg

View File

@ -1,862 +0,0 @@
/*
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 "aselib.h"
#include "cmdlib.h"
#include "inout.h"
#include "qstringops.h"
#include "qpathops.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_ASE_MATERIALS 32
#define MAX_ASE_OBJECTS 64
#define MAX_ASE_ANIMATIONS 32
#define MAX_ASE_ANIMATION_FRAMES 512
#define VERBOSE( x ) { if ( ase.verbose ) { Sys_Printf x ; } }
typedef struct
{
float x, y, z;
float nx, ny, nz;
float s, t;
} aseVertex_t;
typedef struct
{
float s, t;
} aseTVertex_t;
typedef int aseFace_t[3];
typedef struct
{
int numFaces;
int numVertexes;
int numTVertexes;
int timeValue;
aseVertex_t *vertexes;
aseTVertex_t *tvertexes;
aseFace_t *faces, *tfaces;
int currentFace, currentVertex;
} aseMesh_t;
typedef struct
{
int numFrames;
aseMesh_t frames[MAX_ASE_ANIMATION_FRAMES];
int currentFrame;
} aseMeshAnimation_t;
typedef struct
{
char name[128];
} aseMaterial_t;
/*
** contains the animate sequence of a single surface
** using a single material
*/
typedef struct
{
char name[128];
int materialRef;
int numAnimations;
aseMeshAnimation_t anim;
} aseGeomObject_t;
typedef struct
{
int numMaterials;
aseMaterial_t materials[MAX_ASE_MATERIALS];
aseGeomObject_t objects[MAX_ASE_OBJECTS];
char *buffer;
char *curpos;
int len;
int currentObject;
bool verbose;
bool grabAnims;
} ase_t;
static char s_token[1024];
static ase_t ase;
static char gl_filename[1024];
static void ASE_Process( void );
static void ASE_FreeGeomObject( int ndx );
/*
** ASE_Load
*/
void ASE_Load( const char *filename, bool verbose, bool grabAnims ){
FILE *fp = fopen( filename, "rb" );
if ( !fp ) {
Error( "File not found '%s'", filename );
}
memset( &ase, 0, sizeof( ase ) );
ase.verbose = verbose;
ase.grabAnims = grabAnims;
ase.len = Q_filelength( fp );
ase.curpos = ase.buffer = safe_malloc( ase.len );
Sys_Printf( "Processing '%s'\n", filename );
if ( fread( ase.buffer, ase.len, 1, fp ) != 1 ) {
fclose( fp );
Error( "fread() != -1 for '%s'", filename );
}
fclose( fp );
strcpy( gl_filename, filename );
ASE_Process();
}
/*
** ASE_Free
*/
void ASE_Free( void ){
int i;
for ( i = 0; i < ase.currentObject; i++ )
{
ASE_FreeGeomObject( i );
}
}
/*
** ASE_GetNumSurfaces
*/
int ASE_GetNumSurfaces( void ){
return ase.currentObject;
}
/*
** ASE_GetSurfaceName
*/
const char *ASE_GetSurfaceName( int which ){
aseGeomObject_t *pObject = &ase.objects[which];
if ( !pObject->anim.numFrames ) {
return 0;
}
return pObject->name;
}
/*
** ASE_GetSurfaceAnimation
**
** Returns an animation (sequence of polysets)
*/
polyset_t *ASE_GetSurfaceAnimation( int which, int *pNumFrames, int skipFrameStart, int skipFrameEnd, int maxFrames ){
aseGeomObject_t *pObject = &ase.objects[which];
polyset_t *psets;
int numFramesInAnimation;
int numFramesToKeep;
int i, f;
if ( !pObject->anim.numFrames ) {
return 0;
}
if ( pObject->anim.numFrames > maxFrames && maxFrames != -1 ) {
numFramesInAnimation = maxFrames;
}
else
{
numFramesInAnimation = pObject->anim.numFrames;
if ( maxFrames != -1 ) {
Sys_Printf( "WARNING: ASE_GetSurfaceAnimation maxFrames > numFramesInAnimation\n" );
}
}
if ( skipFrameEnd != -1 ) {
numFramesToKeep = numFramesInAnimation - ( skipFrameEnd - skipFrameStart + 1 );
}
else{
numFramesToKeep = numFramesInAnimation;
}
*pNumFrames = numFramesToKeep;
psets = safe_calloc( sizeof( polyset_t ) * numFramesToKeep );
for ( f = 0, i = 0; i < numFramesInAnimation; i++ )
{
int t;
aseMesh_t *pMesh = &pObject->anim.frames[i];
if ( skipFrameStart != -1 ) {
if ( i >= skipFrameStart && i <= skipFrameEnd ) {
continue;
}
}
strcpy( psets[f].name, pObject->name );
strcpy( psets[f].materialname, ase.materials[pObject->materialRef].name );
psets[f].triangles = safe_calloc( sizeof( triangle_t ) * pObject->anim.frames[i].numFaces );
psets[f].numtriangles = pObject->anim.frames[i].numFaces;
for ( t = 0; t < pObject->anim.frames[i].numFaces; t++ )
{
int k;
for ( k = 0; k < 3; k++ )
{
psets[f].triangles[t].verts[k][0] = pMesh->vertexes[pMesh->faces[t][k]].x;
psets[f].triangles[t].verts[k][1] = pMesh->vertexes[pMesh->faces[t][k]].y;
psets[f].triangles[t].verts[k][2] = pMesh->vertexes[pMesh->faces[t][k]].z;
if ( pMesh->tvertexes && pMesh->tfaces ) {
psets[f].triangles[t].texcoords[k][0] = pMesh->tvertexes[pMesh->tfaces[t][k]].s;
psets[f].triangles[t].texcoords[k][1] = pMesh->tvertexes[pMesh->tfaces[t][k]].t;
}
}
}
f++;
}
return psets;
}
static void ASE_FreeGeomObject( int ndx ){
aseGeomObject_t *pObject;
int i;
pObject = &ase.objects[ndx];
for ( i = 0; i < pObject->anim.numFrames; i++ )
{
if ( pObject->anim.frames[i].vertexes ) {
free( pObject->anim.frames[i].vertexes );
}
if ( pObject->anim.frames[i].tvertexes ) {
free( pObject->anim.frames[i].tvertexes );
}
if ( pObject->anim.frames[i].faces ) {
free( pObject->anim.frames[i].faces );
}
if ( pObject->anim.frames[i].tfaces ) {
free( pObject->anim.frames[i].tfaces );
}
}
memset( pObject, 0, sizeof( *pObject ) );
}
static aseMesh_t *ASE_GetCurrentMesh( void ){
aseGeomObject_t *pObject;
if ( ase.currentObject >= MAX_ASE_OBJECTS ) {
Error( "Too many GEOMOBJECTs" );
return 0; // never called
}
pObject = &ase.objects[ase.currentObject];
if ( pObject->anim.currentFrame >= MAX_ASE_ANIMATION_FRAMES ) {
Error( "Too many MESHes" );
return 0;
}
return &pObject->anim.frames[pObject->anim.currentFrame];
}
static int CharIsTokenDelimiter( int ch ){
if ( ch <= 32 ) {
return 1;
}
return 0;
}
static int ASE_GetToken( bool restOfLine ){
int i = 0;
if ( ase.buffer == 0 ) {
return 0;
}
if ( ( ase.curpos - ase.buffer ) == ase.len ) {
return 0;
}
// skip over crap
while ( ( ( ase.curpos - ase.buffer ) < ase.len ) &&
( *ase.curpos <= 32 ) )
{
ase.curpos++;
}
while ( ( ase.curpos - ase.buffer ) < ase.len )
{
s_token[i] = *ase.curpos;
ase.curpos++;
i++;
if ( ( CharIsTokenDelimiter( s_token[i - 1] ) && !restOfLine ) ||
( ( s_token[i - 1] == '\n' ) || ( s_token[i - 1] == '\r' ) ) ) {
s_token[i - 1] = '\0';
break;
}
}
s_token[i] = '\0';
return 1;
}
static void ASE_ParseBracedBlock( void ( *parser )( const char *token ) ){
int indent = 0;
while ( ASE_GetToken( false ) )
{
if ( strEqual( s_token, "{" ) ) {
indent++;
}
else if ( strEqual( s_token, "}" ) ) {
--indent;
if ( indent == 0 ) {
break;
}
else if ( indent < 0 ) {
Error( "Unexpected '}'" );
}
}
else
{
if ( parser ) {
parser( s_token );
}
}
}
}
static void ASE_SkipEnclosingBraces( void ){
int indent = 0;
while ( ASE_GetToken( false ) )
{
if ( strEqual( s_token, "{" ) ) {
indent++;
}
else if ( strEqual( s_token, "}" ) ) {
indent--;
if ( indent == 0 ) {
break;
}
else if ( indent < 0 ) {
Error( "Unexpected '}'" );
}
}
}
}
static void ASE_SkipRestOfLine( void ){
ASE_GetToken( true );
}
static void ASE_KeyMAP_DIFFUSE( const char *token ){
char bitmap[1024];
char filename[1024];
strcpy( filename, gl_filename );
if ( strEqual( token, "*BITMAP" ) ) {
ASE_GetToken( false );
// the purpose of this whole chunk of code below is to extract the relative path
// from a full path in the ASE
strcpy( bitmap, s_token + 1 );
if ( strchr( bitmap, '"' ) ) {
*strchr( bitmap, '"' ) = 0;
}
/* convert backslash to slash */
FixDOSName( bitmap );
/* remove filename from path */
strClear( path_get_last_separator( filename ) );
/* replaces a relative path with a full path */
if ( strEqualPrefix( bitmap, "../" ) ) {
while ( strEqualPrefix( bitmap, "../" ) )
{
/* remove last item from path */
strClear( path_get_last_separator( filename ) );
memmove( bitmap, &bitmap[3], sizeof( bitmap ) - 3 );
}
strcat( filename, "/" );
strcat( filename, bitmap );
strcpy( bitmap, filename );
}
if ( strstr( bitmap, gamedir ) ) {
strcpy( ase.materials[ase.numMaterials].name, strstr( bitmap, gamedir ) + strlen( gamedir ) );
Sys_Printf( "material name: \'%s\'\n", ase.materials[ase.numMaterials].name );
}
else
{
sprintf( ase.materials[ase.numMaterials].name, "(not converted: '%s')", bitmap );
Sys_Printf( "WARNING: illegal material name '%s'\n", bitmap );
}
}
else
{
}
}
static void ASE_KeyMATERIAL( const char *token ){
if ( strEqual( token, "*MAP_DIFFUSE" ) ) {
ASE_ParseBracedBlock( ASE_KeyMAP_DIFFUSE );
}
else
{
}
}
static void ASE_KeyMATERIAL_LIST( const char *token ){
if ( strEqual( token, "*MATERIAL_COUNT" ) ) {
ASE_GetToken( false );
VERBOSE( ( "..num materials: %s\n", s_token ) );
if ( atoi( s_token ) > MAX_ASE_MATERIALS ) {
Error( "Too many materials!" );
}
ase.numMaterials = 0;
}
else if ( strEqual( token, "*MATERIAL" ) ) {
VERBOSE( ( "..material %d ", ase.numMaterials ) );
ASE_ParseBracedBlock( ASE_KeyMATERIAL );
ase.numMaterials++;
}
}
static void ASE_KeyMESH_VERTEX_LIST( const char *token ){
aseMesh_t *pMesh = ASE_GetCurrentMesh();
if ( strEqual( token, "*MESH_VERTEX" ) ) {
ASE_GetToken( false ); // skip number
ASE_GetToken( false );
pMesh->vertexes[pMesh->currentVertex].y = atof( s_token );
ASE_GetToken( false );
pMesh->vertexes[pMesh->currentVertex].x = -atof( s_token );
ASE_GetToken( false );
pMesh->vertexes[pMesh->currentVertex].z = atof( s_token );
pMesh->currentVertex++;
if ( pMesh->currentVertex > pMesh->numVertexes ) {
Error( "pMesh->currentVertex >= pMesh->numVertexes" );
}
}
else
{
Error( "Unknown token '%s' while parsing MESH_VERTEX_LIST", token );
}
}
static void ASE_KeyMESH_FACE_LIST( const char *token ){
aseMesh_t *pMesh = ASE_GetCurrentMesh();
if ( strEqual( token, "*MESH_FACE" ) ) {
ASE_GetToken( false ); // skip face number
ASE_GetToken( false ); // skip label
ASE_GetToken( false ); // first vertex
pMesh->faces[pMesh->currentFace][0] = atoi( s_token );
ASE_GetToken( false ); // skip label
ASE_GetToken( false ); // second vertex
pMesh->faces[pMesh->currentFace][2] = atoi( s_token );
ASE_GetToken( false ); // skip label
ASE_GetToken( false ); // third vertex
pMesh->faces[pMesh->currentFace][1] = atoi( s_token );
ASE_GetToken( true );
/*
if ( ( p = strstr( s_token, "*MESH_MTLID" ) ) != 0 )
{
p += strlen( "*MESH_MTLID" ) + 1;
mtlID = atoi( p );
}
else
{
Error( "No *MESH_MTLID found for face!" );
}
*/
pMesh->currentFace++;
}
else
{
Error( "Unknown token '%s' while parsing MESH_FACE_LIST", token );
}
}
static void ASE_KeyTFACE_LIST( const char *token ){
aseMesh_t *pMesh = ASE_GetCurrentMesh();
if ( strEqual( token, "*MESH_TFACE" ) ) {
int a, b, c;
ASE_GetToken( false );
ASE_GetToken( false );
a = atoi( s_token );
ASE_GetToken( false );
c = atoi( s_token );
ASE_GetToken( false );
b = atoi( s_token );
pMesh->tfaces[pMesh->currentFace][0] = a;
pMesh->tfaces[pMesh->currentFace][1] = b;
pMesh->tfaces[pMesh->currentFace][2] = c;
pMesh->currentFace++;
}
else
{
Error( "Unknown token '%s' in MESH_TFACE", token );
}
}
static void ASE_KeyMESH_TVERTLIST( const char *token ){
aseMesh_t *pMesh = ASE_GetCurrentMesh();
if ( strEqual( token, "*MESH_TVERT" ) ) {
char u[80], v[80], w[80];
ASE_GetToken( false );
ASE_GetToken( false );
strcpy( u, s_token );
ASE_GetToken( false );
strcpy( v, s_token );
ASE_GetToken( false );
strcpy( w, s_token );
pMesh->tvertexes[pMesh->currentVertex].s = atof( u );
pMesh->tvertexes[pMesh->currentVertex].t = 1.0f - atof( v );
pMesh->currentVertex++;
if ( pMesh->currentVertex > pMesh->numTVertexes ) {
Error( "pMesh->currentVertex > pMesh->numTVertexes" );
}
}
else
{
Error( "Unknown token '%s' while parsing MESH_TVERTLIST", token );
}
}
static void ASE_KeyMESH( const char *token ){
aseMesh_t *pMesh = ASE_GetCurrentMesh();
if ( strEqual( token, "*TIMEVALUE" ) ) {
ASE_GetToken( false );
pMesh->timeValue = atoi( s_token );
VERBOSE( ( ".....timevalue: %d\n", pMesh->timeValue ) );
}
else if ( strEqual( token, "*MESH_NUMVERTEX" ) ) {
ASE_GetToken( false );
pMesh->numVertexes = atoi( s_token );
VERBOSE( ( ".....TIMEVALUE: %d\n", pMesh->timeValue ) );
VERBOSE( ( ".....num vertexes: %d\n", pMesh->numVertexes ) );
}
else if ( strEqual( token, "*MESH_NUMFACES" ) ) {
ASE_GetToken( false );
pMesh->numFaces = atoi( s_token );
VERBOSE( ( ".....num faces: %d\n", pMesh->numFaces ) );
}
else if ( strEqual( token, "*MESH_NUMTVFACES" ) ) {
ASE_GetToken( false );
if ( atoi( s_token ) != pMesh->numFaces ) {
Error( "MESH_NUMTVFACES != MESH_NUMFACES" );
}
}
else if ( strEqual( token, "*MESH_NUMTVERTEX" ) ) {
ASE_GetToken( false );
pMesh->numTVertexes = atoi( s_token );
VERBOSE( ( ".....num tvertexes: %d\n", pMesh->numTVertexes ) );
}
else if ( strEqual( token, "*MESH_VERTEX_LIST" ) ) {
pMesh->vertexes = safe_calloc( sizeof( aseVertex_t ) * pMesh->numVertexes );
pMesh->currentVertex = 0;
VERBOSE( ( ".....parsing MESH_VERTEX_LIST\n" ) );
ASE_ParseBracedBlock( ASE_KeyMESH_VERTEX_LIST );
}
else if ( strEqual( token, "*MESH_TVERTLIST" ) ) {
pMesh->currentVertex = 0;
pMesh->tvertexes = safe_calloc( sizeof( aseTVertex_t ) * pMesh->numTVertexes );
VERBOSE( ( ".....parsing MESH_TVERTLIST\n" ) );
ASE_ParseBracedBlock( ASE_KeyMESH_TVERTLIST );
}
else if ( strEqual( token, "*MESH_FACE_LIST" ) ) {
pMesh->faces = safe_calloc( sizeof( aseFace_t ) * pMesh->numFaces );
pMesh->currentFace = 0;
VERBOSE( ( ".....parsing MESH_FACE_LIST\n" ) );
ASE_ParseBracedBlock( ASE_KeyMESH_FACE_LIST );
}
else if ( strEqual( token, "*MESH_TFACELIST" ) ) {
pMesh->tfaces = safe_calloc( sizeof( aseFace_t ) * pMesh->numFaces );
pMesh->currentFace = 0;
VERBOSE( ( ".....parsing MESH_TFACE_LIST\n" ) );
ASE_ParseBracedBlock( ASE_KeyTFACE_LIST );
}
else if ( strEqual( token, "*MESH_NORMALS" ) ) {
ASE_ParseBracedBlock( 0 );
}
}
static void ASE_KeyMESH_ANIMATION( const char *token ){
aseMesh_t *pMesh = ASE_GetCurrentMesh();
// loads a single animation frame
if ( strEqual( token, "*MESH" ) ) {
VERBOSE( ( "...found MESH\n" ) );
assert( pMesh->faces == 0 );
assert( pMesh->vertexes == 0 );
assert( pMesh->tvertexes == 0 );
memset( pMesh, 0, sizeof( *pMesh ) );
ASE_ParseBracedBlock( ASE_KeyMESH );
if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES ) {
Error( "Too many animation frames" );
}
}
else
{
Error( "Unknown token '%s' while parsing MESH_ANIMATION", token );
}
}
static void ASE_KeyGEOMOBJECT( const char *token ){
if ( strEqual( token, "*NODE_NAME" ) ) {
char *name = ase.objects[ase.currentObject].name;
ASE_GetToken( true );
VERBOSE( ( " %s\n", s_token ) );
strcpy( name, s_token + 1 );
if ( NULL != strchr( name, '"' ) ) {
strClear( strchr( name, '"' ) );
}
if ( strEqualPrefix( name, "tag" ) ) {
while ( strchr( name, '_' ) != strrchr( name, '_' ) )
{
strClear( strrchr( name, '_' ) );
}
while ( strrchr( name, ' ' ) )
{
strClear( strrchr( name, ' ' ) );
}
}
}
else if ( strEqual( token, "*NODE_PARENT" ) ) {
ASE_SkipRestOfLine();
}
// ignore unused data blocks
else if ( strEqual( token, "*NODE_TM" ) ||
strEqual( token, "*TM_ANIMATION" ) ) {
ASE_ParseBracedBlock( 0 );
}
// ignore regular meshes that aren't part of animation
else if ( strEqual( token, "*MESH" ) && !ase.grabAnims ) {
/*
if ( strstr( ase.objects[ase.currentObject].name, "tag_" ) == ase.objects[ase.currentObject].name )
{
s_forceStaticMesh = true;
ASE_ParseBracedBlock( ASE_KeyMESH );
s_forceStaticMesh = false;
}
*/
ASE_ParseBracedBlock( ASE_KeyMESH );
if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES ) {
Error( "Too many animation frames" );
}
ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
ase.objects[ase.currentObject].numAnimations++;
/*
// ignore meshes that aren't part of animations if this object isn't a
// a tag
else
{
ASE_ParseBracedBlock( 0 );
}
*/
}
// according to spec these are obsolete
else if ( strEqual( token, "*MATERIAL_REF" ) ) {
ASE_GetToken( false );
ase.objects[ase.currentObject].materialRef = atoi( s_token );
}
// loads a sequence of animation frames
else if ( strEqual( token, "*MESH_ANIMATION" ) ) {
if ( ase.grabAnims ) {
VERBOSE( ( "..found MESH_ANIMATION\n" ) );
if ( ase.objects[ase.currentObject].numAnimations ) {
Error( "Multiple MESH_ANIMATIONS within a single GEOM_OBJECT" );
}
ASE_ParseBracedBlock( ASE_KeyMESH_ANIMATION );
ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
ase.objects[ase.currentObject].numAnimations++;
}
else
{
ASE_SkipEnclosingBraces();
}
}
// skip unused info
else if ( strEqual( token, "*PROP_MOTIONBLUR" ) ||
strEqual( token, "*PROP_CASTSHADOW" ) ||
strEqual( token, "*PROP_RECVSHADOW" ) ) {
ASE_SkipRestOfLine();
}
}
static void ConcatenateObjects( aseGeomObject_t *pObjA, aseGeomObject_t *pObjB ){
}
static void CollapseObjects( void ){
int i;
int numObjects = ase.currentObject;
for ( i = 0; i < numObjects; i++ )
{
int j;
// skip tags
if ( strstr( ase.objects[i].name, "tag" ) == ase.objects[i].name ) {
continue;
}
if ( !ase.objects[i].numAnimations ) {
continue;
}
for ( j = i + 1; j < numObjects; j++ )
{
if ( strstr( ase.objects[j].name, "tag" ) == ase.objects[j].name ) {
continue;
}
if ( ase.objects[i].materialRef == ase.objects[j].materialRef ) {
if ( ase.objects[j].numAnimations ) {
ConcatenateObjects( &ase.objects[i], &ase.objects[j] );
}
}
}
}
}
/*
** ASE_Process
*/
static void ASE_Process( void ){
while ( ASE_GetToken( false ) )
{
if ( strEqual( s_token, "*3DSMAX_ASCIIEXPORT" ) ||
strEqual( s_token, "*COMMENT" ) ) {
ASE_SkipRestOfLine();
}
else if ( strEqual( s_token, "*SCENE" ) ) {
ASE_SkipEnclosingBraces();
}
else if ( strEqual( s_token, "*MATERIAL_LIST" ) ) {
VERBOSE( ( "MATERIAL_LIST\n" ) );
ASE_ParseBracedBlock( ASE_KeyMATERIAL_LIST );
}
else if ( strEqual( s_token, "*GEOMOBJECT" ) ) {
VERBOSE( ( "GEOMOBJECT" ) );
ASE_ParseBracedBlock( ASE_KeyGEOMOBJECT );
if ( strstr( ase.objects[ase.currentObject].name, "Bip" ) ||
strstr( ase.objects[ase.currentObject].name, "ignore_" ) ) {
ASE_FreeGeomObject( ase.currentObject );
VERBOSE( ( "(discarding BIP/ignore object)\n" ) );
}
else if ( ( strstr( ase.objects[ase.currentObject].name, "h_" ) != ase.objects[ase.currentObject].name ) &&
( strstr( ase.objects[ase.currentObject].name, "l_" ) != ase.objects[ase.currentObject].name ) &&
( strstr( ase.objects[ase.currentObject].name, "u_" ) != ase.objects[ase.currentObject].name ) &&
( strstr( ase.objects[ase.currentObject].name, "tag" ) != ase.objects[ase.currentObject].name ) &&
ase.grabAnims ) {
VERBOSE( ( "(ignoring improperly labeled object '%s')\n", ase.objects[ase.currentObject].name ) );
ASE_FreeGeomObject( ase.currentObject );
}
else
{
if ( ++ase.currentObject == MAX_ASE_OBJECTS ) {
Error( "Too many GEOMOBJECTs" );
}
}
}
else if ( s_token[0] ) {
Sys_Printf( "Unknown token '%s'\n", s_token );
}
}
if ( !ase.currentObject ) {
Error( "No animation data!" );
}
CollapseObjects();
}

View File

@ -1,29 +0,0 @@
/*
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 "polyset.h"
void ASE_Load( const char *filename, bool verbose, bool meshanims );
int ASE_GetNumSurfaces( void );
polyset_t *ASE_GetSurfaceAnimation( int ndx, int *numFrames, int skipFrameStart, int skipFrameEnd, int maxFrames );
const char *ASE_GetSurfaceName( int ndx );
void ASE_Free( void );

View File

@ -1,676 +0,0 @@
/*
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 "cmdlib.h"
#include "qstringops.h"
#include "mathlib.h"
#include "inout.h"
#include "bspfile.h"
#include "scriplib.h"
void GetLeafNums( void );
//=============================================================================
int bsp_version = Q3_BSP_VERSION;
int nummodels;
dmodel_t dmodels[MAX_MAP_MODELS];
int numShaders;
dshader_t dshaders[MAX_MAP_SHADERS];
int entdatasize;
char dentdata[MAX_MAP_ENTSTRING];
int numleafs;
dleaf_t dleafs[MAX_MAP_LEAFS];
int numplanes;
dplane_t dplanes[MAX_MAP_PLANES];
int numnodes;
dnode_t dnodes[MAX_MAP_NODES];
int numleafsurfaces;
int dleafsurfaces[MAX_MAP_LEAFFACES];
int numleafbrushes;
int dleafbrushes[MAX_MAP_LEAFBRUSHES];
int numbrushes;
dbrush_t dbrushes[MAX_MAP_BRUSHES];
int numbrushsides;
dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
int numLightBytes;
byte *lightBytes;
int numGridPoints;
byte *gridData;
int numVisBytes;
byte visBytes[MAX_MAP_VISIBILITY];
int numDrawVerts = 0;
int numDrawVertsBuffer = 0;
drawVert_t *drawVerts = NULL;
int numDrawIndexes;
int drawIndexes[MAX_MAP_DRAW_INDEXES];
int numDrawSurfaces;
int numDrawSurfacesBuffer = 0;
dsurface_t *drawSurfaces = NULL;
int numFogs;
dfog_t dfogs[MAX_MAP_FOGS];
void SetLightBytes( int n ){
free( lightBytes );
numLightBytes = n;
if ( n == 0 ) {
return;
}
lightBytes = safe_calloc( numLightBytes );
}
void SetGridPoints( int n ){
free( gridData );
numGridPoints = n;
if ( n == 0 ) {
return;
}
gridData = safe_calloc( numGridPoints * 8 );
}
void IncDrawVerts(){
numDrawVerts++;
if ( drawVerts == 0 ) {
numDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
drawVerts = safe_malloc( sizeof( drawVert_t ) * numDrawVertsBuffer );
}
else if ( numDrawVerts > numDrawVertsBuffer ) {
numDrawVertsBuffer *= 3; // multiply by 1.5
numDrawVertsBuffer /= 2;
if ( numDrawVertsBuffer > MAX_MAP_DRAW_VERTS ) {
numDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
}
drawVerts = void_ptr( realloc( drawVerts, sizeof( drawVert_t ) * numDrawVertsBuffer ) );
if ( !drawVerts ) {
Error( "realloc() failed (IncDrawVerts)" );
}
}
memset( drawVerts + ( numDrawVerts - 1 ), 0, sizeof( drawVert_t ) );
}
void SetDrawVerts( int n ){
free( drawVerts );
numDrawVerts =
numDrawVertsBuffer = n;
drawVerts = safe_calloc( sizeof( drawVert_t ) * numDrawVertsBuffer );
}
void SetDrawSurfacesBuffer(){
free( drawSurfaces );
numDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
drawSurfaces = safe_calloc( sizeof( dsurface_t ) * numDrawSurfacesBuffer );
}
void SetDrawSurfaces( int n ){
free( drawSurfaces );
numDrawSurfaces =
numDrawSurfacesBuffer = n;
drawSurfaces = safe_calloc( sizeof( dsurface_t ) * numDrawSurfacesBuffer );
}
void BspFilesCleanup(){
free( drawVerts );
free( drawSurfaces );
free( lightBytes );
free( gridData );
}
//=============================================================================
/*
=============
SwapBlock
If all values are 32 bits, this can be used to swap everything
=============
*/
void SwapBlock( int *block, int sizeOfBlock ) {
int i;
sizeOfBlock >>= 2;
for ( i = 0 ; i < sizeOfBlock ; i++ ) {
block[i] = LittleLong( block[i] );
}
}
/*
=============
SwapBSPFile
Byte swaps all data in a bsp file.
=============
*/
void SwapBSPFile( void ) {
int i;
// models
SwapBlock( (int *)dmodels, nummodels * sizeof( dmodels[0] ) );
// shaders (don't swap the name)
for ( i = 0 ; i < numShaders ; i++ ) {
dshaders[i].contentFlags = LittleLong( dshaders[i].contentFlags );
dshaders[i].surfaceFlags = LittleLong( dshaders[i].surfaceFlags );
}
// planes
SwapBlock( (int *)dplanes, numplanes * sizeof( dplanes[0] ) );
// nodes
SwapBlock( (int *)dnodes, numnodes * sizeof( dnodes[0] ) );
// leafs
SwapBlock( (int *)dleafs, numleafs * sizeof( dleafs[0] ) );
// leaffaces
SwapBlock( (int *)dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) );
// leafbrushes
SwapBlock( (int *)dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
// brushes
SwapBlock( (int *)dbrushes, numbrushes * sizeof( dbrushes[0] ) );
// brushsides
SwapBlock( (int *)dbrushsides, numbrushsides * sizeof( dbrushsides[0] ) );
// vis
( (int *)&visBytes )[0] = LittleLong( ( (int *)&visBytes )[0] );
( (int *)&visBytes )[1] = LittleLong( ( (int *)&visBytes )[1] );
// drawverts (don't swap colors )
for ( i = 0 ; i < numDrawVerts ; i++ ) {
drawVerts[i].lightmap[0] = LittleFloat( drawVerts[i].lightmap[0] );
drawVerts[i].lightmap[1] = LittleFloat( drawVerts[i].lightmap[1] );
drawVerts[i].st[0] = LittleFloat( drawVerts[i].st[0] );
drawVerts[i].st[1] = LittleFloat( drawVerts[i].st[1] );
drawVerts[i].xyz[0] = LittleFloat( drawVerts[i].xyz[0] );
drawVerts[i].xyz[1] = LittleFloat( drawVerts[i].xyz[1] );
drawVerts[i].xyz[2] = LittleFloat( drawVerts[i].xyz[2] );
drawVerts[i].normal[0] = LittleFloat( drawVerts[i].normal[0] );
drawVerts[i].normal[1] = LittleFloat( drawVerts[i].normal[1] );
drawVerts[i].normal[2] = LittleFloat( drawVerts[i].normal[2] );
}
// drawindexes
SwapBlock( (int *)drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) );
// drawsurfs
SwapBlock( (int *)drawSurfaces, numDrawSurfaces * sizeof( drawSurfaces[0] ) );
// fogs
for ( i = 0 ; i < numFogs ; i++ ) {
dfogs[i].brushNum = LittleLong( dfogs[i].brushNum );
dfogs[i].visibleSide = LittleLong( dfogs[i].visibleSide );
}
}
/*
=============
GetLumpElements
=============
*/
int GetLumpElements( dheader_t *header, int lump, int size ) {
int length;
length = header->lumps[lump].filelen;
if ( length % size ) {
Error( "LoadBSPFile: odd lump size" );
}
return length / size;
}
/*
=============
CopyLump
=============
*/
int CopyLump( dheader_t *header, int lump, void *dest, int size ) {
int length, ofs;
length = header->lumps[lump].filelen;
ofs = header->lumps[lump].fileofs;
if ( length == 0 ) {
return 0;
}
if ( length % size ) {
Error( "LoadBSPFile: odd lump size" );
}
memcpy( dest, (byte *)header + ofs, length );
return length / size;
}
/*
=============
LoadBSPFile
=============
*/
void LoadBSPFile( const char *filename ) {
dheader_t *header;
// load the file header
LoadFile( filename, (void **)&header );
// swap the header
SwapBlock( (int *)header, sizeof( *header ) );
if ( header->ident != BSP_IDENT ) {
Error( "%s is not a IBSP file", filename );
}
if ( header->version != bsp_version ) {
Error( "%s is version %i, not %i", filename, header->version, bsp_version );
}
numShaders = CopyLump( header, LUMP_SHADERS, dshaders, sizeof( dshader_t ) );
nummodels = CopyLump( header, LUMP_MODELS, dmodels, sizeof( dmodel_t ) );
numplanes = CopyLump( header, LUMP_PLANES, dplanes, sizeof( dplane_t ) );
numleafs = CopyLump( header, LUMP_LEAFS, dleafs, sizeof( dleaf_t ) );
numnodes = CopyLump( header, LUMP_NODES, dnodes, sizeof( dnode_t ) );
numleafsurfaces = CopyLump( header, LUMP_LEAFSURFACES, dleafsurfaces, sizeof( dleafsurfaces[0] ) );
numleafbrushes = CopyLump( header, LUMP_LEAFBRUSHES, dleafbrushes, sizeof( dleafbrushes[0] ) );
numbrushes = CopyLump( header, LUMP_BRUSHES, dbrushes, sizeof( dbrush_t ) );
numbrushsides = CopyLump( header, LUMP_BRUSHSIDES, dbrushsides, sizeof( dbrushside_t ) );
numDrawVerts = GetLumpElements( header, LUMP_DRAWVERTS, sizeof( drawVert_t ) );
SetDrawVerts( numDrawVerts );
CopyLump( header, LUMP_DRAWVERTS, drawVerts, sizeof( drawVert_t ) );
numDrawSurfaces = GetLumpElements( header, LUMP_SURFACES, sizeof( dsurface_t ) );
SetDrawSurfaces( numDrawSurfaces );
numDrawSurfaces = CopyLump( header, LUMP_SURFACES, drawSurfaces, sizeof( dsurface_t ) );
numFogs = CopyLump( header, LUMP_FOGS, dfogs, sizeof( dfog_t ) );
numDrawIndexes = CopyLump( header, LUMP_DRAWINDEXES, drawIndexes, sizeof( drawIndexes[0] ) );
numVisBytes = CopyLump( header, LUMP_VISIBILITY, visBytes, 1 );
numLightBytes = GetLumpElements( header, LUMP_LIGHTMAPS, 1 );
SetLightBytes( numLightBytes );
CopyLump( header, LUMP_LIGHTMAPS, lightBytes, 1 );
entdatasize = CopyLump( header, LUMP_ENTITIES, dentdata, 1 );
numGridPoints = GetLumpElements( header, LUMP_LIGHTGRID, 8 );
SetGridPoints( numGridPoints );
CopyLump( header, LUMP_LIGHTGRID, gridData, 8 );
free( header ); // everything has been copied out
// swap everything
SwapBSPFile();
}
//============================================================================
/*
=============
AddLump
=============
*/
void AddLump( FILE *bspfile, dheader_t *header, int lumpnum, const void *data, int len ) {
lump_t *lump;
lump = &header->lumps[lumpnum];
lump->fileofs = LittleLong( ftell( bspfile ) );
lump->filelen = LittleLong( len );
SafeWrite( bspfile, data, ( len + 3 ) & ~3 );
}
/*
=============
WriteBSPFile
Swaps the bsp file in place, so it should not be referenced again
=============
*/
void WriteBSPFile( const char *filename ) {
dheader_t outheader, *header;
FILE *bspfile;
header = &outheader;
memset( header, 0, sizeof( dheader_t ) );
SwapBSPFile();
header->ident = LittleLong( BSP_IDENT );
header->version = LittleLong( bsp_version );
bspfile = SafeOpenWrite( filename );
SafeWrite( bspfile, header, sizeof( dheader_t ) ); // overwritten later
AddLump( bspfile, header, LUMP_SHADERS, dshaders, numShaders * sizeof( dshader_t ) );
AddLump( bspfile, header, LUMP_PLANES, dplanes, numplanes * sizeof( dplane_t ) );
AddLump( bspfile, header, LUMP_LEAFS, dleafs, numleafs * sizeof( dleaf_t ) );
AddLump( bspfile, header, LUMP_NODES, dnodes, numnodes * sizeof( dnode_t ) );
AddLump( bspfile, header, LUMP_BRUSHES, dbrushes, numbrushes * sizeof( dbrush_t ) );
AddLump( bspfile, header, LUMP_BRUSHSIDES, dbrushsides, numbrushsides * sizeof( dbrushside_t ) );
AddLump( bspfile, header, LUMP_LEAFSURFACES, dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) );
AddLump( bspfile, header, LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
AddLump( bspfile, header, LUMP_MODELS, dmodels, nummodels * sizeof( dmodel_t ) );
AddLump( bspfile, header, LUMP_DRAWVERTS, drawVerts, numDrawVerts * sizeof( drawVert_t ) );
AddLump( bspfile, header, LUMP_SURFACES, drawSurfaces, numDrawSurfaces * sizeof( dsurface_t ) );
AddLump( bspfile, header, LUMP_VISIBILITY, visBytes, numVisBytes );
AddLump( bspfile, header, LUMP_LIGHTMAPS, lightBytes, numLightBytes );
AddLump( bspfile, header, LUMP_LIGHTGRID, gridData, 8 * numGridPoints );
AddLump( bspfile, header, LUMP_ENTITIES, dentdata, entdatasize );
AddLump( bspfile, header, LUMP_FOGS, dfogs, numFogs * sizeof( dfog_t ) );
AddLump( bspfile, header, LUMP_DRAWINDEXES, drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) );
fseek( bspfile, 0, SEEK_SET );
SafeWrite( bspfile, header, sizeof( dheader_t ) );
fclose( bspfile );
}
//============================================================================
/*
=============
PrintBSPFileSizes
Dumps info about current file
=============
*/
void PrintBSPFileSizes( void ) {
if ( !num_entities ) {
ParseEntities();
}
Sys_Printf( "%6i models %7i\n"
,nummodels, (int)( nummodels * sizeof( dmodel_t ) ) );
Sys_Printf( "%6i shaders %7i\n"
,numShaders, (int)( numShaders * sizeof( dshader_t ) ) );
Sys_Printf( "%6i brushes %7i\n"
,numbrushes, (int)( numbrushes * sizeof( dbrush_t ) ) );
Sys_Printf( "%6i brushsides %7i\n"
,numbrushsides, (int)( numbrushsides * sizeof( dbrushside_t ) ) );
Sys_Printf( "%6i fogs %7i\n"
,numFogs, (int)( numFogs * sizeof( dfog_t ) ) );
Sys_Printf( "%6i planes %7i\n"
,numplanes, (int)( numplanes * sizeof( dplane_t ) ) );
Sys_Printf( "%6i entdata %7i\n", num_entities, entdatasize );
Sys_Printf( "\n" );
Sys_Printf( "%6i nodes %7i\n"
,numnodes, (int)( numnodes * sizeof( dnode_t ) ) );
Sys_Printf( "%6i leafs %7i\n"
,numleafs, (int)( numleafs * sizeof( dleaf_t ) ) );
Sys_Printf( "%6i leafsurfaces %7i\n"
,numleafsurfaces, (int)( numleafsurfaces * sizeof( dleafsurfaces[0] ) ) );
Sys_Printf( "%6i leafbrushes %7i\n"
,numleafbrushes, (int)( numleafbrushes * sizeof( dleafbrushes[0] ) ) );
Sys_Printf( "%6i drawverts %7i\n"
,numDrawVerts, (int)( numDrawVerts * sizeof( drawVerts[0] ) ) );
Sys_Printf( "%6i drawindexes %7i\n"
,numDrawIndexes, (int)( numDrawIndexes * sizeof( drawIndexes[0] ) ) );
Sys_Printf( "%6i drawsurfaces %7i\n"
,numDrawSurfaces, (int)( numDrawSurfaces * sizeof( drawSurfaces[0] ) ) );
Sys_Printf( "%6i lightmaps %7i\n"
,numLightBytes / ( LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3 ), numLightBytes );
Sys_Printf( " visibility %7i\n"
, numVisBytes );
}
//============================================
int num_entities;
entity_t entities[MAX_MAP_ENTITIES];
void StripTrailing( char *e ){
char *s = e + strlen( e ) - 1;
while ( s >= e && *s <= 32 )
{
strClear( s );
s--;
}
}
/*
=================
ParseEpair
=================
*/
epair_t *ParseEpair( void ) {
epair_t *e = safe_calloc( sizeof( epair_t ) );
if ( strlen( token ) >= MAX_KEY - 1 ) {
Error( "ParseEpar: token too long" );
}
e->key = copystring( token );
GetToken( false );
if ( strlen( token ) >= MAX_VALUE - 1 ) {
Error( "ParseEpar: token too long" );
}
e->value = copystring( token );
// strip trailing spaces that sometimes get accidentally
// added in the editor
StripTrailing( e->key );
StripTrailing( e->value );
return e;
}
/*
================
ParseEntity
================
*/
bool ParseEntity( void ) {
epair_t *e;
entity_t *mapent;
if ( !GetToken( true ) ) {
return false;
}
if ( !strEqual( token, "{" ) ) {
Error( "ParseEntity: { not found" );
}
if ( num_entities == MAX_MAP_ENTITIES ) {
Error( "num_entities == MAX_MAP_ENTITIES" );
}
mapent = &entities[num_entities];
num_entities++;
do {
if ( !GetToken( true ) ) {
Error( "ParseEntity: EOF without closing brace" );
}
if ( strEqual( token, "}" ) ) {
break;
}
e = ParseEpair();
e->next = mapent->epairs;
mapent->epairs = e;
} while ( 1 );
return true;
}
/*
================
ParseEntities
Parses the dentdata string into entities
================
*/
void ParseEntities( void ) {
num_entities = 0;
ParseFromMemory( dentdata, entdatasize );
while ( ParseEntity() ) {
}
}
/*
================
UnparseEntities
Generates the dentdata string from all the entities
This allows the utilities to add or remove key/value pairs
to the data created by the map editor.
================
*/
void UnparseEntities( void ) {
char *buf, *end;
epair_t *ep;
char line[2048];
int i;
char key[1024], value[1024];
buf = dentdata;
end = buf;
*end = 0;
for ( i = 0 ; i < num_entities ; i++ ) {
ep = entities[i].epairs;
if ( !ep ) {
continue; // ent got removed
}
strcat( end, "{\n" );
end += 2;
for ( ep = entities[i].epairs ; ep ; ep = ep->next ) {
strcpy( key, ep->key );
StripTrailing( key );
strcpy( value, ep->value );
StripTrailing( value );
sprintf( line, "\"%s\" \"%s\"\n", key, value );
strcat( end, line );
end += strlen( line );
}
strcat( end, "}\n" );
end += 2;
if ( end > buf + MAX_MAP_ENTSTRING ) {
Error( "Entity text too long" );
}
}
entdatasize = end - buf + 1;
}
void PrintEntity( const entity_t *ent ) {
epair_t *ep;
Sys_Printf( "------- entity %p -------\n", ent );
for ( ep = ent->epairs ; ep ; ep = ep->next ) {
Sys_Printf( "%s = %s\n", ep->key, ep->value );
}
}
void SetKeyValue( entity_t *ent, const char *key, const char *value ) {
epair_t *ep;
for ( ep = ent->epairs ; ep ; ep = ep->next ) {
if ( strEqual( ep->key, key ) ) {
free( ep->value );
ep->value = copystring( value );
return;
}
}
ep = safe_malloc( sizeof( *ep ) );
ep->next = ent->epairs;
ent->epairs = ep;
ep->key = copystring( key );
ep->value = copystring( value );
}
const char *ValueForKey( const entity_t *ent, const char *key ) {
epair_t *ep;
for ( ep = ent->epairs ; ep ; ep = ep->next ) {
if ( strEqual( ep->key, key ) ) {
return ep->value;
}
}
return "";
}
vec_t FloatForKey( const entity_t *ent, const char *key ) {
const char *k;
k = ValueForKey( ent, key );
return atof( k );
}
void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec ) {
const char *k;
double v1, v2, v3;
k = ValueForKey( ent, key );
// scanf into doubles, then assign, so it is vec_t size independent
v1 = v2 = v3 = 0;
sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );
vec[0] = v1;
vec[1] = v2;
vec[2] = v3;
}

View File

@ -1,120 +0,0 @@
/*
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 "qfiles.h"
#include "surfaceflags.h"
extern int bsp_version;
extern int nummodels;
extern dmodel_t dmodels[MAX_MAP_MODELS];
extern int numShaders;
extern dshader_t dshaders[MAX_MAP_MODELS];
extern int entdatasize;
extern char dentdata[MAX_MAP_ENTSTRING];
extern int numleafs;
extern dleaf_t dleafs[MAX_MAP_LEAFS];
extern int numplanes;
extern dplane_t dplanes[MAX_MAP_PLANES];
extern int numnodes;
extern dnode_t dnodes[MAX_MAP_NODES];
extern int numleafsurfaces;
extern int dleafsurfaces[MAX_MAP_LEAFFACES];
extern int numleafbrushes;
extern int dleafbrushes[MAX_MAP_LEAFBRUSHES];
extern int numbrushes;
extern dbrush_t dbrushes[MAX_MAP_BRUSHES];
extern int numbrushsides;
extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
void SetLightBytes( int n );
extern int numLightBytes;
extern byte *lightBytes;
void SetGridPoints( int n );
extern int numGridPoints;
extern byte *gridData;
extern int numVisBytes;
extern byte visBytes[MAX_MAP_VISIBILITY];
void SetDrawVerts( int n );
void IncDrawVerts();
extern int numDrawVerts;
extern drawVert_t *drawVerts;
extern int numDrawIndexes;
extern int drawIndexes[MAX_MAP_DRAW_INDEXES];
void SetDrawSurfaces( int n );
void SetDrawSurfacesBuffer();
extern int numDrawSurfaces;
extern dsurface_t *drawSurfaces;
extern int numFogs;
extern dfog_t dfogs[MAX_MAP_FOGS];
void LoadBSPFile( const char *filename );
void WriteBSPFile( const char *filename );
void PrintBSPFileSizes( void );
//===============
typedef struct epair_s {
struct epair_s *next;
char *key;
char *value;
} epair_t;
typedef struct {
vec3_t origin;
struct bspbrush_s *brushes;
struct parseMesh_s *patches;
int firstDrawSurf;
epair_t *epairs;
} entity_t;
extern int num_entities;
extern entity_t entities[MAX_MAP_ENTITIES];
void ParseEntities( void );
void UnparseEntities( void );
void SetKeyValue( entity_t *ent, const char *key, const char *value );
const char *ValueForKey( const entity_t *ent, const char *key );
// will return "" if not present
vec_t FloatForKey( const entity_t *ent, const char *key );
void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec );
epair_t *ParseEpair( void );
void PrintEntity( const entity_t *ent );

View File

@ -47,7 +47,6 @@
#include <unistd.h>
#endif
#define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
void_ptr safe_malloc( size_t size ){
void *p = malloc( size );
@ -66,121 +65,6 @@ void_ptr safe_calloc( size_t size ){
}
/*
===================
ExpandWildcards
Mimic unix command line expansion
===================
*/
#define MAX_EX_ARGC 1024
int ex_argc;
char *ex_argv[MAX_EX_ARGC];
#ifdef _WIN32
#include "io.h"
void ExpandWildcards( int *argc, char ***argv ){
struct _finddata_t fileinfo;
ex_argc = 0;
for ( int i = 0 ; i < *argc ; i++ )
{
char *path = ( *argv )[i];
if ( path[0] == '-'
|| ( !strchr( path, '*' ) && !strchr( path, '?' ) ) ) {
ex_argv[ex_argc++] = path;
continue;
}
const int handle = _findfirst( path, &fileinfo );
if ( handle == -1 ) {
return;
}
do
{
ex_argv[ex_argc++] = copystring( StringOutputStream( 256 )( PathFilenameless( path ), fileinfo.name ) );
} while ( _findnext( handle, &fileinfo ) != -1 );
_findclose( handle );
}
*argc = ex_argc;
*argv = ex_argv;
}
#else
void ExpandWildcards( int *argc, char ***argv ){
}
#endif
/*
qdir will hold the path up to the quake directory, including the slash
f:\quake\
/raid/quake/
gamedir will hold qdir + the game directory (id1, id2, etc)
*/
char qdir[1024];
char gamedir[1024];
char writedir[1024];
void SetQdirFromPath( const char *path ){
const char *c;
const char *sep;
int len, count;
path = ExpandArg( path );
// search for "quake2" in path
len = strlen( BASEDIRNAME );
for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
{
if ( strniEqual( c, BASEDIRNAME, len ) ) {
//
//strncpy (qdir, path, c+len+2-path);
// the +2 assumes a 2 or 3 following quake which is not the
// case with a retail install
// so we need to add up how much to the next separator
sep = c + len;
count = 1;
while ( !strEmpty( sep ) && !path_separator( *sep ) )
{
sep++;
count++;
}
strncpy( qdir, path, c + len + count - path );
Sys_Printf( "qdir: %s\n", qdir );
FixDOSName( qdir );
c += len + count;
while ( *c )
{
if ( path_separator( *c ) ) {
strncpy( gamedir, path, c + 1 - path );
FixDOSName( gamedir );
Sys_Printf( "gamedir: %s\n", gamedir );
if ( strEmpty( writedir ) ) {
strcpy( writedir, gamedir );
}
else{
path_add_slash( writedir );
}
return;
}
c++;
}
Error( "No gamedir in %s", path );
return;
}
}
Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
}
char *ExpandArg( const char *path ){
static char full[1024];
@ -195,17 +79,6 @@ char *ExpandArg( const char *path ){
return full;
}
char *ExpandPath( const char *path ){
static char full[1024];
if ( path_is_absolute( path ) ) {
strcpy( full, path );
}
else{
sprintf( full, "%s%s", qdir, path );
}
return full;
}
/*
@ -283,23 +156,6 @@ void Q_mkdir( const char *path ){
}
}
/*
============
FileTime
returns -1 if not present
============
*/
int FileTime( const char *path ){
struct stat buf;
if ( stat( path,&buf ) == -1 ) {
return -1;
}
return buf.st_mtime;
}
/*
@ -445,52 +301,6 @@ void SaveFile( const char *filename, const void *buffer, int count ){
}
/*
==============
ParseNum / ParseHex
==============
*/
int ParseHex( const char *hex ){
const char *str;
int num;
num = 0;
str = hex;
while ( *str )
{
num <<= 4;
if ( *str >= '0' && *str <= '9' ) {
num += *str - '0';
}
else if ( *str >= 'a' && *str <= 'f' ) {
num += 10 + *str - 'a';
}
else if ( *str >= 'A' && *str <= 'F' ) {
num += 10 + *str - 'A';
}
else{
Error( "Bad hex number: %s",hex );
}
str++;
}
return num;
}
int ParseNum( const char *str ){
if ( str[0] == '$' ) {
return ParseHex( str + 1 );
}
if ( str[0] == '0' && str[1] == 'x' ) {
return ParseHex( str + 2 );
}
return atol( str );
}
/*
============================================================================
@ -607,120 +417,6 @@ float LittleFloat( float l ){
//=======================================================
// FIXME: byte swap?
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
// and the initial and final xor values shown below... in other words, the
// CCITT standard CRC used by XMODEM
#define CRC_INIT_VALUE 0xffff
#define CRC_XOR_VALUE 0x0000
static unsigned short crctable[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
void CRC_Init( unsigned short *crcvalue ){
*crcvalue = CRC_INIT_VALUE;
}
void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
*crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
}
unsigned short CRC_Value( unsigned short crcvalue ){
return crcvalue ^ CRC_XOR_VALUE;
}
//=============================================================================
/*
============
CreatePath
============
*/
void CreatePath( const char *path ){
const char *ofs;
char dir[1024];
#ifdef _WIN32
int olddrive = -1;
if ( path[1] == ':' ) {
olddrive = _getdrive();
_chdrive( toupper( path[0] ) - 'A' + 1 );
}
#endif
if ( path[1] == ':' ) {
path += 2;
}
for ( ofs = path + 1 ; *ofs ; ofs++ )
{
if ( path_separator( *ofs ) ) { // create the directory
memcpy( dir, path, ofs - path );
dir[ ofs - path ] = 0;
Q_mkdir( dir );
}
}
#ifdef _WIN32
if ( olddrive != -1 ) {
_chdrive( olddrive );
}
#endif
}
/*
============
QCopyFile
Used to archive source files
============
*/
void QCopyFile( const char *from, const char *to ){
void *buffer;
int length;
length = LoadFile( from, &buffer );
CreatePath( to );
SaveFile( to, buffer, length );
free( buffer );
}
void Sys_Sleep( int n ){
#ifdef WIN32
Sleep( n );

View File

@ -50,17 +50,10 @@ void_ptr safe_calloc( size_t size );
void Q_getwd( char *out );
int Q_filelength( FILE *f );
int FileTime( const char *path );
void Q_mkdir( const char *path );
extern char qdir[1024];
extern char gamedir[1024];
extern char writedir[1024];
void SetQdirFromPath( const char *path );
char *ExpandArg( const char *path ); // from cmd line
char *ExpandPath( const char *path ); // from scripts
void ExpandWildcards( int *argc, char ***argv );
double I_FloatTime( void );
@ -76,8 +69,6 @@ void SaveFile( const char *filename, const void *buffer, int count );
bool FileExists( const char *filename );
int ParseNum( const char *str );
short BigShort( short l );
short LittleShort( short l );
int BigLong( int l );
@ -86,12 +77,5 @@ float BigFloat( float l );
float LittleFloat( float l );
void CRC_Init( unsigned short *crcvalue );
void CRC_ProcessByte( unsigned short *crcvalue, byte data );
unsigned short CRC_Value( unsigned short crcvalue );
void CreatePath( const char *path );
void QCopyFile( const char *from, const char *to );
// sleep for the given amount of milliseconds
void Sys_Sleep( int n );

View File

@ -1,312 +0,0 @@
/*
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
*/
//
// l3dslib.c: library for loading triangles from an Alias triangle file
//
#include <stdio.h>
#include "cmdlib.h"
#include "mathlib.h"
#include "trilib.h"
#include "l3dslib.h"
#define MAIN3DS 0x4D4D
#define EDIT3DS 0x3D3D // this is the start of the editor config
#define EDIT_OBJECT 0x4000
#define OBJ_TRIMESH 0x4100
#define TRI_VERTEXL 0x4110
#define TRI_FACEL1 0x4120
#define MAXVERTS 2000
#define MAXTRIANGLES 750
typedef struct {
int v[4];
} tri;
float fverts[MAXVERTS][3];
tri tris[MAXTRIANGLES];
int bytesread, level, numtris, totaltris;
int vertsfound, trisfound;
triangle_t *ptri;
// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
// start out with a vertex pool and vertex indices for triangles, we have to convert
// to raw, explicit triangles
void StoreAliasTriangles( void ){
int i, j, k;
if ( ( totaltris + numtris ) > MAXTRIANGLES ) {
Error( "Error: Too many triangles" );
}
for ( i = 0; i < numtris ; i++ )
{
for ( j = 0 ; j < 3 ; j++ )
{
for ( k = 0 ; k < 3 ; k++ )
{
ptri[i + totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
}
}
}
totaltris += numtris;
numtris = 0;
vertsfound = 0;
trisfound = 0;
}
int ParseVertexL( FILE *input ){
int i, j, startbytesread, numverts;
unsigned short tshort;
if ( vertsfound ) {
Error( "Error: Multiple vertex chunks" );
}
vertsfound = 1;
startbytesread = bytesread;
if ( feof( input ) ) {
Error( "Error: unexpected end of file" );
}
fread( &tshort, sizeof( tshort ), 1, input );
bytesread += sizeof( tshort );
numverts = (int)tshort;
if ( numverts > MAXVERTS ) {
Error( "Error: Too many vertices" );
}
for ( i = 0 ; i < numverts ; i++ )
{
for ( j = 0 ; j < 3 ; j++ )
{
if ( feof( input ) ) {
Error( "Error: unexpected end of file" );
}
fread( &fverts[i][j], sizeof( float ), 1, input );
bytesread += sizeof( float );
}
}
if ( vertsfound && trisfound ) {
StoreAliasTriangles();
}
return bytesread - startbytesread;
}
int ParseFaceL1( FILE *input ){
int i, j, startbytesread;
unsigned short tshort;
if ( trisfound ) {
Error( "Error: Multiple face chunks" );
}
trisfound = 1;
startbytesread = bytesread;
if ( feof( input ) ) {
Error( "Error: unexpected end of file" );
}
fread( &tshort, sizeof( tshort ), 1, input );
bytesread += sizeof( tshort );
numtris = (int)tshort;
if ( numtris > MAXTRIANGLES ) {
Error( "Error: Too many triangles" );
}
for ( i = 0 ; i < numtris ; i++ )
{
for ( j = 0 ; j < 4 ; j++ )
{
if ( feof( input ) ) {
Error( "Error: unexpected end of file" );
}
fread( &tshort, sizeof( tshort ), 1, input );
bytesread += sizeof( tshort );
tris[i].v[j] = (int)tshort;
}
}
if ( vertsfound && trisfound ) {
StoreAliasTriangles();
}
return bytesread - startbytesread;
}
int ParseChunk( FILE *input ){
#define BLOCK_SIZE 4096
char temp[BLOCK_SIZE];
unsigned short type;
int i, length, w, t, retval;
level++;
retval = 0;
// chunk type
if ( feof( input ) ) {
Error( "Error: unexpected end of file" );
}
fread( &type, sizeof( type ), 1, input );
bytesread += sizeof( type );
// chunk length
if ( feof( input ) ) {
Error( "Error: unexpected end of file" );
}
fread( &length, sizeof( length ), 1, input );
bytesread += sizeof( length );
w = length - 6;
// process chunk if we care about it, otherwise skip it
switch ( type )
{
case TRI_VERTEXL:
w -= ParseVertexL( input );
goto ParseSubchunk;
case TRI_FACEL1:
w -= ParseFaceL1( input );
goto ParseSubchunk;
case EDIT_OBJECT:
// read the name
i = 0;
do
{
if ( feof( input ) ) {
Error( "Error: unexpected end of file" );
}
fread( &temp[i], 1, 1, input );
i++;
w--;
bytesread++;
} while ( temp[i - 1] );
// fall through
case MAIN3DS:
case OBJ_TRIMESH:
case EDIT3DS:
// parse through subchunks
ParseSubchunk:
while ( w > 0 )
{
w -= ParseChunk( input );
}
retval = length;
goto Done;
default:
// skip other chunks
while ( w > 0 )
{
t = w;
if ( t > BLOCK_SIZE ) {
t = BLOCK_SIZE;
}
if ( feof( input ) ) {
Error( "Error: unexpected end of file" );
}
fread( &temp, t, 1, input );
bytesread += t;
w -= t;
}
retval = length;
goto Done;
}
Done:
level--;
return retval;
}
void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles ){
FILE *input;
short int tshort;
bytesread = 0;
level = 0;
numtris = 0;
totaltris = 0;
vertsfound = 0;
trisfound = 0;
if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
fprintf( stderr, "reader: could not open file '%s'\n", filename );
exit( 0 );
}
fread( &tshort, sizeof( tshort ), 1, input );
// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
// no MAIN3DS
if ( ( tshort != MAIN3DS ) && ( tshort != EDIT3DS ) ) {
fprintf( stderr, "File is not a 3DS file.\n" );
exit( 0 );
}
// back to top of file so we can parse the first chunk descriptor
fseek( input, 0, SEEK_SET );
ptri = safe_malloc( MAXTRIANGLES * sizeof( triangle_t ) );
*pptri = ptri;
// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
ParseChunk( input );
if ( vertsfound || trisfound ) {
Error( "Incomplete triangle set" );
}
*numtriangles = totaltris;
fclose( input );
}

View File

@ -1,25 +0,0 @@
/*
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
*/
//
// l3dslib.h: header file for loading triangles from a 3DS triangle file
//
void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles );

View File

@ -1,53 +0,0 @@
/*
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
*/
#ifndef __POLYSET_H__
#define __POLYSET_H__
#define POLYSET_MAXTRIANGLES 4096
#define POLYSET_MAXPOLYSETS 64
#include "mathlib.h"
typedef float st_t[2];
typedef float rgb_t[3];
typedef struct {
vec3_t verts[3];
vec3_t normals[3];
st_t texcoords[3];
} triangle_t;
typedef struct
{
char name[100];
char materialname[100];
triangle_t *triangles;
int numtriangles;
} polyset_t;
polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet );
polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets );
polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris );
void Polyset_SnapSets( polyset_t *psets, int numpolysets );
void Polyset_ComputeNormals( polyset_t *psets, int numpolysets );
#endif

View File

@ -1,491 +0,0 @@
/*
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
*/
#ifndef __QFILES_H__
#define __QFILES_H__
//
// qfiles.h: quake file formats
// This file must be identical in the quake and utils directories
//
#include "mathlib.h"
// surface geometry should not exceed these limits
#define SHADER_MAX_VERTEXES 1000
#define SHADER_MAX_INDEXES ( 6 * SHADER_MAX_VERTEXES )
// the maximum size of game relative pathnames
#define MAX_QPATH 64
/*
========================================================================
QVM files
========================================================================
*/
#define VM_MAGIC 0x12721444
typedef struct {
int vmMagic;
int instructionCount;
int codeOffset;
int codeLength;
int dataOffset;
int dataLength;
int litLength; // ( dataLength - litLength ) should be byteswapped on load
int bssLength; // zero filled memory appended to datalength
} vmHeader_t;
/*
========================================================================
PCX files are used for 8 bit images
========================================================================
*/
typedef struct {
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned char data; // unbounded
} pcx_t;
/*
========================================================================
TGA files are used for 24/32 bit images
========================================================================
*/
typedef struct _TargaHeader {
unsigned char id_length, colormap_type, image_type;
unsigned short colormap_index, colormap_length;
unsigned char colormap_size;
unsigned short x_origin, y_origin, width, height;
unsigned char pixel_size, attributes;
} TargaHeader;
/*
========================================================================
.MD3 triangle model file format
========================================================================
*/
#define MD3_IDENT ( ( '3' << 24 ) + ( 'P' << 16 ) + ( 'D' << 8 ) + 'I' )
#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.0 / 64 )
typedef struct md3Frame_s {
vec3_t bounds[2];
vec3_t localOrigin;
float radius;
char name[16];
} md3Frame_t;
typedef struct md3Tag_s {
char name[MAX_QPATH]; // tag name
vec3_t origin;
vec3_t axis[3];
} md3Tag_t;
/*
** 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 {
int ident; //
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;
typedef struct {
char name[MAX_QPATH];
int shaderIndex; // for in-game use
} md3Shader_t;
typedef struct {
int indexes[3];
} md3Triangle_t;
typedef struct {
float st[2];
} md3St_t;
typedef struct {
short xyz[3];
short normal;
} md3XyzNormal_t;
typedef struct {
int ident;
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;
/*
==============================================================================
MD4 file format
==============================================================================
*/
#define MD4_IDENT ( ( '4' << 24 ) + ( 'P' << 16 ) + ( 'D' << 8 ) + 'I' )
#define MD4_VERSION 1
#define MD4_MAX_BONES 128
typedef struct {
int boneIndex; // these are indexes into the boneReferences,
float boneWeight; // not the global per-frame bone list
} md4Weight_t;
typedef struct {
vec3_t vertex;
vec3_t normal;
float texCoords[2];
int numWeights;
md4Weight_t weights[1]; // variable sized
} md4Vertex_t;
typedef struct {
int indexes[3];
} md4Triangle_t;
typedef struct {
int ident;
char name[MAX_QPATH]; // polyset name
char shader[MAX_QPATH];
int shaderIndex; // for in-game use
int ofsHeader; // this will be a negative number
int numVerts;
int ofsVerts;
int numTriangles;
int ofsTriangles;
// Bone references are a set of ints representing all the bones
// present in any vertex weights for this surface. This is
// needed because a model may have surfaces that need to be
// drawn at different sort times, and we don't want to have
// to re-interpolate all the bones for each surface.
int numBoneReferences;
int ofsBoneReferences;
int ofsEnd; // next surface follows
} md4Surface_t;
typedef struct {
float matrix[3][4];
} md4Bone_t;
typedef struct {
vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame
vec3_t localOrigin; // midpoint of bounds, used for sphere cull
float radius; // dist from localOrigin to corner
char name[16];
md4Bone_t bones[1]; // [numBones]
} md4Frame_t;
typedef struct {
int numSurfaces;
int ofsSurfaces; // first surface, others follow
int ofsEnd; // next lod follows
} md4LOD_t;
typedef struct {
int ident;
int version;
char name[MAX_QPATH]; // model name
// frames and bones are shared by all levels of detail
int numFrames;
int numBones;
int ofsFrames; // md4Frame_t[numFrames]
// each level of detail has completely separate sets of surfaces
int numLODs;
int ofsLODs;
int ofsEnd; // end of file
} md4Header_t;
/*
==============================================================================
.BSP file format
==============================================================================
*/
#define BSP_IDENT ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'B' << 8 ) + 'I' )
// little-endian "IBSP"
//#define BSP_VERSION 46
#define Q3_BSP_VERSION 46
#define WOLF_BSP_VERSION 47
// there shouldn't be any problem with increasing these values at the
// expense of more memory allocation in the utilities
#define MAX_MAP_MODELS 0x400
#define MAX_MAP_BRUSHES 0x8000
#define MAX_MAP_ENTITIES 0x800
#define MAX_MAP_ENTSTRING 0x40000
#define MAX_MAP_SHADERS 0x400
#define MAX_MAP_AREAS 0x100 // MAX_MAP_AREA_BYTES in q_shared must match!
#define MAX_MAP_FOGS 0x100
#define MAX_MAP_PLANES 0x20000
#define MAX_MAP_NODES 0x20000
#define MAX_MAP_BRUSHSIDES 0x40000 //% 0x20000 /* ydnar */
#define MAX_MAP_LEAFS 0x20000
#define MAX_MAP_LEAFFACES 0x20000
#define MAX_MAP_LEAFBRUSHES 0x40000
#define MAX_MAP_PORTALS 0x20000
#define MAX_MAP_LIGHTING 0x800000
#define MAX_MAP_LIGHTGRID 0x800000
#define MAX_MAP_VISIBILITY 0x200000
#define MAX_MAP_DRAW_SURFS 0x20000
#define MAX_MAP_DRAW_VERTS 0x80000
#define MAX_MAP_DRAW_INDEXES 0x80000
// key / value pair sizes in the entities lump
#define MAX_KEY 32
#define MAX_VALUE 1024
// the editor uses these predefined yaw angles to orient entities up or down
#define ANGLE_UP -1
#define ANGLE_DOWN -2
#define LIGHTMAP_WIDTH 128
#define LIGHTMAP_HEIGHT 128
#define MIN_WORLD_COORD ( -65536 )
#define MAX_WORLD_COORD ( 65536 )
#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD )
//=============================================================================
typedef struct {
int fileofs, filelen;
} lump_t;
#define LUMP_ENTITIES 0
#define LUMP_SHADERS 1
#define LUMP_PLANES 2
#define LUMP_NODES 3
#define LUMP_LEAFS 4
#define LUMP_LEAFSURFACES 5
#define LUMP_LEAFBRUSHES 6
#define LUMP_MODELS 7
#define LUMP_BRUSHES 8
#define LUMP_BRUSHSIDES 9
#define LUMP_DRAWVERTS 10
#define LUMP_DRAWINDEXES 11
#define LUMP_FOGS 12
#define LUMP_SURFACES 13
#define LUMP_LIGHTMAPS 14
#define LUMP_LIGHTGRID 15
#define LUMP_VISIBILITY 16
#define HEADER_LUMPS 17
typedef struct {
int ident;
int version;
lump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct {
float mins[3], maxs[3];
int firstSurface, numSurfaces;
int firstBrush, numBrushes;
} dmodel_t;
typedef struct {
char shader[MAX_QPATH];
int surfaceFlags;
int contentFlags;
} dshader_t;
// planes x^1 is always the opposite of plane x
typedef struct {
float normal[3];
float dist;
} dplane_t;
typedef struct {
int planeNum;
int children[2]; // negative numbers are -(leafs+1), not nodes
int mins[3]; // for frustum culling
int maxs[3];
} dnode_t;
typedef struct {
int cluster; // -1 = opaque cluster (do I still store these?)
int area;
int mins[3]; // for frustum culling
int maxs[3];
int firstLeafSurface;
int numLeafSurfaces;
int firstLeafBrush;
int numLeafBrushes;
} dleaf_t;
typedef struct {
int planeNum; // positive plane side faces out of the leaf
int shaderNum;
} dbrushside_t;
typedef struct {
int firstSide;
int numSides;
int shaderNum; // the shader that determines the contents flags
} dbrush_t;
typedef struct {
char shader[MAX_QPATH];
int brushNum;
int visibleSide; // the brush side that ray tests need to clip against (-1 == none)
} dfog_t;
typedef struct {
vec3_t xyz;
float st[2];
float lightmap[2];
vec3_t normal;
byte color[4];
} drawVert_t;
typedef enum {
MST_BAD,
MST_PLANAR,
MST_PATCH,
MST_TRIANGLE_SOUP,
MST_FLARE
} mapSurfaceType_t;
typedef struct {
int shaderNum;
int fogNum;
int surfaceType;
int firstVert;
int numVerts;
int firstIndex;
int numIndexes;
int lightmapNum;
int lightmapX, lightmapY;
int lightmapWidth, lightmapHeight;
vec3_t lightmapOrigin;
vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds
int patchWidth;
int patchHeight;
} dsurface_t;
#endif

View File

@ -1,112 +0,0 @@
/*
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
*/
// Copyright (C) 1999-2000 Id Software, Inc.
//
// This file must be identical in the quake and utils directories
// contents flags are separate bits
// a given brush can contribute multiple content bits
// these definitions also need to be in q_shared.h!
#define CONTENTS_SOLID 1 // an eye is never valid in a solid
#define CONTENTS_LAVA 8
#define CONTENTS_SLIME 16
#define CONTENTS_WATER 32
#define CONTENTS_FOG 64
#define CONTENTS_AREAPORTAL 0x8000
#define CONTENTS_PLAYERCLIP 0x10000
#define CONTENTS_MONSTERCLIP 0x20000
//bot specific contents types
#define CONTENTS_TELEPORTER 0x40000
#define CONTENTS_JUMPPAD 0x80000
#define CONTENTS_CLUSTERPORTAL 0x100000
#define CONTENTS_DONOTENTER 0x200000
#define CONTENTS_BOTCLIP 0x400000
#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
#define CONTENTS_BODY 0x2000000 // should never be on a brush, only in game
#define CONTENTS_CORPSE 0x4000000
#define CONTENTS_DETAIL 0x8000000 // brushes not used for the bsp
#define CONTENTS_STRUCTURAL 0x10000000 // brushes used for the bsp
#define CONTENTS_TRANSLUCENT 0x20000000 // don't consume surface fragments inside
#define CONTENTS_TRIGGER 0x40000000
#define CONTENTS_NODROP 0x80000000 // don't leave bodies or items (death fog, lava)
#define SURF_NODAMAGE 0x1 // never give falling damage
#define SURF_SLICK 0x2 // effects game physics
#define SURF_SKY 0x4 // lighting from environment map
#define SURF_LADDER 0x8
#define SURF_NOIMPACT 0x10 // don't make missile explosions
#define SURF_NOMARKS 0x20 // don't leave missile marks
#define SURF_FLESH 0x40 // make flesh sounds and effects
#define SURF_NODRAW 0x80 // don't generate a drawsurface at all
#define SURF_HINT 0x100 // make a primary bsp splitter
#define SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes
#define SURF_NOLIGHTMAP 0x400 // surface doesn't need a lightmap
#define SURF_POINTLIGHT 0x800 // generate lighting info at vertexes
#define SURF_METALSTEPS 0x1000 // clanking footsteps
#define SURF_NOSTEPS 0x2000 // no footstep sounds
#define SURF_NONSOLID 0x4000 // don't collide against curves with this set
#define SURF_LIGHTFILTER 0x8000 // act as a light filter during q3map -light
#define SURF_ALPHASHADOW 0x10000 // do per-pixel light shadow casting in q3map
#define SURF_NODLIGHT 0x20000 // don't dlight even if solid (solid lava, skies)
#define SURF_DUST 0x40000 // leave a dust trail when walking on this surface
/* ydnar flags */
#define CONTENTS_OPAQUE 0x02
#define CONTENTS_LIGHTGRID 0x04
#define SURF_VERTEXLIT ( SURF_POINTLIGHT | SURF_NOLIGHTMAP )
/* wolfenstein flags (collisions with valid q3a flags are noted) */
#define CONTENTS_MISSILECLIP 0x80
#define CONTENTS_ITEM 0x100
#define CONTENTS_AI_NOSIGHT 0x1000
#define CONTENTS_CLIPSHOT 0x2000
#define CONTENTS_DONOTENTER_LARGE 0x400000 /* CONTENTS_BOTCLIP */
#define SURF_CERAMIC 0x40 /* SURF_FLESH */
#define SURF_METAL 0x1000 /* SURF_METALSTEPS */
#define SURF_WOOD 0x40000 /* SURF_DUST */
#define SURF_GRASS 0x80000
#define SURF_GRAVEL 0x100000
#define SURF_GLASS 0x200000
#define SURF_SNOW 0x400000
#define SURF_ROOF 0x800000
#define SURF_RUBBLE 0x1000000
#define SURF_CARPET 0x2000000
#define SURF_MONSTERSLICK 0x4000000
#define SURF_MONSLICK_W 0x8000000
#define SURF_MONSLICK_N 0x10000000
#define SURF_MONSLICK_E 0x20000000
#define SURF_MONSLICK_S 0x40000000

View File

@ -1,230 +0,0 @@
/*
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
*/
//
// trilib.c: library for loading triangles from an Alias triangle file
//
#include <stdio.h>
#include "cmdlib.h"
#include "inout.h"
#include "qstringops.h"
#include "mathlib.h"
#include "polyset.h"
#include "trilib.h"
// on disk representation of a face
#define FLOAT_START 99999.0
#define FLOAT_END -FLOAT_START
#define MAGIC 123322
typedef struct {
float v[3];
} vector;
typedef struct
{
vector n; /* normal */
vector p; /* point */
vector c; /* color */
float u; /* u */
float v; /* v */
} aliaspoint_t;
typedef struct {
aliaspoint_t pt[3];
} tf_triangle;
static void ByteSwapTri( tf_triangle *tri ){
for ( size_t i = 0 ; i < sizeof( tf_triangle ) / 4 ; i++ )
{
( (int *)tri )[i] = BigLong( ( (int *)tri )[i] );
}
}
static void ReadPolysetGeometry( triangle_t *tripool, FILE *input, int count, triangle_t *ptri ){
tf_triangle tri;
int i;
for ( i = 0; i < count; ++i ) {
int j;
fread( &tri, sizeof( tf_triangle ), 1, input );
ByteSwapTri( &tri );
for ( j = 0 ; j < 3 ; j++ )
{
int k;
for ( k = 0 ; k < 3 ; k++ )
{
ptri->verts[j][k] = tri.pt[j].p.v[k];
ptri->normals[j][k] = tri.pt[j].n.v[k];
// ptri->colors[j][k] = tri.pt[j].c.v[k];
}
ptri->texcoords[j][0] = tri.pt[j].u;
ptri->texcoords[j][1] = tri.pt[j].v;
}
ptri++;
if ( ( ptri - tripool ) >= POLYSET_MAXTRIANGLES ) {
Error( "Error: too many triangles; increase POLYSET_MAXTRIANGLES\n" );
}
}
}
void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets ){
FILE *input;
float start;
char name[256], tex[256];
int i, count, magic, pset = 0;
triangle_t *ptri;
polyset_t *pPSET;
int iLevel;
int exitpattern;
float t;
t = -FLOAT_START;
*( (unsigned char *)&exitpattern + 0 ) = *( (unsigned char *)&t + 3 );
*( (unsigned char *)&exitpattern + 1 ) = *( (unsigned char *)&t + 2 );
*( (unsigned char *)&exitpattern + 2 ) = *( (unsigned char *)&t + 1 );
*( (unsigned char *)&exitpattern + 3 ) = *( (unsigned char *)&t + 0 );
if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
Error( "reader: could not open file '%s'", filename );
}
iLevel = 0;
fread( &magic, sizeof( int ), 1, input );
if ( BigLong( magic ) != MAGIC ) {
Error( "%s is not a Alias object separated triangle file, magic number is wrong.", filename );
}
pPSET = safe_calloc( POLYSET_MAXPOLYSETS * sizeof( polyset_t ) );
ptri = safe_calloc( POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );
*ppPSET = pPSET;
while ( feof( input ) == 0 ) {
if ( fread( &start, sizeof( float ), 1, input ) < 1 ) {
break;
}
*(int *)&start = BigLong( *(int *)&start );
if ( *(int *)&start != exitpattern ) {
if ( start == FLOAT_START ) {
/* Start of an object or group of objects. */
i = -1;
do {
/* There are probably better ways to read a string from */
/* a file, but this does allow you to do error checking */
/* (which I'm not doing) on a per character basis. */
++i;
fread( &( name[i] ), sizeof( char ), 1, input );
} while ( name[i] != '\0' );
if ( i != 0 ) {
strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );
}
else{
strcpy( pPSET[pset].name, "(unnamed)" );
}
strLower( pPSET[pset].name );
// indent();
// fprintf( stdout, "OBJECT START: %s\n", name );
fread( &count, sizeof( int ), 1, input );
count = BigLong( count );
++iLevel;
if ( count != 0 ) {
// indent();
// fprintf( stdout, "NUMBER OF TRIANGLES: %d\n", count );
i = -1;
do {
++i;
fread( &( tex[i] ), sizeof( char ), 1, input );
} while ( tex[i] != '\0' );
/*
if ( i != 0 )
strncpy( pPSET[pset].texname, tex, sizeof( pPSET[pset].texname ) - 1 );
else
strcpy( pPSET[pset].texname, "(unnamed)" );
strLower( pPSET[pset].texname );
*/
// indent();
// fprintf( stdout, " Object texture name: '%s'\n", tex );
}
/* Else (count == 0) this is the start of a group, and */
/* no texture name is present. */
}
else if ( start == FLOAT_END ) {
/* End of an object or group. Yes, the name should be */
/* obvious from context, but it is in here just to be */
/* safe and to provide a little extra information for */
/* those who do not wish to write a recursive reader. */
/* Mea culpa. */
--iLevel;
i = -1;
do {
++i;
fread( &( name[i] ), sizeof( char ), 1, input );
} while ( name[i] != '\0' );
if ( i != 0 ) {
strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );
}
else{
strcpy( pPSET[pset].name, "(unnamed)" );
}
strLower( pPSET[pset].name );
// indent();
// fprintf( stdout, "OBJECT END: %s\n", name );
continue;
}
}
//
// read the triangles
//
if ( count > 0 ) {
pPSET[pset].triangles = ptri;
ReadPolysetGeometry( pPSET[0].triangles, input, count, ptri );
ptri += count;
pPSET[pset].numtriangles = count;
if ( ++pset >= POLYSET_MAXPOLYSETS ) {
Error( "Error: too many polysets; increase POLYSET_MAXPOLYSETS\n" );
}
}
}
*numpsets = pset;
fclose( input );
}

View File

@ -1,25 +0,0 @@
/*
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
*/
//
// trilib.h: header file for loading triangles from an Alias triangle file
//
void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets );

View File

@ -1,2 +0,0 @@
*.dsp -m 'COPY' -k 'b'
*.dsw -m 'COPY' -k 'b'

View File

@ -1,658 +0,0 @@
/*
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 <assert.h>
#include "q3data.h"
static void Load3DS( const char *filename, _3DS_t *p3DS, bool verbose );
static bool s_verbose;
#define MAX_MATERIALS 100
#define MAX_NAMED_OBJECTS 100
#define MAX_MESH_MATERIAL_GROUPS 100
#define MAX_TRI_OBJECTS 512
static char s_buffer[1000000];
static int ReadString( FILE *fp, char *buffer ){
int i = 0;
int bytesRead = 0;
do
{
fread( &buffer[i], 1, sizeof( char ), fp );
bytesRead++;
} while ( buffer[i++] != 0 );
buffer[i] = 0;
return bytesRead;
}
static int ReadChunkAndLength( FILE *fp, unsigned short *chunk, long *len ){
if ( fread( chunk, sizeof( *chunk ), 1, fp ) != 1 ) {
return 0;
}
if ( fread( len, sizeof( long ), 1, fp ) != 1 ) {
Error( "Unexpected EOF found" );
}
return 1;
}
static void LoadMapName( FILE *fp, char *buffer, int thisChunkLen ){
unsigned short chunkID;
long chunkLen;
long bytesRead = 0;
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
{
switch ( chunkID )
{
case _3DS_CHUNK_MAT_MAPNAME:
fread( buffer, chunkLen - 6, 1, fp );
break;
default:
fread( s_buffer, chunkLen - 6, 1, fp );
break;
}
bytesRead += chunkLen;
if ( bytesRead >= thisChunkLen ) {
return;
}
}
}
static void LoadMaterialList( FILE *fp, long thisChunkLen, _3DSMaterial_t *pMat ){
long chunkLen;
unsigned short chunkID;
long bytesRead = 0;
_3DSMaterial_t mat;
char curdir[1024];
char buffer[2048];
memset( &mat, 0, sizeof( mat ) );
if ( s_verbose ) {
printf( " >>> MATERIAL LIST\n" );
}
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
{
switch ( chunkID )
{
case _3DS_CHUNK_MAT_NAME:
fread( mat.name, chunkLen - 6, 1, fp );
if ( s_verbose ) {
printf( " found mat name '%s'\n", mat.name );
}
break;
case _3DS_CHUNK_TEXMAP:
LoadMapName( fp, mat.texture, chunkLen - 6 );
if ( s_verbose ) {
printf( " found texture '%s'\n", mat.texture );
}
break;
case _3DS_CHUNK_SPECMAP:
LoadMapName( fp, mat.specular, chunkLen - 6 );
if ( s_verbose ) {
printf( " found specular map '%s'\n", mat.specular );
}
break;
case _3DS_CHUNK_OPACMAP:
LoadMapName( fp, mat.opacity, chunkLen - 6 );
if ( s_verbose ) {
printf( " found opacity map '%s'\n", mat.opacity );
}
break;
case _3DS_CHUNK_REFLMAP:
LoadMapName( fp, mat.reflection, chunkLen - 6 );
if ( s_verbose ) {
printf( " found reflection map '%s'\n", mat.reflection );
}
break;
case _3DS_CHUNK_BUMPMAP:
LoadMapName( fp, mat.bump, chunkLen - 6 );
if ( s_verbose ) {
printf( " found bump map '%s'\n", mat.bump );
}
break;
default:
fread( s_buffer, chunkLen - 6, 1, fp );
break;
}
bytesRead += chunkLen;
if ( bytesRead >= thisChunkLen ) {
break;
}
}
Q_getwd( curdir );
if ( mat.texture[0] ) {
sprintf( buffer, "%s%s", curdir, mat.texture );
if ( strstr( buffer, gamedir + 1 ) ) {
strcpy( mat.texture, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
}
else{
strcpy( mat.texture, buffer );
}
}
if ( mat.specular[0] ) {
sprintf( buffer, "%s%s", curdir, mat.specular );
if ( strstr( buffer, gamedir + 1 ) ) {
strcpy( mat.specular, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
}
else{
strcpy( mat.specular, buffer );
}
}
if ( mat.bump[0] ) {
sprintf( buffer, "%s%s", curdir, mat.bump );
if ( strstr( buffer, gamedir + 1 ) ) {
strcpy( mat.bump, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
}
else{
strcpy( mat.bump, buffer );
}
}
if ( mat.reflection[0] ) {
sprintf( buffer, "%s%s", curdir, mat.reflection );
if ( strstr( buffer, gamedir + 1 ) ) {
strcpy( mat.reflection, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
}
else{
strcpy( mat.reflection, buffer );
}
}
if ( mat.opacity[0] ) {
sprintf( buffer, "%s%s", curdir, mat.opacity );
if ( strstr( buffer, gamedir + 1 ) ) {
strcpy( mat.opacity, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
}
else{
strcpy( mat.opacity, buffer );
}
}
*pMat = mat;
}
static void LoadMeshMaterialGroup( FILE *fp, long thisChunkLen, _3DSMeshMaterialGroup_t *pMMG ){
_3DSMeshMaterialGroup_t mmg;
memset( &mmg, 0, sizeof( mmg ) );
ReadString( fp, mmg.name );
fread( &mmg.numFaces, sizeof( mmg.numFaces ), 1, fp );
mmg.pFaces = safe_malloc( sizeof( mmg.pFaces[0] ) * mmg.numFaces );
fread( mmg.pFaces, sizeof( mmg.pFaces[0] ), mmg.numFaces, fp );
if ( s_verbose ) {
printf( " >>> MESH MATERIAL GROUP '%s' (%d faces)\n", mmg.name, mmg.numFaces );
{
int i;
for ( i = 0; i < mmg.numFaces; i++ )
{
printf( " %d\n", mmg.pFaces[i] );
}
}
}
*pMMG = mmg;
}
static void LoadNamedTriObject( FILE *fp, long thisChunkLen, _3DSTriObject_t *pTO ){
long chunkLen;
unsigned short chunkID;
int i = 0;
long bytesRead = 0;
_3DSTriObject_t triObj;
_3DSMeshMaterialGroup_t meshMaterialGroups[MAX_MESH_MATERIAL_GROUPS];
int numMeshMaterialGroups = 0;
memset( &triObj, 0, sizeof( triObj ) );
if ( s_verbose ) {
printf( " >>> NAMED TRI OBJECT\n" );
}
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
{
switch ( chunkID )
{
case _3DS_CHUNK_MSH_MAT_GROUP:
LoadMeshMaterialGroup( fp, chunkLen - 6, &meshMaterialGroups[numMeshMaterialGroups] );
bytesRead += chunkLen;
numMeshMaterialGroups++;
break;
case _3DS_CHUNK_FACE_ARRAY:
fread( &triObj.numFaces, sizeof( triObj.numFaces ), 1, fp );
assert( triObj.pFaces == 0 );
triObj.pFaces = safe_malloc( sizeof( triObj.pFaces[0] ) * triObj.numFaces );
fread( triObj.pFaces, sizeof( triObj.pFaces[0] ), triObj.numFaces, fp );
bytesRead += sizeof( triObj.numFaces ) + triObj.numFaces * sizeof( triObj.pFaces[0] ) + 6;
if ( s_verbose ) {
printf( " found face array with %d faces\n", triObj.numFaces );
for ( i = 0; i < triObj.numFaces; i++ )
{
printf( " %d: %d,%d,%d\n", i, triObj.pFaces[i].a, triObj.pFaces[i].b, triObj.pFaces[i].c );
}
}
break;
case _3DS_CHUNK_POINT_ARRAY:
fread( &triObj.numPoints, sizeof( triObj.numPoints ), 1, fp );
triObj.pPoints = safe_malloc( sizeof( triObj.pPoints[0] ) * triObj.numPoints );
fread( triObj.pPoints, sizeof( triObj.pPoints[0] ), triObj.numPoints, fp );
bytesRead += sizeof( triObj.numPoints ) + triObj.numPoints * sizeof( triObj.pPoints[0] ) + 6;
// flip points around into our coordinate system
for ( i = 0; i < triObj.numPoints; i++ )
{
float x, y, z;
x = triObj.pPoints[i].x;
y = triObj.pPoints[i].y;
z = triObj.pPoints[i].z;
triObj.pPoints[i].x = -y;
triObj.pPoints[i].y = x;
triObj.pPoints[i].z = z;
}
if ( s_verbose ) {
printf( " found point array with %d points\n", triObj.numPoints );
for ( i = 0; i < triObj.numPoints; i++ )
{
printf( " %d: %f,%f,%f\n", i, triObj.pPoints[i].x, triObj.pPoints[i].y, triObj.pPoints[i].z );
}
}
break;
case _3DS_CHUNK_TEX_VERTS:
fread( &triObj.numTexVerts, sizeof( triObj.numTexVerts ), 1, fp );
triObj.pTexVerts = safe_malloc( sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts );
fread( triObj.pTexVerts, sizeof( triObj.pTexVerts[0] ), triObj.numTexVerts, fp );
bytesRead += sizeof( triObj.numTexVerts ) + sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts + 6;
if ( s_verbose ) {
printf( " found tex vert array with %d tex verts\n", triObj.numTexVerts );
for ( i = 0; i < triObj.numTexVerts; i++ )
{
printf( " %d: %f,%f\n", i, triObj.pTexVerts[i].s, triObj.pTexVerts[i].t );
}
}
break;
default:
fread( s_buffer, chunkLen - 6, 1, fp );
bytesRead += chunkLen;
break;
}
if ( bytesRead >= thisChunkLen ) {
break;
}
}
*pTO = triObj;
if ( numMeshMaterialGroups == 0 ) {
numMeshMaterialGroups = 1;
strcpy( meshMaterialGroups[0].name, "(null)" );
if ( pTO->numTexVerts ) {
printf( "Warning: assigning (null) skin to tri object\n" );
}
}
else
{
assert( pTO->numFaces == meshMaterialGroups[0].numFaces );
}
pTO->pMeshMaterialGroups = safe_malloc( sizeof( _3DSMeshMaterialGroup_t ) * numMeshMaterialGroups );
memcpy( pTO->pMeshMaterialGroups, meshMaterialGroups, numMeshMaterialGroups * sizeof( meshMaterialGroups[0] ) );
pTO->numMeshMaterialGroups = numMeshMaterialGroups;
//
// sanity checks
//
assert( numMeshMaterialGroups <= 1 );
}
static void LoadNamedObject( FILE *fp, long thisChunkLen, _3DSNamedObject_t *pNO ){
long chunkLen;
unsigned short chunkID;
long bytesRead = 0;
char name[100];
_3DSTriObject_t triObj[MAX_TRI_OBJECTS];
int numTriObjects = 0;
memset( triObj, 0, sizeof( triObj ) );
bytesRead += ReadString( fp, name );
if ( s_verbose ) {
printf( " >>> NAMED OBJECT '%s'\n", name );
}
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
{
switch ( chunkID )
{
case _3DS_CHUNK_NAMED_TRI_OBJECT:
LoadNamedTriObject( fp, chunkLen - 6, &triObj[numTriObjects] );
numTriObjects++;
break;
default:
fread( s_buffer, chunkLen - 6, 1, fp );
break;
}
bytesRead += chunkLen;
if ( bytesRead >= thisChunkLen ) {
break;
}
}
strcpy( pNO->name, name );
pNO->pTriObjects = safe_malloc( sizeof( _3DSTriObject_t ) * numTriObjects );
memcpy( pNO->pTriObjects, triObj, sizeof( triObj[0] ) * numTriObjects );
pNO->numTriObjects = numTriObjects;
assert( numTriObjects <= 1 );
}
static void LoadEditChunk( FILE *fp, long thisChunkLen, _3DSEditChunk_t *pEC ){
unsigned short chunkID;
long chunkLen;
long bytesRead = 0;
_3DSEditChunk_t editChunk;
_3DSMaterial_t mat[MAX_MATERIALS];
_3DSNamedObject_t namedObjects[MAX_NAMED_OBJECTS];
int numMaterials = 0, numNamedObjects = 0;
memset( &editChunk, 0, sizeof( editChunk ) );
if ( s_verbose ) {
printf( ">>> EDIT CHUNK\n" );
}
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
{
switch ( chunkID )
{
case _3DS_CHUNK_MAT_LIST:
LoadMaterialList( fp, chunkLen - 6, &mat[numMaterials] );
numMaterials++;
break;
case _3DS_CHUNK_NAMED_OBJECT:
LoadNamedObject( fp, chunkLen - 6, &namedObjects[numNamedObjects] );
if ( namedObjects[numNamedObjects].numTriObjects != 0 ) {
++numNamedObjects;
}
break;
case _3DS_CHUNK_MESH_VERSION:
default:
fread( s_buffer, chunkLen - 6, 1, fp );
break;
}
bytesRead += chunkLen;
if ( bytesRead >= thisChunkLen ) {
break;
}
}
if ( numMaterials == 0 ) {
numMaterials = 1;
strcpy( mat[0].name, "(null)" );
printf( "Warning: no material definitions found\n" );
}
pEC->numNamedObjects = numNamedObjects;
pEC->pMaterials = safe_malloc( sizeof( _3DSMaterial_t ) * numMaterials );
pEC->pNamedObjects = safe_malloc( sizeof( _3DSNamedObject_t ) * numNamedObjects );
memcpy( pEC->pMaterials, mat, numMaterials * sizeof( mat[0] ) );
memcpy( pEC->pNamedObjects, namedObjects, numNamedObjects * sizeof( namedObjects[0] ) );
}
static void Load3DS( const char *filename, _3DS_t *p3DS, bool verbose ){
FILE *fp;
unsigned short chunkID;
long chunkLen;
_3DSEditChunk_t editChunk;
s_verbose = verbose;
if ( ( fp = fopen( filename, "rb" ) ) == 0 ) {
Error( "Unable to open '%s'", filename );
}
// read magic number
if ( ( fread( &chunkID, sizeof( short ), 1, fp ) != 1 ) ||
( LittleShort( chunkID ) != _3DS_CHUNK_MAGIC ) ) {
Error( "Missing or incorrect magic number in '%s'", filename );
}
if ( fread( &chunkLen, sizeof( chunkLen ), 1, fp ) != 1 ) {
Error( "Unexpected EOF encountered in '%s'", filename );
}
// version number
if ( !ReadChunkAndLength( fp, &chunkID, &chunkLen ) ) {
Error( "Missing version number in '%s'", filename );
}
if ( fread( s_buffer, chunkLen - 6, 1, fp ) != 1 ) {
Error( "Unexpected EOF encountered in '%s'", filename );
}
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
{
switch ( chunkID )
{
case _3DS_CHUNK_EDIT:
LoadEditChunk( fp, chunkLen - 6, &editChunk );
break;
case _3DS_CHUNK_KEYFRAME_DATA:
fread( s_buffer, chunkLen - 6, 1, fp );
break;
default:
fread( s_buffer, chunkLen - 6, 1, fp );
break;
}
}
fclose( fp );
p3DS->editChunk = editChunk;
}
static void ComputeNormals( _3DSTriObject_t *pTO, triangle_t *pTris ){
vec3_t faceNormals[POLYSET_MAXTRIANGLES];
vec3_t vertexNormals[POLYSET_MAXTRIANGLES * 3];
vec3_t side0, side1, facenormal;
int f, v;
memset( faceNormals, 0, sizeof( faceNormals ) );
memset( vertexNormals, 0, sizeof( vertexNormals ) );
//
// compute face normals
//
for ( f = 0; f < pTO->numFaces; f++ )
{
VectorSubtract( pTris[f].verts[0], pTris[f].verts[1], side0 );
VectorSubtract( pTris[f].verts[2], pTris[f].verts[1], side1 );
CrossProduct( side0, side1, facenormal );
VectorNormalize( facenormal, faceNormals[f] );
}
//
// sum vertex normals
//
for ( v = 0; v < pTO->numPoints; v++ )
{
for ( f = 0; f < pTO->numFaces; f++ )
{
if ( ( pTO->pFaces[f].a == v ) ||
( pTO->pFaces[f].b == v ) ||
( pTO->pFaces[f].c == v ) ) {
vertexNormals[v][0] += faceNormals[f][0];
vertexNormals[v][1] += faceNormals[f][1];
vertexNormals[v][2] += faceNormals[f][2];
}
}
VectorNormalize( vertexNormals[v], vertexNormals[v] );
}
//
// copy vertex normals into triangles
//
for ( f = 0; f < pTO->numFaces; f++ )
{
int i0 = pTO->pFaces[f].c;
int i1 = pTO->pFaces[f].b;
int i2 = pTO->pFaces[f].a;
VectorCopy( vertexNormals[i0], pTris[f].normals[0] );
VectorCopy( vertexNormals[i1], pTris[f].normals[1] );
VectorCopy( vertexNormals[i2], pTris[f].normals[2] );
}
}
/*
** void _3DS_LoadPolysets
*/
void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, bool verbose ){
_3DS_t _3ds;
int numPolysets;
polyset_t *pPSET;
triangle_t *ptri, *triangles;
int i;
// load the 3DS
memset( &_3ds, 0, sizeof( _3ds ) );
Load3DS( filename, &_3ds, verbose );
// compute information
numPolysets = _3ds.editChunk.numNamedObjects;
// allocate memory
pPSET = safe_calloc( numPolysets * sizeof( polyset_t ) );
triangles = ptri = safe_calloc( POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );
// copy the data over
for ( i = 0; i < numPolysets; i++ )
{
char matnamebuf[1024];
int j;
triangle_t *tri;
_3DSTriObject_t *pTO = &_3ds.editChunk.pNamedObjects[i].pTriObjects[0];
pPSET[i].triangles = ptri;
pPSET[i].numtriangles = pTO->numFaces;
strcpy( pPSET[i].name, _3ds.editChunk.pNamedObjects[i].name );
strcpy( matnamebuf, filename );
StripFilename( matnamebuf );
strcat( matnamebuf, pTO->pMeshMaterialGroups[0].name );
if ( strstr( matnamebuf, gamedir ) ) {
strcpy( pPSET[i].materialname, strstr( matnamebuf, gamedir ) + strlen( gamedir ) );
}
else{
strcpy( pPSET[i].materialname, pTO->pMeshMaterialGroups[0].name );
}
assert( pPSET[i].numtriangles < POLYSET_MAXTRIANGLES );
for ( tri = ptri, j = 0; j < pPSET[i].numtriangles; j++ )
{
int i0 = pTO->pFaces[j].c;
int i1 = pTO->pFaces[j].b;
int i2 = pTO->pFaces[j].a;
tri->verts[0][0] = pTO->pPoints[i0].x;
tri->verts[0][1] = pTO->pPoints[i0].y;
tri->verts[0][2] = pTO->pPoints[i0].z;
tri->verts[1][0] = pTO->pPoints[i1].x;
tri->verts[1][1] = pTO->pPoints[i1].y;
tri->verts[1][2] = pTO->pPoints[i1].z;
tri->verts[2][0] = pTO->pPoints[i2].x;
tri->verts[2][1] = pTO->pPoints[i2].y;
tri->verts[2][2] = pTO->pPoints[i2].z;
/*
for ( k = 0; k < 3; k++ )
{
tri->colors[0][k] = 1;
tri->colors[1][k] = 1;
tri->colors[2][k] = 1;
}
*/
if ( pTO->pTexVerts ) {
tri->texcoords[0][0] = pTO->pTexVerts[i0].s;
tri->texcoords[0][1] = 1.0f - pTO->pTexVerts[i0].t;
tri->texcoords[1][0] = pTO->pTexVerts[i1].s;
tri->texcoords[1][1] = 1.0f - pTO->pTexVerts[i1].t;
tri->texcoords[2][0] = pTO->pTexVerts[i2].s;
tri->texcoords[2][1] = 1.0f - pTO->pTexVerts[i2].t;
}
tri++;
}
ptri += pPSET[i].numtriangles;
assert( ptri - triangles < POLYSET_MAXTRIANGLES );
}
// compute normal data
#if 0
for ( i = 0; i < numPolysets; i++ )
{
// unique vertices based solely on vertex position
ComputeNormals( &_3ds.editChunk.pNamedObjects[i].pTriObjects[0],
pPSET[i].triangles );
}
#endif
free( _3ds.editChunk.pMaterials );
free( _3ds.editChunk.pNamedObjects );
*ppPSET = pPSET;
*numpsets = numPolysets;
}

View File

@ -1,139 +0,0 @@
/*
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 struct
{
float x, y, z;
} _3DSPoint_t;
typedef struct
{
short a, b, c;
short flags;
} _3DSFace_t;
typedef struct
{
float s, t;
} _3DSTexVert_t;
typedef struct
{
char name[100];
short numFaces;
short *pFaces;
} _3DSMeshMaterialGroup_t;
typedef struct
{
char name[80];
char texture[100];
char specular[100];
char reflection[100];
char bump[100];
char opacity[100];
} _3DSMaterial_t;
typedef struct
{
short numFaces, numPoints, numTexVerts;
int numMeshMaterialGroups;
_3DSPoint_t *pPoints;
_3DSFace_t *pFaces;
_3DSTexVert_t *pTexVerts;
_3DSMeshMaterialGroup_t *pMeshMaterialGroups;
} _3DSTriObject_t;
typedef struct
{
char name[100];
int numTriObjects;
_3DSTriObject_t *pTriObjects;
} _3DSNamedObject_t;
typedef struct
{
int numNamedObjects;
int numMaterials;
_3DSNamedObject_t *pNamedObjects;
_3DSMaterial_t *pMaterials;
} _3DSEditChunk_t;
typedef struct
{
_3DSEditChunk_t editChunk;
} _3DS_t;
#define _3DS_CHUNK_NULL 0x0000
#define _3DS_CHUNK_UNKNOWN0 0x0001
#define _3DS_CHUNK_M3D_VERSION 0x0002
#define _3DS_CHUNK_M3D_KFVERSION 0x0005
#define _3DS_CHUNK_COLOR_F 0x0010
#define _3DS_CHUNK_COLOR_24 0x0011
#define _3DS_CHUNK_LIN_COLOR_24 0x0012
#define _3DS_CHUNK_LIN_COLOR_F 0x0013
#define _3DS_CHUNK_INT_PERCENTAGE 0x0030
#define _3DS_CHUNK_FLOAT_PERCENT 0x0031
#define _3DS_CHUNK_MASTER_SCALE 0x0100
#define _3DS_CHUNK_CHUNK_TYPE 0x0995
#define _3DS_CHUNK_CHUNK_UNIQUE 0x0996
#define _3DS_CHUNK_NOT_CHUNK 0x0997
#define _3DS_CHUNK_CONTAINER 0x0998
#define _3DS_CHUNK_IS_CHUNK 0x0999
#define _3DS_CHUNK_C_SXP_SELFI_MASKDATA 0x0c3c
#define _3DS_CHUNK_BITMAP 0x1100
#define _3DS_CHUNK_USE_BITMAP 0x1101
#define _3DS_CHUNK_SOLID_BGND 0x1200
#define _3DS_CHUNK_USE_SOLID_BGND 0x1201
#define _3DS_CHUNK_EDIT 0x3d3d
#define _3DS_CHUNK_MESH_VERSION 0x3d3e
#define _3DS_CHUNK_NAMED_OBJECT 0x4000
#define _3DS_CHUNK_NAMED_TRI_OBJECT 0x4100
#define _3DS_CHUNK_POINT_ARRAY 0x4110
#define _3DS_CHUNK_POINT_FLAG_ARRAY 0x4111
#define _3DS_CHUNK_FACE_ARRAY 0x4120
#define _3DS_CHUNK_MSH_MAT_GROUP 0x4130
#define _3DS_CHUNK_TEX_VERTS 0x4140
#define _3DS_CHUNK_SMOOTH_GROUP 0x4150
#define _3DS_CHUNK_MESH_MATRIX 0x4160
#define _3DS_CHUNK_MAGIC 0x4d4d
#define _3DS_CHUNK_MAT_NAME 0xa000
#define _3DS_CHUNK_TEXMAP 0xa200
#define _3DS_CHUNK_SPECMAP 0xa204
#define _3DS_CHUNK_OPACMAP 0xa210
#define _3DS_CHUNK_REFLMAP 0xa220
#define _3DS_CHUNK_BUMPMAP 0xa230
#define _3DS_CHUNK_MAT_MAPNAME 0xa300
#define _3DS_CHUNK_MAT_LIST 0xafff
#define _3DS_CHUNK_KEYFRAME_DATA 0xb000
void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, bool verbose );

View File

@ -1,787 +0,0 @@
/*
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 "q3data.h"
#if 0
/*
==================
MTF
==================
*/
cblock_t MTF( cblock_t in ){
int i, j, b, code;
byte *out_p;
int index[256];
cblock_t out;
out_p = out.data = malloc( in.count + 4 );
// write count
*out_p++ = in.count & 255;
*out_p++ = ( in.count >> 8 ) & 255;
*out_p++ = ( in.count >> 16 ) & 255;
*out_p++ = ( in.count >> 24 ) & 255;
for ( i = 0 ; i < 256 ; i++ )
index[i] = i;
for ( i = 0 ; i < in.count ; i++ )
{
b = in.data[i];
code = index[b];
*out_p++ = code;
// shuffle b indexes to 0
for ( j = 0 ; j < 256 ; j++ )
if ( index[j] < code ) {
index[j]++;
}
index[b] = 0;
}
out.count = out_p - out.data;
return out;
}
//==========================================================================
int bwt_size;
byte *bwt_data;
int bwtCompare( const void *elem1, const void *elem2 ){
int i;
int i1, i2;
int b1, b2;
i1 = *(int *)elem1;
i2 = *(int *)elem2;
for ( i = 0 ; i < bwt_size ; i++ )
{
b1 = bwt_data[i1];
b2 = bwt_data[i2];
if ( b1 < b2 ) {
return -1;
}
if ( b1 > b2 ) {
return 1;
}
if ( ++i1 == bwt_size ) {
i1 = 0;
}
if ( ++i2 == bwt_size ) {
i2 = 0;
}
}
return 0;
}
/*
==================
BWT
==================
*/
cblock_t BWT( cblock_t in ){
int *sorted;
int i;
byte *out_p;
cblock_t out;
bwt_size = in.count;
bwt_data = in.data;
sorted = malloc( in.count * sizeof( *sorted ) );
for ( i = 0 ; i < in.count ; i++ )
sorted[i] = i;
qsort( sorted, in.count, sizeof( *sorted ), bwtCompare );
out_p = out.data = malloc( in.count + 8 );
// write count
*out_p++ = in.count & 255;
*out_p++ = ( in.count >> 8 ) & 255;
*out_p++ = ( in.count >> 16 ) & 255;
*out_p++ = ( in.count >> 24 ) & 255;
// write head index
for ( i = 0 ; i < in.count ; i++ )
if ( sorted[i] == 0 ) {
break;
}
*out_p++ = i & 255;
*out_p++ = ( i >> 8 ) & 255;
*out_p++ = ( i >> 16 ) & 255;
*out_p++ = ( i >> 24 ) & 255;
// write the L column
for ( i = 0 ; i < in.count ; i++ )
*out_p++ = in.data[( sorted[i] + in.count - 1 ) % in.count];
free( sorted );
out.count = out_p - out.data;
return out;
}
//==========================================================================
typedef struct hnode_s
{
int count;
bool used;
int children[2];
} hnode_t;
int numhnodes;
hnode_t hnodes[512];
unsigned charbits[256];
int charbitscount[256];
int SmallestNode( void ){
int i;
int best, bestnode;
best = 99999999;
bestnode = -1;
for ( i = 0 ; i < numhnodes ; i++ )
{
if ( hnodes[i].used ) {
continue;
}
if ( !hnodes[i].count ) {
continue;
}
if ( hnodes[i].count < best ) {
best = hnodes[i].count;
bestnode = i;
}
}
if ( bestnode == -1 ) {
return -1;
}
hnodes[bestnode].used = true;
return bestnode;
}
void BuildChars( int nodenum, unsigned bits, int bitcount ){
hnode_t *node;
if ( nodenum < 256 ) {
if ( bitcount > 32 ) {
Error( "bitcount > 32" );
}
charbits[nodenum] = bits;
charbitscount[nodenum] = bitcount;
return;
}
node = &hnodes[nodenum];
bits <<= 1;
BuildChars( node->children[0], bits, bitcount + 1 );
bits |= 1;
BuildChars( node->children[1], bits, bitcount + 1 );
}
/*
==================
Huffman
==================
*/
cblock_t Huffman( cblock_t in ){
int i;
hnode_t *node;
int outbits, c;
unsigned bits;
byte *out_p;
cblock_t out;
int max, maxchar;
// count
memset( hnodes, 0, sizeof( hnodes ) );
for ( i = 0 ; i < in.count ; i++ )
hnodes[in.data[i]].count++;
// normalize counts
max = 0;
maxchar = 0;
for ( i = 0 ; i < 256 ; i++ )
{
if ( hnodes[i].count > max ) {
max = hnodes[i].count;
maxchar = i;
}
}
if ( max == 0 ) {
Error( "Huffman: max == 0" );
}
for ( i = 0 ; i < 256 ; i++ )
{
hnodes[i].count = ( hnodes[i].count * 255 + max - 1 ) / max;
}
// build the nodes
numhnodes = 256;
while ( numhnodes != 511 )
{
node = &hnodes[numhnodes];
// pick two lowest counts
node->children[0] = SmallestNode();
if ( node->children[0] == -1 ) {
break; // no more
}
node->children[1] = SmallestNode();
if ( node->children[1] == -1 ) {
if ( node->children[0] != numhnodes - 1 ) {
Error( "Bad smallestnode" );
}
break;
}
node->count = hnodes[node->children[0]].count +
hnodes[node->children[1]].count;
numhnodes++;
}
BuildChars( numhnodes - 1, 0, 0 );
out_p = out.data = malloc( in.count * 2 + 1024 );
memset( out_p, 0, in.count * 2 + 1024 );
// write count
*out_p++ = in.count & 255;
*out_p++ = ( in.count >> 8 ) & 255;
*out_p++ = ( in.count >> 16 ) & 255;
*out_p++ = ( in.count >> 24 ) & 255;
// save out the 256 normalized counts so the tree can be recreated
for ( i = 0 ; i < 256 ; i++ )
*out_p++ = hnodes[i].count;
// write bits
outbits = 0;
for ( i = 0 ; i < in.count ; i++ )
{
c = charbitscount[in.data[i]];
bits = charbits[in.data[i]];
while ( c )
{
c--;
if ( bits & ( 1 << c ) ) {
out_p[outbits >> 3] |= 1 << ( outbits & 7 );
}
outbits++;
}
}
out_p += ( outbits + 7 ) >> 3;
out.count = out_p - out.data;
return out;
}
//==========================================================================
/*
==================
RLE
==================
*/
#define RLE_CODE 0xe8
#define RLE_TRIPPLE 0xe9
int rle_counts[256];
int rle_bytes[256];
cblock_t RLE( cblock_t in ){
int i;
byte *out_p;
int val;
int repeat;
cblock_t out;
out_p = out.data = malloc( in.count * 2 );
// write count
*out_p++ = in.count & 255;
*out_p++ = ( in.count >> 8 ) & 255;
*out_p++ = ( in.count >> 16 ) & 255;
*out_p++ = ( in.count >> 24 ) & 255;
for ( i = 0 ; i < in.count ; )
{
val = in.data[i];
rle_bytes[val]++;
repeat = 1;
i++;
while ( i < in.count && repeat < 255 && in.data[i] == val )
{
repeat++;
i++;
}
if ( repeat < 256 ) {
rle_counts[repeat]++;
}
if ( repeat > 3 || val == RLE_CODE ) {
*out_p++ = RLE_CODE;
*out_p++ = val;
*out_p++ = repeat;
}
else
{
while ( repeat-- )
*out_p++ = val;
}
}
out.count = out_p - out.data;
return out;
}
//==========================================================================
unsigned lzss_head[256];
unsigned lzss_next[0x20000];
/*
==================
LZSS
==================
*/
#define BACK_WINDOW 0x10000
#define BACK_BITS 16
#define FRONT_WINDOW 16
#define FRONT_BITS 4
cblock_t LZSS( cblock_t in ){
int i;
byte *out_p;
cblock_t out;
int val;
int j, start, max;
int bestlength, beststart;
int outbits;
if ( in.count >= sizeof( lzss_next ) / 4 ) {
Error( "LZSS: too big" );
}
memset( lzss_head, -1, sizeof( lzss_head ) );
out_p = out.data = malloc( in.count * 2 );
memset( out.data, 0, in.count * 2 );
// write count
*out_p++ = in.count & 255;
*out_p++ = ( in.count >> 8 ) & 255;
*out_p++ = ( in.count >> 16 ) & 255;
*out_p++ = ( in.count >> 24 ) & 255;
outbits = 0;
for ( i = 0 ; i < in.count ; )
{
val = in.data[i];
#if 1
// chained search
bestlength = 0;
beststart = 0;
max = FRONT_WINDOW;
if ( i + max > in.count ) {
max = in.count - i;
}
start = lzss_head[val];
while ( start != -1 && start >= i - BACK_WINDOW )
{
// count match length
for ( j = 0 ; j < max ; j++ )
if ( in.data[start + j] != in.data[i + j] ) {
break;
}
if ( j > bestlength ) {
bestlength = j;
beststart = start;
}
start = lzss_next[start];
}
#else
// slow simple search
// search for a match
max = FRONT_WINDOW;
if ( i + max > in.count ) {
max = in.count - i;
}
start = i - BACK_WINDOW;
if ( start < 0 ) {
start = 0;
}
bestlength = 0;
beststart = 0;
for ( ; start < i ; start++ )
{
if ( in.data[start] != val ) {
continue;
}
// count match length
for ( j = 0 ; j < max ; j++ )
if ( in.data[start + j] != in.data[i + j] ) {
break;
}
if ( j > bestlength ) {
bestlength = j;
beststart = start;
}
}
#endif
beststart = BACK_WINDOW - ( i - beststart );
if ( bestlength < 3 ) { // output a single char
bestlength = 1;
out_p[outbits >> 3] |= 1 << ( outbits & 7 ); // set bit to mark char
outbits++;
for ( j = 0 ; j < 8 ; j++, outbits++ )
if ( val & ( 1 << j ) ) {
out_p[outbits >> 3] |= 1 << ( outbits & 7 );
}
}
else
{ // output a phrase
outbits++; // leave a 0 bit to mark phrase
for ( j = 0 ; j < BACK_BITS ; j++, outbits++ )
if ( beststart & ( 1 << j ) ) {
out_p[outbits >> 3] |= 1 << ( outbits & 7 );
}
for ( j = 0 ; j < FRONT_BITS ; j++, outbits++ )
if ( bestlength & ( 1 << j ) ) {
out_p[outbits >> 3] |= 1 << ( outbits & 7 );
}
}
while ( bestlength-- )
{
val = in.data[i];
lzss_next[i] = lzss_head[val];
lzss_head[val] = i;
i++;
}
}
out_p += ( outbits + 7 ) >> 3;
out.count = out_p - out.data;
return out;
}
//==========================================================================
#define MIN_REPT 15
#define MAX_REPT 0
#define HUF_TOKENS ( 256 + MAX_REPT )
unsigned charbits1[256][HUF_TOKENS];
int charbitscount1[256][HUF_TOKENS];
hnode_t hnodes1[256][HUF_TOKENS * 2];
int numhnodes1[256];
int order0counts[256];
/*
==================
SmallestNode1
==================
*/
int SmallestNode1( hnode_t *hnodes, int numhnodes ){
int i;
int best, bestnode;
best = 99999999;
bestnode = -1;
for ( i = 0 ; i < numhnodes ; i++ )
{
if ( hnodes[i].used ) {
continue;
}
if ( !hnodes[i].count ) {
continue;
}
if ( hnodes[i].count < best ) {
best = hnodes[i].count;
bestnode = i;
}
}
if ( bestnode == -1 ) {
return -1;
}
hnodes[bestnode].used = true;
return bestnode;
}
/*
==================
BuildChars1
==================
*/
void BuildChars1( int prev, int nodenum, unsigned bits, int bitcount ){
hnode_t *node;
if ( nodenum < HUF_TOKENS ) {
if ( bitcount > 32 ) {
Error( "bitcount > 32" );
}
charbits1[prev][nodenum] = bits;
charbitscount1[prev][nodenum] = bitcount;
return;
}
node = &hnodes1[prev][nodenum];
bits <<= 1;
BuildChars1( prev, node->children[0], bits, bitcount + 1 );
bits |= 1;
BuildChars1( prev, node->children[1], bits, bitcount + 1 );
}
/*
==================
BuildTree1
==================
*/
void BuildTree1( int prev ){
hnode_t *node, *nodebase;
int numhnodes;
// build the nodes
numhnodes = HUF_TOKENS;
nodebase = hnodes1[prev];
while ( 1 )
{
node = &nodebase[numhnodes];
// pick two lowest counts
node->children[0] = SmallestNode1( nodebase, numhnodes );
if ( node->children[0] == -1 ) {
break; // no more
}
node->children[1] = SmallestNode1( nodebase, numhnodes );
if ( node->children[1] == -1 ) {
break;
}
node->count = nodebase[node->children[0]].count +
nodebase[node->children[1]].count;
numhnodes++;
}
numhnodes1[prev] = numhnodes - 1;
BuildChars1( prev, numhnodes - 1, 0, 0 );
}
/*
==================
Huffman1_Count
==================
*/
void Huffman1_Count( cblock_t in ){
int i;
int prev;
int v;
int rept;
prev = 0;
for ( i = 0 ; i < in.count ; i++ )
{
v = in.data[i];
order0counts[v]++;
hnodes1[prev][v].count++;
prev = v;
#if 1
for ( rept = 1 ; i + rept < in.count && rept < MAX_REPT ; rept++ )
if ( in.data[i + rept] != v ) {
break;
}
if ( rept > MIN_REPT ) {
hnodes1[prev][255 + rept].count++;
i += rept - 1;
}
#endif
}
}
/*
==================
Huffman1_Build
==================
*/
byte scaled[256][HUF_TOKENS];
void Huffman1_Build( FILE *f ){
int i, j, v;
int max;
int total;
for ( i = 0 ; i < 256 ; i++ )
{
// normalize and save the counts
max = 0;
for ( j = 0 ; j < HUF_TOKENS ; j++ )
{
if ( hnodes1[i][j].count > max ) {
max = hnodes1[i][j].count;
}
}
if ( max == 0 ) {
max = 1;
}
total = 0;
for ( j = 0 ; j < HUF_TOKENS ; j++ )
{ // easy to overflow 32 bits here!
v = ( hnodes1[i][j].count * (double)255 + max - 1 ) / max;
if ( v > 255 ) {
Error( "v > 255" );
}
scaled[i][j] = hnodes1[i][j].count = v;
if ( v ) {
total++;
}
}
if ( total == 1 ) { // must have two tokens
if ( !scaled[i][0] ) {
scaled[i][0] = hnodes1[i][0].count = 1;
}
else{
scaled[i][1] = hnodes1[i][1].count = 1;
}
}
BuildTree1( i );
}
#if 0
// count up the total bits
total = 0;
for ( i = 0 ; i < 256 ; i++ )
for ( j = 0 ; j < 256 ; j++ )
total += charbitscount1[i][j] * hnodes1[i][j].count;
total = ( total + 7 ) / 8;
printf( "%i bytes huffman1 compressed\n", total );
#endif
fwrite( scaled, 1, sizeof( scaled ), f );
}
/*
==================
Huffman1
Order 1 compression with pre-built table
==================
*/
cblock_t Huffman1( cblock_t in ){
int i;
int outbits, c;
unsigned bits;
byte *out_p;
cblock_t out;
int prev;
int v;
int rept;
out_p = out.data = malloc( in.count * 2 + 1024 );
memset( out_p, 0, in.count * 2 + 1024 );
// write count
*out_p++ = in.count & 255;
*out_p++ = ( in.count >> 8 ) & 255;
*out_p++ = ( in.count >> 16 ) & 255;
*out_p++ = ( in.count >> 24 ) & 255;
// write bits
outbits = 0;
prev = 0;
for ( i = 0 ; i < in.count ; i++ )
{
v = in.data[i];
c = charbitscount1[prev][v];
bits = charbits1[prev][v];
if ( !c ) {
Error( "!bits" );
}
while ( c )
{
c--;
if ( bits & ( 1 << c ) ) {
out_p[outbits >> 3] |= 1 << ( outbits & 7 );
}
outbits++;
}
prev = v;
#if 1
// check for repeat encodes
for ( rept = 1 ; i + rept < in.count && rept < MAX_REPT ; rept++ )
if ( in.data[i + rept] != v ) {
break;
}
if ( rept > MIN_REPT ) {
c = charbitscount1[prev][255 + rept];
bits = charbits1[prev][255 + rept];
if ( !c ) {
Error( "!bits" );
}
while ( c )
{
c--;
if ( bits & ( 1 << c ) ) {
out_p[outbits >> 3] |= 1 << ( outbits & 7 );
}
outbits++;
}
i += rept - 1;
}
#endif
}
out_p += ( outbits + 7 ) >> 3;
out.count = out_p - out.data;
return out;
}
#endif

View File

@ -1,487 +0,0 @@
/*
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 "q3data.h"
byte *byteimage, *lbmpalette;
int byteimagewidth, byteimageheight;
char mip_prefix[1024]; // directory to dump the textures in
bool colormap_issued;
byte colormap_palette[768];
/*
==============
Cmd_Grab
$grab filename x y width height
==============
*/
void Cmd_Grab( void ){
int xl,yl,w,h,y;
byte *cropped;
char savename[1024];
char dest[1024];
GetToken( false );
if ( path_separator( token[0] ) ) {
sprintf( savename, "%s%s.pcx", writedir, token + 1 );
}
else{
sprintf( savename, "%spics/%s.pcx", writedir, token );
}
if ( g_release ) {
if ( path_separator( token[0] ) ) {
sprintf( dest, "%s.pcx", token + 1 );
}
else{
sprintf( dest, "pics/%s.pcx", token );
}
ReleaseFile( dest );
return;
}
GetToken( false );
xl = atoi( token );
GetToken( false );
yl = atoi( token );
GetToken( false );
w = atoi( token );
GetToken( false );
h = atoi( token );
if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
}
// crop it to the proper size
cropped = safe_malloc( w * h );
for ( y = 0 ; y < h ; y++ )
{
memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
}
// save off the new image
printf( "saving %s\n", savename );
CreatePath( savename );
WritePCXfile( savename, cropped, w, h, lbmpalette );
free( cropped );
}
/*
==============
Cmd_Raw
$grab filename x y width height
==============
*/
void Cmd_Raw( void ){
int xl,yl,w,h,y;
byte *cropped;
char savename[1024];
char dest[1024];
GetToken( false );
sprintf( savename, "%s%s.lmp", writedir, token );
if ( g_release ) {
sprintf( dest, "%s.lmp", token );
ReleaseFile( dest );
return;
}
GetToken( false );
xl = atoi( token );
GetToken( false );
yl = atoi( token );
GetToken( false );
w = atoi( token );
GetToken( false );
h = atoi( token );
if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
}
// crop it to the proper size
cropped = safe_malloc( w * h );
for ( y = 0 ; y < h ; y++ )
{
memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
}
// save off the new image
printf( "saving %s\n", savename );
CreatePath( savename );
SaveFile( savename, cropped, w * h );
free( cropped );
}
/*
=============================================================================
COLORMAP GRABBING
=============================================================================
*/
/*
===============
BestColor
===============
*/
byte BestColor( int r, int g, int b, int start, int stop ){
int i;
int dr, dg, db;
int bestdistortion, distortion;
int bestcolor;
byte *pal;
//
// let any color go to 0 as a last resort
//
bestdistortion = 256 * 256 * 4;
bestcolor = 0;
pal = colormap_palette + start * 3;
for ( i = start ; i <= stop ; i++ )
{
dr = r - (int)pal[0];
dg = g - (int)pal[1];
db = b - (int)pal[2];
pal += 3;
distortion = dr * dr + dg * dg + db * db;
if ( distortion < bestdistortion ) {
if ( !distortion ) {
return i; // perfect match
}
bestdistortion = distortion;
bestcolor = i;
}
}
return bestcolor;
}
/*
==============
Cmd_Colormap
$colormap filename
the brightes colormap is first in the table (FIXME: reverse this now?)
64 rows of 256 : lightmaps
256 rows of 256 : translucency table
==============
*/
void Cmd_Colormap( void ){
int levels, brights;
int l, c;
float frac, red, green, blue;
float range;
byte *cropped, *lump_p;
char savename[1024];
char dest[1024];
colormap_issued = true;
if ( !g_release ) {
memcpy( colormap_palette, lbmpalette, 768 );
}
if ( !TokenAvailable() ) { // just setting colormap_issued
return;
}
GetToken( false );
sprintf( savename, "%spics/%s.pcx", writedir, token );
if ( g_release ) {
sprintf( dest, "pics/%s.pcx", token );
ReleaseFile( dest );
return;
}
range = 2;
levels = 64;
brights = 1; // ignore 255 (transparent)
cropped = safe_malloc( ( levels + 256 ) * 256 );
lump_p = cropped;
// shaded levels
for ( l = 0; l < levels; l++ )
{
frac = range - range * (float)l / ( levels - 1 );
for ( c = 0 ; c < 256 - brights ; c++ )
{
red = lbmpalette[c * 3];
green = lbmpalette[c * 3 + 1];
blue = lbmpalette[c * 3 + 2];
red = (int)( red * frac + 0.5 );
green = (int)( green * frac + 0.5 );
blue = (int)( blue * frac + 0.5 );
//
// note: 254 instead of 255 because 255 is the transparent color, and we
// don't want anything remapping to that
// don't use color 0, because NT can't remap that (or 255)
//
*lump_p++ = BestColor( red,green,blue, 1, 254 );
}
// fullbrights always stay the same
for ( ; c < 256 ; c++ )
*lump_p++ = c;
}
// 66% transparency table
for ( l = 0; l < 255; l++ )
{
for ( c = 0 ; c < 255 ; c++ )
{
red = lbmpalette[c * 3] * 0.33 + lbmpalette[l * 3] * 0.66;
green = lbmpalette[c * 3 + 1] * 0.33 + lbmpalette[l * 3 + 1] * 0.66;
blue = lbmpalette[c * 3 + 2] * 0.33 + lbmpalette[l * 3 + 2] * 0.66;
*lump_p++ = BestColor( red,green,blue, 1, 254 );
}
*lump_p++ = 255;
}
for ( c = 0 ; c < 256 ; c++ )
*lump_p++ = 255;
// save off the new image
printf( "saving %s\n", savename );
CreatePath( savename );
WritePCXfile( savename, cropped, 256, levels + 256, lbmpalette );
free( cropped );
}
/*
=============================================================================
MIPTEX GRABBING
=============================================================================
*/
byte pixdata[256];
int d_red, d_green, d_blue;
byte palmap[32][32][32];
bool palmap_built;
/*
=============
FindColor
=============
*/
int FindColor( int r, int g, int b ){
int bestcolor;
if ( r > 255 ) {
r = 255;
}
if ( r < 0 ) {
r = 0;
}
if ( g > 255 ) {
g = 255;
}
if ( g < 0 ) {
g = 0;
}
if ( b > 255 ) {
b = 255;
}
if ( b < 0 ) {
b = 0;
}
#ifndef TABLECOLORS
bestcolor = BestColor( r, g, b, 0, 254 );
#else
bestcolor = palmap[r >> 3][g >> 3][b >> 3];
#endif
return bestcolor;
}
void BuildPalmap( void ){
#ifdef TABLECOLORS
int r, g, b;
int bestcolor;
if ( palmap_built ) {
return;
}
palmap_built = true;
for ( r = 4 ; r < 256 ; r += 8 )
{
for ( g = 4 ; g < 256 ; g += 8 )
{
for ( b = 4 ; b < 256 ; b += 8 )
{
bestcolor = BestColor( r, g, b, 1, 254 );
palmap[r >> 3][g >> 3][b >> 3] = bestcolor;
}
}
}
#endif
if ( !colormap_issued ) {
Error( "You must issue a $colormap command first" );
}
}
/*
=============
AveragePixels
=============
*/
byte AveragePixels( int count ){
int r,g,b;
int i;
int vis;
int pix;
int bestcolor;
byte *pal;
vis = 0;
r = g = b = 0;
for ( i = 0 ; i < count ; i++ )
{
pix = pixdata[i];
r += lbmpalette[pix * 3];
g += lbmpalette[pix * 3 + 1];
b += lbmpalette[pix * 3 + 2];
vis++;
}
r /= vis;
g /= vis;
b /= vis;
// error diffusion
r += d_red;
g += d_green;
b += d_blue;
//
// find the best color
//
bestcolor = FindColor( r, g, b );
// error diffusion
pal = colormap_palette + bestcolor * 3;
d_red = r - (int)pal[0];
d_green = g - (int)pal[1];
d_blue = b - (int)pal[2];
return bestcolor;
}
/*
=============================================================================
ENVIRONMENT MAP GRABBING
Creates six pcx files from tga files without any palette edge seams
also copies the tga files for GL rendering.
=============================================================================
*/
// 3dstudio environment map suffixes
const char *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
/*
=================
Cmd_Environment
=================
*/
void Cmd_Environment( void ){
char name[1024];
int i, x, y;
byte image[256 * 256];
byte *tga;
GetToken( false );
if ( g_release ) {
for ( i = 0 ; i < 6 ; i++ )
{
sprintf( name, "env/%s%s.pcx", token, suf[i] );
ReleaseFile( name );
sprintf( name, "env/%s%s.tga", token, suf[i] );
ReleaseFile( name );
}
return;
}
// get the palette
BuildPalmap();
sprintf( name, "%senv/", gamedir );
CreatePath( name );
// convert the images
for ( i = 0 ; i < 6 ; i++ )
{
sprintf( name, "%senv/%s%s.tga", gamedir, token, suf[i] );
printf( "loading %s...\n", name );
LoadTGA( name, &tga, NULL, NULL );
for ( y = 0 ; y < 256 ; y++ )
{
for ( x = 0 ; x < 256 ; x++ )
{
image[y * 256 + x] = FindColor( tga[( y * 256 + x ) * 4 + 0],tga[( y * 256 + x ) * 4 + 1],tga[( y * 256 + x ) * 4 + 2] );
}
}
free( tga );
sprintf( name, "%senv/%s%s.pcx", writedir, token, suf[i] );
if ( FileTime( name ) != -1 ) {
printf( "%s already exists, not overwriting.\n", name );
}
else{
WritePCXfile( name, image, 256, 256, colormap_palette );
}
}
}

View File

@ -1,179 +0,0 @@
/*
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 "md3lib.h"
#include "inout.h"
#include "../common/cmdlib.h"
#include <cstring>
/*
** MD3_ComputeTagFromTri
*/
void MD3_ComputeTagFromTri( md3Tag_t *pTag, const float pTri[3][3] ){
float len[3];
vec3_t axes[3], sides[3];
int longestSide, shortestSide, hypotSide;
int origin;
int j;
float d;
memset( axes, 0, sizeof( axes ) );
memset( sides, 0, sizeof( sides ) );
//
// compute sides
//
for ( j = 0; j < 3; j++ )
{
sides[j][0] = pTri[( j + 1 ) % 3][0] - pTri[j][0];
sides[j][1] = pTri[( j + 1 ) % 3][1] - pTri[j][1];
sides[j][2] = pTri[( j + 1 ) % 3][2] - pTri[j][2];
len[j] = ( float ) sqrt( DotProduct( sides[j], sides[j] ) );
}
#if 0
if ( len[0] > len[1] && len[0] > len[2] ) {
longestSide = 0; shortestSide = 1; origin = 2;
}
else if ( len[1] > len[0] && len[1] > len[2] ) {
longestSide = 1; shortestSide = 2; origin = 0;
}
else if ( len[2] > len[0] && len[2] > len[1] ) {
longestSide = 2; shortestSide = 0; origin = 1;
}
else
{
Error( "invalid tag triangle, must be a right triangle with unequal length sides" );
}
#endif
hypotSide = len[0] > len[1]? ( len[0] > len[2]? 0 : 2 ) : ( len[1] > len[2]? 1 : 2 );
origin = ( hypotSide + 2 ) % 3;
len[hypotSide] = -1;
longestSide = len[0] > len[1]? ( len[0] > len[2]? 0 : 2 ) : ( len[1] > len[2]? 1 : 2 );
len[longestSide] = -1;
shortestSide = len[0] > len[1]? ( len[0] > len[2]? 0 : 2 ) : ( len[1] > len[2]? 1 : 2 );
len[shortestSide] = -1;
// VectorNormalize( sides[shortestSide], axes[0] );
// VectorNormalize( sides[longestSide], axes[1] );
VectorNormalize( sides[longestSide], axes[0] );
VectorNormalize( sides[shortestSide], axes[1] );
// project shortest side so that it is exactly 90 degrees to the longer side
d = DotProduct( axes[0], axes[1] );
VectorMA( axes[0], -d, axes[1], axes[0] );
VectorNormalize( axes[0], axes[0] );
CrossProduct( sides[longestSide], sides[shortestSide], axes[2] );
VectorNormalize( axes[2], axes[2] );
pTag->origin[0] = pTri[origin][0];
pTag->origin[1] = pTri[origin][1];
pTag->origin[2] = pTri[origin][2];
VectorCopy( axes[0], pTag->axis[0] );
VectorCopy( axes[1], pTag->axis[1] );
VectorCopy( axes[2], pTag->axis[2] );
}
/*
==============
MD3_Dump
==============
*/
void MD3_Dump( const char *filename ){
md3Header_t header;
md3Tag_t *pTag;
md3Surface_t *pSurface;
FILE *fp;
void *_buffer;
void *buffer;
int fileSize;
int i;
if ( ( fp = fopen( filename, "rb" ) ) == 0 ) {
Error( "Unable to open '%s'\n", filename );
}
fileSize = Q_filelength( fp );
_buffer = safe_malloc( fileSize );
fread( _buffer, fileSize, 1, fp );
fclose( fp );
buffer = ( char * ) _buffer;
header = *( md3Header_t * ) _buffer;
if ( header.ident != MD3_IDENT ) {
Error( "Incorrect ident for '%s'\n", filename );
}
printf( "Contents of '%s'\n", filename );
printf( " version: %d\n", header.version );
printf( " name: %s\n", header.name );
printf( " num frames: %d\n", header.numFrames );
printf( " num tags: %d\n", header.numTags );
printf( " num surfaces: %d\n", header.numSurfaces );
printf( " num skins: %d\n", header.numSkins );
printf( " file size: %d\n", fileSize );
printf( "--- TAGS ---\n" );
pTag = ( md3Tag_t * ) ( ( ( char * ) buffer ) + header.ofsTags );
for ( i = 0; i < header.numTags; i++, pTag++ )
{
printf( " tag %d ('%s')\n", i, pTag->name );
printf( " origin: %f,%f,%f\n", pTag->origin[0], pTag->origin[1], pTag->origin[2] );
printf( " vf: %f,%f,%f\n", pTag->axis[0][0], pTag->axis[0][1], pTag->axis[0][2] );
printf( " vr: %f,%f,%f\n", pTag->axis[1][0], pTag->axis[1][1], pTag->axis[1][2] );
printf( " vu: %f,%f,%f\n", pTag->axis[2][0], pTag->axis[2][1], pTag->axis[2][2] );
}
printf( "--- SURFACES ---\n" );
pSurface = ( md3Surface_t * ) ( ( ( char * ) buffer ) + header.ofsSurfaces );
for ( i = 0; i < header.numSurfaces; i++ )
{
int j;
md3Shader_t *pShader = ( md3Shader_t * ) ( ( ( char * ) pSurface ) + pSurface->ofsShaders );
printf( "\n surface %d ('%s')\n", i, pSurface->name );
printf( " num frames: %d\n", pSurface->numFrames );
printf( " num shaders: %d\n", pSurface->numShaders );
printf( " num tris: %d\n", pSurface->numTriangles );
printf( " num verts: %d\n", pSurface->numVerts );
if ( pSurface->numShaders > 0 ) {
printf( " --- SHADERS ---\n" );
for ( j = 0; j < pSurface->numShaders; j++, pShader++ )
{
printf( " shader %d ('%s')\n", j, pShader->name );
}
}
pSurface = ( md3Surface_t * ) ( ( ( char * ) pSurface ) + pSurface->ofsEnd );
}
free( _buffer );
}

View File

@ -1,25 +0,0 @@
/*
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 "../common/qfiles.h"
void MD3_Dump( const char *filename );
void MD3_ComputeTagFromTri( md3Tag_t *pTag, const float tri[3][3] );

File diff suppressed because it is too large Load Diff

View File

@ -1,147 +0,0 @@
/*
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 0
/*
** ReindexTriangle
**
** Given a triangle_t, find which indices match into the associated
** surface's base triangles.
*/
static void ReindexTriangle( int surfno, triangle_t *pTri, int indices[3] ){
int t, i;
md3SurfaceData_t *pSurfData = &g_data.surfData[surfno];
int matches[3][3];
int numMatches = 0;
indices[0] = -1;
indices[1] = -1;
indices[2] = -1;
for ( i = 0; i < 3; i++ )
{
numMatches = 0;
matches[i][0] = -1;
matches[i][1] = -1;
matches[i][2] = -1;
for ( t = 0; t < pSurfData->header.numVerts; t++ )
{
if ( !VectorCompare( pTri->verts[i], pSurfData->baseVertexes[t].xyz ) ) {
continue;
}
/*
if ( !VectorCompare( pTri->normals[i], pSurfData->baseVertexes[t].normal ) )
continue;
if ( pTri->texcoords[i][0] != pSurfData->baseVertexes[t].st[0] )
continue;
if ( pTri->texcoords[i][1] != pSurfData->baseVertexes[t].st[1] )
continue;
*/
matches[i][numMatches++] = t;
}
if ( indices[i] == -1 ) {
// Error( "Could not ReindexTriangle, vertex not found" );
}
}
#if 0
for ( t = 0; t < psets[i].numtriangles; t++ )
{
int b;
bTri = &g_data.surfData[i].baseTriangles[t];
for ( j = 0 ; j < 3 ; j++ )
{
bVert = &bTri->v[j];
// get the xyz index
for ( k = 0; k < g_data.surfData[i].header.numVerts; k++ )
{
if ( ( g_data.surfData[i].baseVertexes[k].st[0] == bVert->st[0] ) &&
( g_data.surfData[i].baseVertexes[k].st[1] == bVert->st[1] ) &&
( VectorCompare( bVert->xyz, g_data.surfData[i].baseVertexes[k].xyz ) ) &&
( VectorCompare( bVert->normal, g_data.surfData[i].baseVertexes[k].normal ) ) ) {
break; // this vertex is already in the base vertex list
}
}
if ( k == g_data.surfData[i].header.numVerts ) { // new index
g_data.surfData[i].baseVertexes[g_data.surfData[i].header.numVerts] = *bVert;
g_data.surfData[i].header.numVerts++;
}
bVert->index = k;
}
}
#endif
}
const char *FindFrameFile( const char *frame ){
int time1;
char file1[1024];
static char retname[1024];
char base[32];
char suffix[32];
const char *s;
if ( strchr( frame, '.' ) ) {
return frame; // already in dot format
}
// split 'run1' into 'run' and '1'
s = frame + strlen( frame ) - 1;
while ( s != frame && *s >= '0' && *s <= '9' )
s--;
strcpy( suffix, s + 1 );
strcpy( base, frame );
base[s - frame + 1] = 0;
// check for 'run1.tri'
sprintf( file1, "%s/%s%s.tri", g_cddir, base, suffix );
time1 = FileTime( file1 );
if ( time1 != -1 ) {
sprintf( retname, "%s%s.tri", base, suffix );
return retname;
}
// check for 'run.1'
sprintf( file1, "%s/%s.%s",g_cddir, base, suffix );
time1 = FileTime( file1 );
if ( time1 != -1 ) {
sprintf( retname, "%s.%s", base, suffix );
return retname;
}
Error( "frame %s could not be found",frame );
return NULL;
}
#endif

View File

@ -1,316 +0,0 @@
/*
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 "p3dlib.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../common/cmdlib.h"
#include "../common/qstringops.h"
#include "../common/qpathops.h"
#define MAX_POLYSETS 64
typedef struct
{
long len;
int numPairs;
char polysetNames[MAX_POLYSETS][256];
char shaders[MAX_POLYSETS][256];
char *buffer, *curpos;
} p3d_t;
static p3d_t p3d;
static int P3DProcess();
static int P3DGetToken( int restOfLine );
static char s_token[1024];
static int s_curpair;
/*
** P3DLoad
**
*/
int P3DLoad( const char *filename ){
FILE *fp = fopen( filename, "rb" );
if ( !fp ) {
return 0;
}
memset( &p3d, 0, sizeof( p3d ) );
p3d.len = Q_filelength( fp );
p3d.curpos = p3d.buffer = safe_malloc( p3d.len );
if ( fread( p3d.buffer, p3d.len, 1, fp ) != 1 ) {
fclose( fp );
return 0;
}
fclose( fp );
return P3DProcess();
}
/*
** P3DClose
**
*/
void P3DClose(){
if ( p3d.buffer ) {
free( p3d.buffer );
p3d.buffer = 0;
}
}
int CharIsTokenDelimiter( int ch ){
if ( ch <= 32 ) {
return 1;
}
return 0;
}
int P3DSkipToToken( const char *name ){
while ( P3DGetToken( 0 ) )
{
if ( striEqual( s_token, name ) ) {
return 1;
}
}
return 0;
}
/*
** P3DGetToken
**
*/
int P3DGetToken( int restOfLine ){
int i = 0;
if ( p3d.buffer == 0 ) {
return 0;
}
if ( ( p3d.curpos - p3d.buffer ) == p3d.len ) {
return 0;
}
// skip over crap
while ( ( ( p3d.curpos - p3d.buffer ) < p3d.len ) &&
( *p3d.curpos <= 32 ) )
{
p3d.curpos++;
}
while ( ( p3d.curpos - p3d.buffer ) < p3d.len )
{
s_token[i] = *p3d.curpos;
p3d.curpos++;
i++;
if ( ( CharIsTokenDelimiter( s_token[i - 1] ) && !restOfLine ) ||
( ( s_token[i - 1] == '\n' ) ) ) {
s_token[i - 1] = 0;
break;
}
}
s_token[i] = 0;
return 1;
}
int P3DGetNextPair( char **psetName, char **associatedShader ){
if ( s_curpair < p3d.numPairs ) {
*psetName = p3d.polysetNames[s_curpair];
*associatedShader = p3d.shaders[s_curpair];
s_curpair++;
return 1;
}
return 0;
}
int P3DSkipToTokenInBlock( const char *name ){
int iLevel = 0;
while ( P3DGetToken( 0 ) )
{
if ( strEqual( s_token, "}" ) ) {
iLevel--;
}
else if ( strEqual( s_token, "{" ) ) {
iLevel++;
}
if ( striEqual( s_token, name ) ) {
return 1;
}
if ( iLevel == 0 ) {
return 0;
}
}
return 0;
}
/*
** P3DProcess
**
** Nothing fancy here.
*/
int P3DProcess(){
s_curpair = 0;
// first token should be a string
P3DGetToken( 1 ); // Voodoo Ascii File
// skip to the first Obj declaration
while ( P3DGetToken( 0 ) )
{
if ( striEqual( s_token, "Obj" ) ) {
int j = 0, k = 0;
if ( P3DSkipToToken( "Text" ) ) {
if ( P3DSkipToTokenInBlock( "TMap" ) ) {
if ( !P3DSkipToToken( "Path" ) ) {
return 0;
}
if ( !P3DGetToken( 1 ) ) {
return 0;
}
while ( s_token[j] != 0 )
{
if ( s_token[j] == '\\' ) {
j++;
p3d.shaders[p3d.numPairs][k] = '/';
}
else
{
p3d.shaders[p3d.numPairs][k] = s_token[j];
}
j++;
k++;
}
p3d.shaders[p3d.numPairs][k] = 0;
StripExtension( p3d.shaders[p3d.numPairs] );
//
// skip to the end of the Object and grab its name
//
if ( !P3DSkipToToken( "Name" ) ) {
return 0;
}
if ( P3DGetToken( 0 ) ) {
// strip off leading 'Obj_' if it exists
if ( strstr( s_token, "Obj_" ) == s_token ) {
strcpy( p3d.polysetNames[p3d.numPairs], s_token + strlen( "Obj_" ) );
}
else{
strcpy( p3d.polysetNames[p3d.numPairs], s_token );
}
// strip off trailing unused color information
// if ( strrchr( p3d.polysetNames[p3d.numPairs], '_' ) != 0 )
// *strrchr( p3d.polysetNames[p3d.numPairs], '_' ) = 0;
p3d.numPairs++;
}
else
{
return 0;
}
}
}
}
}
s_curpair = 0;
return 1;
}
#if 0
void SkinFromP3D( const char *file ){
char filename[1024];
char *psetName, *associatedShader;
/*
** a P3D file contains a list of polysets, each with a list of associated
** texture names that constitute it's
**
** Thus:
**
** P3D file -> skin
** polyset -> polyset
** texture -> texture.SHADER becomes polyset's shader
*/
sprintf( filename, "%s/%s", g_cddir, file );
if ( !P3DLoad( filename ) ) {
Error( "unable to load '%s'", filename );
}
while ( P3DGetNextPair( &psetName, &associatedShader ) )
{
int i;
// find the polyset in the object that this particular pset/shader pair
// corresponds to and append the shader to it
for ( i = 0; i < g_data.model.numSurfaces; i++ )
{
if ( striEqual( g_data.surfData[i].header.name, psetName ) ) {
char *p;
if ( strstr( associatedShader, gamedir + 1 ) ) {
p = strstr( associatedShader, gamedir + 1 ) + strlen( gamedir ) - 1;
}
else
{
p = associatedShader;
}
strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, p );
g_data.surfData[i].header.numShaders++;
}
}
}
P3DClose();
}
#endif

View File

@ -1,29 +0,0 @@
/*
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
*/
#define P3D_GET_CROSSLINE 1
#define P3D_GET_RESTOFLINE 2
int P3DLoad( const char *filename );
void P3DClose();
int P3DGetNextPair( char **name, char **associatedShader );

View File

@ -1,267 +0,0 @@
/*
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 <assert.h>
#include "q3data.h"
polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris ){
int p, np, op;
int numNewPolysets = 0;
int numSplitPolysets = 0;
polyset_t *newpsets;
int sumTriangles = 0;
for ( p = 0; p < numpolysets; p++ )
{
numNewPolysets += psets[p].numtriangles / maxTris + 1;
}
if ( numNewPolysets == numpolysets ) {
return psets;
}
printf( "Warning: creating %d polysets from input of %d polysets\n", numNewPolysets, numpolysets );
newpsets = safe_calloc( sizeof( polyset_t ) * numNewPolysets );
for ( np = 0, op = 0; op < numpolysets; op++ )
{
numSplitPolysets = ( psets[op].numtriangles / ( maxTris + 1 ) ) + 1;
if ( numSplitPolysets == 1 ) {
memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
np++;
}
else
{
sumTriangles = 0;
// split this pset into multiple smaller psets
for ( p = 0; p < numSplitPolysets; p++, np++ )
{
memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
newpsets[np].triangles = psets[op].triangles + sumTriangles;
if ( sumTriangles + maxTris > psets[op].numtriangles ) {
newpsets[np].numtriangles = psets[op].numtriangles - sumTriangles;
}
else{
newpsets[np].numtriangles = maxTris;
}
sumTriangles += newpsets[np].numtriangles;
}
}
}
*pNumNewPolysets = numNewPolysets;
return newpsets;
}
polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet ){
polyset_t *psets;
polyset_t *finalpsets;
//
// load the frame
//
if ( path_extension_is( file, "3ds" ) ) {
_3DS_LoadPolysets( file, &psets, numpolysets, g_verbose );
}
else{
Error( "TRI files no longer supported" );
}
// TRI_LoadPolysets( file, &psets, numpolysets );
/*
//
// scale polysets
//
for ( i = 0; i < psets; i++ )
{
int j;
for ( j = 0; j < psets[i].numtriangles; j++ )
{
}
}
*/
//
// split polysets if necessary
//
finalpsets = Polyset_SplitSets( psets, *numpolysets, numpolysets, maxTrisPerSet );
return finalpsets;
}
polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets ){
int p;
int sumtriangles = 0;
polyset_t *oldpsets = psets;
//
// no tag checking because this is an $oldbase and thus shouldn't have any
// tags
//
for ( p = 0; p < numpolysets; p++ )
{
sumtriangles += oldpsets[p].numtriangles;
}
psets = safe_calloc( sizeof( polyset_t ) );
psets[0].numtriangles = sumtriangles;
psets[0].triangles = safe_malloc( MD3_MAX_TRIANGLES * sizeof( triangle_t ) );
// each call to "LoadPolysets" only allocates a single large chunk of
// triangle memory that is utilized by all the polysets loaded by
// that one call
memcpy( psets[0].triangles, oldpsets[0].triangles, sizeof( triangle_t ) * sumtriangles );
free( oldpsets[0].triangles );
free( oldpsets );
return psets;
}
static float SnapFloat( float x ){
int ix;
x *= 1.0f / MD3_XYZ_SCALE;
ix = ( int ) x;
x = ( float ) ix;
x *= MD3_XYZ_SCALE;
return x;
}
void Polyset_SnapSets( polyset_t *psets, int numpolysets ){
int p;
for ( p = 0; p < numpolysets; p++ )
{
int t;
for ( t = 0; t < psets[p].numtriangles; t++ )
{
int v;
for ( v = 0; v < 3; v++ )
{
psets[p].triangles[t].verts[v][0] = SnapFloat( psets[p].triangles[t].verts[v][0] );
psets[p].triangles[t].verts[v][1] = SnapFloat( psets[p].triangles[t].verts[v][1] );
psets[p].triangles[t].verts[v][2] = SnapFloat( psets[p].triangles[t].verts[v][2] );
}
}
}
}
void Polyset_ComputeNormals( polyset_t *psets, int numpolysets ){
int p;
int i, t;
int vertexIndex[MD3_MAX_TRIANGLES][3];
vec3_t verts[MD3_MAX_VERTS];
vec3_t normals[MD3_MAX_VERTS];
vec3_t faceNormals[MD3_MAX_TRIANGLES];
//
// iterate through polysets
//
for ( p = 0; p < numpolysets; p++ )
{
int numUniqueVertices = 0;
assert( psets[p].numtriangles < MD3_MAX_TRIANGLES );
memset( vertexIndex, 0xff, sizeof( vertexIndex ) );
memset( verts, 0, sizeof( verts ) );
memset( normals, 0, sizeof( normals ) );
//
// unique vertices
//
for ( t = 0; t < psets[p].numtriangles; t++ )
{
int j;
for ( j = 0; j < 3; j++ )
{
for ( i = 0; i < numUniqueVertices; i++ )
{
if ( VectorCompare( psets[p].triangles[t].verts[j], verts[i] ) ) {
break;
}
}
if ( i == numUniqueVertices ) {
vertexIndex[t][j] = numUniqueVertices;
VectorCopy( ( psets[p].triangles[t].verts[j] ), ( verts[numUniqueVertices] ) );
numUniqueVertices++;
}
else
{
vertexIndex[t][j] = i;
}
}
}
//
// compute face normals
//
for ( t = 0; t < psets[p].numtriangles; t++ )
{
vec3_t side0, side1, facenormal;
VectorSubtract( psets[p].triangles[t].verts[0], psets[p].triangles[t].verts[1], side0 );
VectorSubtract( psets[p].triangles[t].verts[2], psets[p].triangles[t].verts[1], side1 );
CrossProduct( side0, side1, facenormal );
VectorNormalize( facenormal, faceNormals[t] );
}
//
// sum normals and copy them back
//
for ( i = 0; i < numUniqueVertices; i++ )
{
for ( t = 0; t < psets[p].numtriangles; t++ )
{
if ( vertexIndex[t][0] == i ||
vertexIndex[t][1] == i ||
vertexIndex[t][2] == i ) {
normals[i][0] += faceNormals[t][0];
normals[i][1] += faceNormals[t][1];
normals[i][2] += faceNormals[t][2];
}
}
VectorNormalize( normals[i], normals[i] );
}
for ( t = 0; t < psets[p].numtriangles; t++ )
{
VectorCopy( normals[vertexIndex[t][0]], psets[p].triangles[t].normals[0] );
VectorCopy( normals[vertexIndex[t][1]], psets[p].triangles[t].normals[1] );
VectorCopy( normals[vertexIndex[t][2]], psets[p].triangles[t].normals[2] );
}
}
}

View File

@ -1,644 +0,0 @@
/*
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 "q3data.h"
#include "md3lib.h"
#include "vfs.h"
bool g_verbose;
bool g_stripify = true;
bool g_release; // don't grab, copy output data to new tree
char g_releasedir[1024]; // c:\quake2\baseq2, etc
bool g_archive; // don't grab, copy source data to new tree
char g_only[256]; // if set, only grab this cd
bool g_skipmodel; // set true when a cd is not g_only
// bogus externs for some TA hacks (common/ using them against q3map)
char *moddir = NULL;
/*
=======================================================
PAK FILES
=======================================================
*/
unsigned Com_BlockChecksum( void *buffer, int length );
typedef struct
{
char name[56];
int filepos, filelen;
} packfile_t;
typedef struct
{
char id[4];
int dirofs;
int dirlen;
} packheader_t;
packfile_t pfiles[16384];
FILE *pakfile;
packfile_t *pf;
packheader_t pakheader;
/*
==============
ReleaseFile
Filename should be gamedir relative.
Either copies the file to the release dir, or adds it to
the pak file.
==============
*/
void ReleaseFile( char *filename ){
char source[1024];
char dest[1024];
if ( !g_release ) {
return;
}
sprintf( source, "%s%s", gamedir, filename );
sprintf( dest, "%s/%s", g_releasedir, filename );
printf( "copying to %s\n", dest );
QCopyFile( source, dest );
return;
}
typedef struct
{
// shader
// opaque
// opaque 2
// blend
// blend 2
char names[5][1024];
int num;
} ShaderFiles_t;
ShaderFiles_t s_shaderFiles;
void FindShaderFiles( char *filename ){
char buffer[1024];
char stripped[1024];
char linebuffer[1024];
int len, i;
char *buf;
const char *diffuseExtensions[] =
{
".TGA",
".WAL",
".PCX",
0
};
const char *otherExtensions[] =
{
".specular.TGA",
".blend.TGA",
".alpha.TGA",
0
};
s_shaderFiles.num = 0;
strcpy( stripped, filename );
path_set_extension( stripped, ".shader" );
if ( FileExists( stripped ) ) {
char *p;
char mapa[512], mapb[512];
strcpy( s_shaderFiles.names[s_shaderFiles.num], stripped );
s_shaderFiles.num++;
// load and parse
len = LoadFile( stripped, (void **)&buf );
p = buf;
while ( p - buf < len )
{
i = 0;
// skip spaces
while ( *p == ' ' || *p == '\n' || *p == '\t' )
p++;
// grab rest of the line
while ( *p != 0 && *p != '\n' )
{
linebuffer[i] = *p;
i++;
p++;
}
if ( *p == '\n' ) {
p++;
}
linebuffer[i] = 0;
strLower( linebuffer );
// see if the line specifies an opaque map or blendmap
if ( strstr( linebuffer, "opaquemap" ) == linebuffer ||
strstr( linebuffer, "blendmap" ) == linebuffer ) {
int j;
i = 0;
mapa[0] = mapb[0] = 0;
// skip past the keyword
while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
i++;
// skip past spaces
while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
i++;
// grab first map name
j = 0;
while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
{
mapa[j] = linebuffer[i];
j++;
i++;
}
mapa[j] = 0;
// skip past spaces
while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
i++;
// grab second map name
j = 0;
while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
{
mapb[j] = linebuffer[i];
j++;
i++;
}
mapb[j] = 0;
// store map names
if ( mapa[0] != 0 && mapa[0] != '-' ) {
sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapa );
s_shaderFiles.num++;
}
if ( mapb[0] != 0 && mapb[0] != '-' && mapb[0] != '^' && mapb[0] != '*' ) {
sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapb );
s_shaderFiles.num++;
}
}
}
}
else
{
StripExtension( stripped );
// look for diffuse maps
for ( i = 0; i < 3; i++ )
{
strcpy( buffer, stripped );
strcat( buffer, diffuseExtensions[i] );
if ( FileExists( buffer ) ) {
strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
s_shaderFiles.num++;
break;
}
}
for ( i = 0; i < 3; i++ )
{
strcpy( buffer, stripped );
strcat( buffer, otherExtensions[i] );
if ( FileExists( buffer ) ) {
strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
s_shaderFiles.num++;
}
}
}
}
/*
==============
ReleaseShader
Copies all needed files for a shader to the release directory
==============
*/
void ReleaseShader( char *filename ){
char fullpath[1024];
char dest[1024];
char stripped[1024];
int i;
sprintf( fullpath, "%s%s", gamedir, filename );
FindShaderFiles( fullpath );
for ( i = 0; i < s_shaderFiles.num; i++ )
{
strcpy( stripped, s_shaderFiles.names[i] );
if ( strstr( stripped, gamedir ) ) {
memmove( stripped, stripped + strlen( gamedir ), strlen( stripped ) );
}
sprintf( dest, "%s/%s", g_releasedir, stripped );
printf( "copying to %s\n", dest );
QCopyFile( s_shaderFiles.names[i], dest );
}
}
/*
===============
Cmd_File
This is only used to cause a file to be copied during a release
build (default.cfg, maps, etc)
===============
*/
void Cmd_File( void ){
GetToken( false );
ReleaseFile( token );
}
/*
===============
PackDirectory_r
===============
*/
#ifdef WIN32
#include "io.h"
void PackDirectory_r( char *dir ){
struct _finddata_t fileinfo;
int handle;
char dirstring[1024];
char filename[1024];
sprintf( dirstring, "%s%s/*.*", gamedir, dir );
handle = _findfirst( dirstring, &fileinfo );
if ( handle == -1 ) {
return;
}
do
{
sprintf( filename, "%s/%s", dir, fileinfo.name );
if ( fileinfo.attrib & _A_SUBDIR ) { // directory
if ( fileinfo.name[0] != '.' ) { // don't pak . and ..
PackDirectory_r( filename );
}
continue;
}
// copy or pack the file
ReleaseFile( filename );
} while ( _findnext( handle, &fileinfo ) != -1 );
_findclose( handle );
}
#else
#include <sys/types.h>
#include <sys/dir.h>
void PackDirectory_r( char *dir ){
struct dirent **namelist, *ent;
int count;
struct stat st;
int i;
char fullname[1024];
char dirstring[1024];
char *name;
sprintf( dirstring, "%s%s", gamedir, dir );
count = scandir( dirstring, &namelist, NULL, NULL );
for ( i = 0 ; i < count ; i++ )
{
ent = namelist[i];
name = ent->d_name;
if ( name[0] == '.' ) {
continue;
}
sprintf( fullname, "%s/%s", dir, name );
sprintf( dirstring, "%s%s/%s", gamedir, dir, name );
if ( stat( dirstring, &st ) == -1 ) {
Error( "fstating %s", pf->name );
}
if ( S_ISDIR( st.st_mode ) != 0 ) { // directory
PackDirectory_r( fullname );
continue;
}
// copy or pack the file
ReleaseFile( fullname );
}
}
#endif
/*
===============
Cmd_Dir
This is only used to cause a directory to be copied during a
release build (sounds, etc)
===============
*/
void Cmd_Dir( void ){
GetToken( false );
PackDirectory_r( token );
}
//========================================================================
#define MAX_RTEX 16384
int numrtex;
char rtex[MAX_RTEX][64];
void ReleaseTexture( char *name ){
int i;
char path[1024];
for ( i = 0 ; i < numrtex ; i++ )
if ( striEqual( name, rtex[i] ) ) {
return;
}
if ( numrtex == MAX_RTEX ) {
Error( "numrtex == MAX_RTEX" );
}
strcpy( rtex[i], name );
numrtex++;
sprintf( path, "textures/%s.wal", name );
ReleaseFile( path );
}
/*
===============
Cmd_Maps
Only relevant for release and pak files.
Releases the .bsp files for the maps, and scans all of the files to
build a list of all textures used, which are then released.
===============
*/
void Cmd_Maps( void ){
char map[1024];
while ( TokenAvailable() )
{
GetToken( false );
sprintf( map, "maps/%s.bsp", token );
ReleaseFile( map );
if ( !g_release ) {
continue;
}
// get all the texture references
sprintf( map, "%smaps/%s.bsp", gamedir, token );
LoadBSPFile( map );
}
}
//==============================================================
/*
===============
ParseScript
===============
*/
void ParseScript( void ){
while ( 1 )
{
do
{ // look for a line starting with a $ command
if ( !GetToken( true ) ) {
return;
}
if ( token[0] == '$' ) {
break;
}
while ( TokenAvailable() )
GetToken( false );
} while ( 1 );
//
// model commands
//
if ( !strcmp( token, "$modelname" ) ) {
Cmd_Modelname();
}
else if ( !strcmp( token, "$base" ) ) {
Cmd_Base();
}
else if ( !strcmp( token, "$exit" ) ) {
break;
}
else if ( !strcmp( token, "$3dsconvert" ) ) {
Cmd_3DSConvert();
}
else if ( !strcmp( token, "$spritebase" ) ) {
Cmd_SpriteBase();
}
else if ( !strcmp( token, "$cd" ) ) {
Cmd_Cd();
}
else if ( !strcmp( token, "$origin" ) ) {
Cmd_Origin();
}
else if ( !strcmp( token, "$scale" ) ) {
Cmd_ScaleUp();
}
else if ( !strcmp( token, "$frame" ) ) {
Cmd_Frame();
}
else if ( !strcmp( token, "$skin" ) ) {
Cmd_Skin();
}
else if ( !strcmp( token, "$spriteshader" ) ) {
Cmd_SpriteShader();
}
else if ( !strcmp( token, "$aseconvert" ) ) {
Cmd_ASEConvert( false );
}
else if ( !strcmp( token, "$aseanimconvert" ) ) {
Cmd_ASEConvert( true );
}
//
// image commands
//
else if ( !strcmp( token, "$grab" ) ) {
Cmd_Grab();
}
else if ( !strcmp( token, "$raw" ) ) {
Cmd_Raw();
}
else if ( !strcmp( token, "$colormap" ) ) {
Cmd_Colormap();
}
else if ( !strcmp( token, "$environment" ) ) {
Cmd_Environment();
}
//
// video
//
else if ( !strcmp( token, "$video" ) ) {
Cmd_Video();
}
//
// misc
//
else if ( !strcmp( token, "$file" ) ) {
Cmd_File();
}
else if ( !strcmp( token, "$dir" ) ) {
Cmd_Dir();
}
else if ( !strcmp( token, "$maps" ) ) {
Cmd_Maps();
}
else{
Error( "bad command %s\n", token );
}
}
}
//=======================================================
#include "version.h"
/*
==============
main
==============
*/
int main( int argc, char **argv ){
int i; // VC4.2 compiler bug if auto...
char path[1024];
// using GtkRadiant's versioning next to Id's versioning
printf( "Q3Data - (c) 1999 Id Software Inc.\n" );
printf( "NetRadiant - v" RADIANT_VERSION " " __DATE__ "\n" );
ExpandWildcards( &argc, &argv );
for ( i = 1 ; i < argc ; i++ )
{
if ( !strcmp( argv[i], "-release" ) ) {
g_release = true;
strcpy( g_releasedir, argv[i + 1] );
printf( "Copy output to: %s\n", g_releasedir );
i++;
}
else if ( !strcmp( argv[i], "-nostrips" ) ) {
g_stripify = false;
printf( "Not optimizing for strips\n" );
}
else if ( !strcmp( argv[i], "-writedir" ) ) {
strcpy( writedir, argv[i + 1] );
printf( "Write output to: %s\n", writedir );
i++;
}
else if ( !strcmp( argv[i], "-verbose" ) ) {
g_verbose = true;
}
else if ( !strcmp( argv[i], "-dump" ) ) {
printf( "Dumping contents of: '%s'\n", argv[i + 1] );
if ( path_extension_is( argv[i + 1], "md3" ) ) {
MD3_Dump( argv[i + 1] );
}
else
{
Error( "Do not know how to dump the contents of '%s'\n", argv[i + 1] );
}
i++;
}
else if ( !strcmp( argv[i], "-3dsconvert" ) ) {
// NOTE TTimo this is broken, tried on a sample .3ds
// what happens .. it calls the Convert3DStoMD3,
// which calls the scriptlib function in non initialized state .. and crashes
printf( "Converting %s.3DS to %s.MD3\n", argv[i + 1], argv[i + 1] );
SetQdirFromPath( argv[i + 1] );
vfsInitDirectory( gamedir );
Convert3DStoMD3( argv[i + 1] );
i++;
}
else if ( !strcmp( argv[i], "-only" ) ) {
strcpy( g_only, argv[i + 1] );
printf( "Only grabbing %s\n", g_only );
i++;
}
else if ( !strcmp( argv[i], "-gamedir" ) ) {
strcpy( gamedir, argv[i + 1] );
i++;
}
else if ( argv[i][0] == '-' ) {
Error( "Unknown option \"%s\"", argv[i] );
}
else{
break;
}
}
if ( i == argc ) {
Error( "usage: q3data [-dump <file.md3>] [-release <directory>] [-only <model>] [-3dsconvert <file.3ds>] [-verbose] [file.qdt]" );
}
for ( ; i < argc ; i++ )
{
printf( "--------------- %s ---------------\n", argv[i] );
// load the script
strcpy( path, argv[i] );
DefaultExtension( path, ".qdt" );
if ( !gamedir[0] ) {
SetQdirFromPath( path );
}
// NOTE TTimo
// q3data went through a partial conversion to use the vfs
// it was never actually tested before 1.1.1
// the code is still mostly using direct file access calls
vfsInitDirectory( gamedir );
LoadScriptFile( ExpandArg( path ), -1 );
//
// parse it
//
ParseScript();
// write out the last model
FinishModel( TYPE_UNKNOWN );
}
return 0;
}

View File

@ -1,102 +0,0 @@
/*
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
*/
// q3data.h
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <sys/stat.h>
#include "../common/cmdlib.h"
#include "../common/inout.h"
#include "../common/qstringops.h"
#include "../common/qpathops.h"
#include "scriplib.h"
#include "mathlib.h"
#include "polyset.h"
#include "trilib.h"
#include "imagelib.h"
#include "qthreads.h"
#include "l3dslib.h"
#include "bspfile.h"
#include "p3dlib.h"
#include "3dslib.h"
#include "aselib.h"
#include "md3lib.h"
void Cmd_ASEConvert( bool grabAnims );
void Cmd_3DSConvert( void );
void Cmd_Modelname( void );
void Cmd_SpriteBase( void );
void Cmd_Base( void );
void Cmd_Cd( void );
void Cmd_Origin( void );
void Cmd_ScaleUp( void );
void Cmd_Frame( void );
void Cmd_Modelname( void );
void Cmd_SpriteShader( void );
void Cmd_Skin( void );
void Cmd_Skinsize( void );
void FinishModel( int type );
void Cmd_Grab( void );
void Cmd_Raw( void );
void Cmd_Mip( void );
void Cmd_Environment( void );
void Cmd_Colormap( void );
void Cmd_File( void );
void Cmd_Dir( void );
void Cmd_StartWad( void );
void Cmd_EndWad( void );
void Cmd_Mippal( void );
void Cmd_Mipdir( void );
void Cmd_Video( void );
void ReleaseFile( char *filename );
void ReleaseShader( char *filename );
void Convert3DStoMD3( const char *filename );
void OrderMesh( int input[][3], int output[][3], int numTris );
extern byte *byteimage, *lbmpalette;
extern int byteimagewidth, byteimageheight;
extern bool g_release; // don't grab, copy output data to new tree
extern char g_releasedir[1024]; // c:\quake2\baseq2, etc
extern bool g_archive; // don't grab, copy source data to new tree
extern bool do3ds;
extern char g_only[256]; // if set, only grab this cd
extern bool g_skipmodel; // set true when a cd is not g_only
extern bool g_verbose;
extern char *trifileext;
#define TYPE_ITEM 0
#define TYPE_PLAYER 1
#define TYPE_WEAPON 2
#define TYPE_HAND 3
#define TYPE_UNKNOWN 4

View File

@ -1,293 +0,0 @@
/*
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 <stdio.h>
#include <string.h>
#include <stdlib.h>
static int s_used[8192]; // same as MD3_MAX_TRIANGLES
/*
** FindNextTriangleInStrip
**
** Given a surface and triangle this tries to find the next triangle
** in the strip that would continue the strip. The next triangle in
** the strip should have the same winding as this triangle.
*/
static int FindNextTriangleInStripOrFan( int mesh[][3], int tri, int orientation, int numTris, int odd ){
int t;
int currentTri[3];
int side;
int a, b, c;
int refa, refb;
currentTri[0] = mesh[tri][( 0 + orientation ) % 3];
currentTri[1] = mesh[tri][( 1 + orientation ) % 3];
currentTri[2] = mesh[tri][( 2 + orientation ) % 3];
if ( odd ) {
refa = currentTri[1];
refb = currentTri[2];
}
else
{
refa = currentTri[2];
refb = currentTri[0];
}
// go through all triangles and look for sides that match
// this triangle's
for ( t = 0; t < numTris; t++ )
{
// don't check against self or against previously used triangles
if ( t == tri ) {
continue;
}
if ( s_used[t] ) {
continue;
}
// check all three sides of the candidate triangle
for ( side = 0; side < 3; side++ )
{
// check only the second (abutting) side
if ( ( refa == mesh[t][( side + 1 ) % 3] ) &&
( refb == mesh[t][side] ) ) {
a = mesh[t][0];
b = mesh[t][1];
c = mesh[t][2];
// rotate the candidate triangle to align it properly in the strip
if ( side == 1 ) {
mesh[t][0] = b;
mesh[t][1] = c;
mesh[t][2] = a;
}
else if ( side == 2 ) {
mesh[t][0] = c;
mesh[t][1] = a;
mesh[t][2] = b;
}
return t;
}
/*
else
{
Error( "fans not implemented yet" );
// check only the third (abutting) side
if ( ( currentTri[2] == pSurf->baseTriangles[t].v[side].index ) &&
( currentTri[0] == pSurf->baseTriangles[t].v[(side+1)%3].index ) )
{
return t;
}
}
*/
}
}
return -1;
}
/*
** StripLength
*/
static int StripLength( int mesh[][3], int strip[][3], int tri, int orientation, int numInputTris, int fillNo ){
int stripIndex = 0;
int next;
int odd = 1;
strip[stripIndex][0] = mesh[tri][( 0 + orientation ) % 3];
strip[stripIndex][1] = mesh[tri][( 1 + orientation ) % 3];
strip[stripIndex][2] = mesh[tri][( 2 + orientation ) % 3];
s_used[tri] = fillNo;
stripIndex++;
next = tri;
while ( ( next = FindNextTriangleInStripOrFan( mesh, next, orientation, numInputTris, odd ) ) != -1 )
{
s_used[next] = fillNo;
odd = !odd;
strip[stripIndex][0] = mesh[next][0];
strip[stripIndex][1] = mesh[next][1];
strip[stripIndex][2] = mesh[next][2];
stripIndex++;
// all iterations after first need to be with an unrotated reference triangle
orientation = 0;
}
return stripIndex;
}
/*
** BuildOptimizedList
**
** Attempts to build the longest strip/fan possible. Does not adhere
** to pure strip or fan, will intermix between the two so long as some
** type of connectivity can be maintained.
*/
#define MAX_ORIENTATIONS 3
#define MAX_MATCHED_SIDES 4
#define MAX_SEED_TRIANGLES 16
static int BuildOptimizedList( int mesh[][3], int strip[][3], int numInputTris ){
int t;
int stripLen = 0;
int bestTri = -1, bestLength = 0, bestOrientation = -1;
int matchedSides = 0;
int orientation = 0;
int seedTriangles[MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
int seedLengths[MAX_ORIENTATIONS][MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
int numSeeds[MAX_MATCHED_SIDES] = { 0, 0, 0 };
int i;
// build a ranked list of candidate seed triangles based on
// number of offshoot strips. Precedence goes to orphans,
// then corners, then edges, and interiors.
memset( seedTriangles, 0xff, sizeof( seedTriangles ) );
memset( seedLengths, 0xff, sizeof( seedLengths ) );
for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
{
// find the triangle with lowest number of child strips
for ( t = 0; t < numInputTris; t++ )
{
int orientation;
int n;
if ( s_used[t] ) {
continue;
}
// try the candidate triangle in three different orientations
matchedSides = 0;
for ( orientation = 0; orientation < 3; orientation++ )
{
if ( ( n = FindNextTriangleInStripOrFan( mesh, t, orientation, numInputTris, 1 ) ) != -1 ) {
matchedSides++;
}
}
if ( matchedSides == i ) {
seedTriangles[i][numSeeds[i]] = t;
numSeeds[i]++;
if ( numSeeds[i] == MAX_SEED_TRIANGLES ) {
break;
}
}
}
}
// we have a list of potential seed triangles, so we now go through each
// potential candidate and look to see which produces the longest strip
// and select our startTri based on this
for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
{
int j;
for ( j = 0; j < numSeeds[i]; j++ )
{
for ( orientation = 0; orientation < 3; orientation++ )
{
int k;
seedLengths[orientation][i][j] = StripLength( mesh, strip, seedTriangles[i][j], orientation, numInputTris, 2 );
if ( seedLengths[orientation][i][j] > bestLength ) {
bestTri = seedTriangles[i][j];
bestLength = seedLengths[orientation][i][j];
bestOrientation = orientation;
}
for ( k = 0; k < numInputTris; k++ )
{
if ( s_used[k] == 2 ) {
s_used[k] = 0;
}
}
}
}
if ( bestTri != -1 ) {
break;
}
}
// build the strip for real
if ( bestTri != -1 ) {
stripLen = StripLength( mesh, strip, bestTri, bestOrientation, numInputTris, 1 );
}
return stripLen;
}
/*
** OrderMesh
**
** Given an input mesh and an output mesh, this routine will reorder
** the triangles within the mesh into strips/fans.
*/
void OrderMesh( int input[][3], int output[][3], int numTris ){
int i;
int sumStrippedTriangles = 0;
int strippedTriangles;
int totalStrips = 0;
int strip[8192][3]; // could dump directly into 'output', but
// this helps with debugging
memset( s_used, 0, sizeof( s_used ) );
#if 0
FILE *fp = fopen( "strip.txt", "wt" );
for ( i = 0; i < numTris; i++ )
{
fprintf( fp, "%4d: %3d %3d %3d\n", i, input[i][0], input[i][1], input[i][2] );
}
fclose( fp );
#endif
// while there are still triangles that are not part of a strip
while ( sumStrippedTriangles < numTris )
{
// build a strip
strippedTriangles = BuildOptimizedList( input, strip, numTris );
for ( i = 0; i < strippedTriangles; i++ )
{
output[sumStrippedTriangles + i][0] = strip[i][0];
output[sumStrippedTriangles + i][1] = strip[i][1];
output[sumStrippedTriangles + i][2] = strip[i][2];
}
sumStrippedTriangles += strippedTriangles;
totalStrips++;
}
printf( "Triangles on surface: %d\n", sumStrippedTriangles );
printf( "Total strips from surface: %d\n", totalStrips );
printf( "Average strip length: %f\n", ( float ) sumStrippedTriangles / totalStrips );
}

File diff suppressed because it is too large Load Diff