remove q3data and dependencies
looks like it has no any use today
This commit is contained in:
parent
d897de13d5
commit
5c67990859
36
Makefile
36
Makefile
|
|
@ -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
|
||||
|
|
|
|||
BIN
icons/q3data.ico
BIN
icons/q3data.ico
Binary file not shown.
|
Before Width: | Height: | Size: 766 B |
|
|
@ -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 {}` \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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 );
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 );
|
||||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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 );
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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 );
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
*.dsp -m 'COPY' -k 'b'
|
||||
*.dsw -m 'COPY' -k 'b'
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 );
|
||||
|
|
@ -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
|
||||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 );
|
||||
|
|
@ -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] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
Loading…
Reference in New Issue
Block a user