factor/extra/game/models/obj/obj.factor

167 lines
5.6 KiB
Factor

! Copyright (C) 2010 Erik Charlebois
! See http://factorcode.org/license.txt for BSD license.
USING: io io.encodings.ascii math.parser sequences splitting
kernel assocs io.files combinators math.order math namespaces
arrays sequences.deep accessors alien.c-types alien.data
game.models game.models.util gpu.shaders images game.models.loader
prettyprint specialized-arrays make ;
QUALIFIED-WITH: alien.c-types c
SPECIALIZED-ARRAYS: c:float c:uint ;
IN: game.models.obj
SINGLETON: obj-models
"obj" ascii obj-models register-models-class
<PRIVATE
SYMBOLS: vp vt vn current-model current-material material-dictionary models ;
TUPLE: material
{ name initial: f }
{ ambient-reflectivity initial: { 1.0 1.0 1.0 } }
{ diffuse-reflectivity initial: { 1.0 1.0 1.0 } }
{ specular-reflectivity initial: { 1.0 1.0 1.0 } }
{ transmission-filter initial: { 1.0 1.0 1.0 } }
{ dissolve initial: 1.0 }
{ specular-exponent initial: 10.0 }
{ refraction-index initial: 1.5 }
{ ambient-map initial: f }
{ diffuse-map initial: f }
{ specular-map initial: f }
{ specular-exponent-map initial: f }
{ dissolve-map initial: f }
{ displacement-map initial: f }
{ bump-map initial: f }
{ reflection-map initial: f } ;
: cm ( -- current-material ) current-material get ; inline
: md ( -- material-dictionary ) material-dictionary get ; inline
: strings>numbers ( strings -- numbers )
[ string>number ] map ;
: strings>faces ( strings -- faces )
[ "/" split [ string>number ] map ] map ;
: split-string ( string -- strings )
" \t\n" split harvest ;
: line>mtl ( line -- )
" \t\n" split harvest
[
[ rest ] [ first ] bi
{
{ "newmtl" [ first
[ material new swap >>name current-material set ]
[ cm swap md set-at ] bi
] }
{ "Ka" [ 3 head strings>numbers cm ambient-reflectivity<< ] }
{ "Kd" [ 3 head strings>numbers cm diffuse-reflectivity<< ] }
{ "Ks" [ 3 head strings>numbers cm specular-reflectivity<< ] }
{ "Tf" [ 3 head strings>numbers cm transmission-filter<< ] }
{ "d" [ first string>number cm dissolve<< ] }
{ "Ns" [ first string>number cm specular-exponent<< ] }
{ "Ni" [ first string>number cm refraction-index<< ] }
{ "map_Ka" [ first cm ambient-map<< ] }
{ "map_Kd" [ first cm diffuse-map<< ] }
{ "map_Ks" [ first cm specular-map<< ] }
{ "map_Ns" [ first cm specular-exponent-map<< ] }
{ "map_d" [ first cm dissolve-map<< ] }
{ "map_bump" [ first cm bump-map<< ] }
{ "bump" [ first cm bump-map<< ] }
{ "disp" [ first cm displacement-map<< ] }
{ "refl" [ first cm reflection-map<< ] }
[ 2drop ]
} case
] unless-empty ;
: read-mtl ( file -- material-dictionary )
[
f current-material ,,
H{ } clone material-dictionary ,,
] H{ } make
[
ascii file-lines [ line>mtl ] each
md
] with-variables ;
VERTEX-FORMAT: obj-vertex-format
{ "POSITION" float-components 3 f }
{ "TEXCOORD" float-components 2 f }
{ "NORMAL" float-components 3 f } ;
: triangle>aos ( x -- y )
dup length
{
{ 3 [
first3
[ 1 - vp get nth ]
[ 1 - vt get nth ]
[ 1 - vn get nth ] tri* 3array flatten
] }
{ 2 [
first2
[ 1 - vp get nth ]
[ 1 - vt get nth ] bi* 2array flatten
] }
} case ;
: quad>aos ( x -- y z )
[ 3 head [ triangle>aos 1array ] map ]
[ [ 2 swap nth ]
[ 3 swap nth ]
[ 0 swap nth ] tri 3array
[ triangle>aos 1array ] map ]
bi ;
: face>aos ( x -- y )
dup length
{
{ 3 [ [ triangle>aos 1array ] map 1array ] }
{ 4 [ quad>aos 2array ] }
} case ;
: push* ( elt seq -- seq )
[ push ] keep ;
: push-current-model ( -- )
current-model get [
[ dseq>> flatten c:float >c-array ]
[ iseq>> flatten c:uint >c-array ]
bi obj-vertex-format current-material get model boa models get push
V{ } V{ } H{ } <indexed-seq> current-model set
] unless-empty ;
: line>obj ( line -- )
split-string
[
[ rest ] [ first ] bi
{
{ "mtllib" [ first read-mtl material-dictionary set ] }
{ "v" [ strings>numbers 3 head vp [ push* ] change ] }
{ "vt" [ strings>numbers 2 head vt [ push* ] change ] }
{ "vn" [ strings>numbers 3 head vn [ push* ] change ] }
{ "usemtl" [ push-current-model first md at current-material set ] }
{ "f" [ strings>faces face>aos [ [ current-model [ push* ] change ] each ] each ] }
[ 2drop ]
} case
] unless-empty ;
PRIVATE>
M: obj-models stream>models
drop
[
V{ } clone vp ,,
V{ } clone vt ,,
V{ } clone vn ,,
V{ } clone models ,,
V{ } V{ } H{ } <indexed-seq> current-model ,,
f current-material ,,
f material-dictionary ,,
] H{ } make
[
[ line>obj ] each-stream-line push-current-model
models get
] with-variables ;