1+ package models ;
2+
3+ import away3d .core .base .Geometry ;
4+ import flixel .FlxSprite ;
5+ import away3d .textures .BitmapCubeTexture ;
6+ import away3d .primitives .SkyBox ;
7+ import away3d .lights .shadowmaps .DirectionalShadowMapper ;
8+ import lime .app .Application ;
9+ import flixel .FlxG ;
10+ // import lime.utils.Assets;
11+ import away3d .entities .Sprite3D ;
12+
13+ import away3d .entities .Mesh ;
14+ import away3d .events .Asset3DEvent ;
15+ import away3d .library .assets .Asset3DType ;
16+ import away3d .lights .DirectionalLight ;
17+ import away3d .loaders .Loader3D ;
18+ import away3d .loaders .misc .AssetLoaderContext ;
19+ import away3d .loaders .parsers .OBJParser ;
20+ import away3d .loaders .parsers .DAEParser ;
21+ import away3d .materials .TextureMaterial ;
22+ import away3d .materials .lightpickers .StaticLightPicker ;
23+ import away3d .controllers .FirstPersonController ;
24+ import away3d .utils .Cast ;
25+ import flx3D .FlxView3D ;
26+ import openfl .utils .Assets ;
27+ import flx3D .Flx3DUtil ;
28+ using StringTools ;
29+
30+ /**
31+ * @see https://github.com/TheZoroForce240/Voiid-Chronicles-V2-Source/blob/main/source/states/TestState.hx
32+ */
33+ class Scene3D extends FlxView3D
34+ {
35+ // Mesh
36+ public var meshs : Map <String , Array <Mesh >> = new Map <String , Array <Mesh >>();
37+
38+ // Lighting
39+ public var light : DirectionalLight ;
40+ var lightPicker : StaticLightPicker ;
41+
42+ // Loading
43+ private var _loader : Loader3D ;
44+ private var assetLoaderContext : AssetLoaderContext = new AssetLoaderContext ();
45+ private var texMap : Map <String , TextureMaterial >;
46+
47+ public var enableDebugCam : Bool = true ;
48+ public var controller : FirstPersonController ;
49+ public function new (x : Float = 0 , y : Float = 0 , width : Int = - 1 , height : Int = - 1 )
50+ {
51+ super (x , y , width , height );
52+
53+ antialiasing = true ;
54+
55+ #if (haxe >= "4.0.0")
56+ texMap = new Map ();
57+ #else
58+ texMap = new Map <String , TextureMaterial >();
59+ #end
60+
61+
62+ light = new DirectionalLight ();
63+ light .ambient = 0.1 ;
64+ light .diffuse = 0.5 ;
65+ light .ambientColor = toColor (" 0.31" , " 0.07" , " 0.51" );
66+ light .z - = 10 ;
67+
68+
69+ view .scene .addChild (light );
70+
71+ view .camera .lens .near = 0.1 ;
72+ view .antiAlias = 1 ;
73+ lightPicker = new StaticLightPicker ([light ]);
74+ light .shadowMapper = new DirectionalShadowMapper ();
75+ light ._castsShadows = true ;
76+
77+ controller = new FirstPersonController (view .camera , 0 , 0 );
78+ controller .fly = true ;
79+ // view.filters3d = [new BloomFilter3D(1, 1, .75, 0.1, 3)];
80+ // view.filters3d = [new DepthOfFieldFilter3D(), new MotionBlurFilter3D(), new BloomFilter3D(1, 1, .75, 0.05, 4)];
81+ }
82+
83+ public function loadModel (folder : String , name : String , fileFormat : String )
84+ {
85+ _loader = new Loader3D ();
86+ var modelBytes = Assets .getBytes (folder + name + ' .' + fileFormat );
87+ if (fileFormat == ' obj' )
88+ {
89+ assetLoaderContext .mapUrlToData (name + " .mtl" , Assets .getBytes (folder + name + " .mtl" ));
90+ var mtl = Assets .getText (folder + name + " .mtl" ); // could just get it from bytes but who cares lol
91+ var mtlLines = mtl .split (" \n " );
92+
93+ // need to redo mtl parsing separate from the obj parser because of the workaround for multi tex support
94+
95+ // store current string data for when it creates the tex, map_kd is normally the last line in a material (which is when it gets made)
96+ var curMat = " " ;
97+ var curSpec = " " ;
98+ var curSpecCol = " " ;
99+ var curAmbCol = " " ;
100+ var curDifCol = " " ;
101+ var curAlpha = " " ;
102+
103+ for (l in mtlLines )
104+ {
105+ if (l .startsWith (" newmtl " ))
106+ {
107+ curMat = l .replace (' newmtl ' , ' ' );
108+ }
109+ else if (l .startsWith (" Ns " ))
110+ {
111+ curSpec = l .replace (' Ns ' , ' ' );
112+ }
113+ else if (l .startsWith (" Ks " ))
114+ {
115+ curSpecCol = l .replace (' Ks ' , ' ' );
116+ }
117+ else if (l .startsWith (" Ka " ))
118+ {
119+ curAmbCol = l .replace (' Ka ' , ' ' );
120+ }
121+ else if (l .startsWith (" Kd " ))
122+ {
123+ curDifCol = l .replace (' Kd ' , ' ' );
124+ }
125+ else if (l .startsWith (" d " ))
126+ {
127+ curAlpha = l .replace (' d ' , ' ' );
128+ }
129+ else if (l .startsWith (" map_Kd " ))
130+ {
131+ var texToLoad = l .replace (' map_Kd ' , ' ' ).rtrim (); // remove map_Kd from the line
132+ // var texSprite = new FlxSprite().loadGraphic(folder+texToLoad);
133+ // var bitData = BitmapData.fromFile(folder+texToLoad);
134+ // FlxG.state.add(texSprite);
135+ // trace(folder+texToLoad);
136+ var bitmapTex = Cast .bitmapTexture (folder + texToLoad );
137+ var tex = new TextureMaterial (bitmapTex , true , true );
138+ tex .texture = bitmapTex ;
139+ // set values
140+ tex .specular = Std .parseFloat (curSpec ) * 0.001 ;
141+ var specCol = curSpecCol .split (" " ); tex .specularColor = toColor (specCol [0 ], specCol [1 ], specCol [2 ]);
142+ var ambCol = curAmbCol .split (" " ); tex .ambientColor = toColor (ambCol [0 ], ambCol [1 ], ambCol [2 ]);
143+ var difCol = curDifCol .split (" " ); tex .diffuseMethod .diffuseColor = toColor (difCol [0 ], difCol [1 ], difCol [2 ]);
144+ tex .alpha = Std .parseFloat (curAlpha );
145+ tex .alphaThreshold = 0.5 ; // so transparent textures work properly
146+
147+
148+ texMap .set (curMat , tex );
149+
150+ // trace(texMap.get(curMat));
151+ // texMap[curMat] = tex;
152+
153+ // trace("loading tex " + texToLoad);
154+ }
155+ }
156+ _loader .loadData (modelBytes , assetLoaderContext , name , new OBJParser ());
157+ }
158+ else if (fileFormat == ' dae' )
159+ {
160+ _loader .loadData (modelBytes , assetLoaderContext , name , new DAEParser ());
161+ }
162+
163+
164+
165+ _loader .addEventListener (Asset3DEvent .ASSET_COMPLETE , onAssetDone );
166+ view .scene .addChild (_loader );
167+ }
168+ // taken from the obj parser
169+ public function toColor (r : String , g : String , b : String ): UInt
170+ {
171+ return Std .int (Std .parseFloat (r ) * 255 ) << 16 | Std .int (Std .parseFloat (g ) * 255 ) << 8 | Std .int (Std .parseFloat (b ) * 255 );
172+ }
173+
174+ public function onAssetDone (event : Asset3DEvent )
175+ {
176+ if (event .asset .assetType == Asset3DType .MESH )
177+ {
178+ var mesh : Mesh = cast (event .asset , Mesh );
179+ var matName = mesh .material .name .split (' ~' )[0 ].rtrim ();
180+ // trace(mesh.material.name);
181+
182+ for (texName => tex in texMap )
183+ {
184+ if (texName .contains (matName ) || matName .contains (texName )) // it was acting weird and it fixed it???
185+ {
186+ mesh .material = tex ; // set the tex
187+ mesh .material .lightPicker = lightPicker ;
188+ }
189+ }
190+ // trace(texName);
191+
192+ if (texMap .exists (matName )) // randomly stopped working
193+ {
194+
195+ }
196+
197+
198+
199+ // trace(event.asset.assetNamespace);
200+ switch (event .asset .assetNamespace )
201+ {
202+ case " matt" :
203+ mesh .scale (20 );
204+ mesh .rotationY = - 90 ;
205+ mesh .rotationX = 90 ;
206+
207+ }
208+
209+ if (! meshs .exists (event .asset .assetNamespace ))
210+ meshs .set (event .asset .assetNamespace , []); // make sure its empty
211+ meshs .get (event .asset .assetNamespace ).push (mesh );
212+ }
213+ }
214+
215+ public function loadSkybox (folder : String )
216+ {
217+ var cubeMap : BitmapCubeTexture = new BitmapCubeTexture
218+ (
219+ Cast .bitmapData (folder + " right.png" ),
220+ Cast .bitmapData (folder + " left.png" ),
221+ Cast .bitmapData (folder + " top.png" ),
222+ Cast .bitmapData (folder + " bottom.png" ),
223+ Cast .bitmapData (folder + " front.png" ),
224+ Cast .bitmapData (folder + " back.png" )
225+ );
226+ var skybox : SkyBox = new SkyBox (cubeMap );
227+ view .scene .addChild (skybox );
228+ }
229+
230+ override function update (elapsed : Float )
231+ {
232+ if (enableDebugCam )
233+ debugCamControls (elapsed );
234+ super .update (elapsed );
235+ }
236+
237+ override function destroy ()
238+ {
239+ for (name => mesh in meshs )
240+ {
241+ for (s in mesh )
242+ {
243+ Flx3DUtil .dispose (s );
244+ }
245+ }
246+ super .destroy ();
247+ }
248+
249+ function debugCamControls (elapsed : Float )
250+ {
251+ /* if (FlxG.keys.pressed.LEFT)
252+ {
253+ controller.panAngle -= 30*elapsed;
254+ }
255+ if (FlxG.keys.pressed.RIGHT)
256+ {
257+ controller.panAngle += 30*elapsed;
258+ }
259+ if (FlxG.keys.pressed.UP)
260+ {
261+ controller.tiltAngle -= 30*elapsed;
262+ }
263+ if (FlxG.keys.pressed.DOWN)
264+ {
265+ controller.tiltAngle += 30*elapsed;
266+ }*/
267+
268+ if (FlxG .mouse .deltaScreenX != 0 )
269+ controller .panAngle + = FlxG .mouse .deltaScreenX ;
270+ if (FlxG .mouse .deltaScreenY != 0 )
271+ controller .tiltAngle + = FlxG .mouse .deltaScreenY ;
272+
273+ if (FlxG .keys .pressed .W )
274+ {
275+ controller .incrementWalk (100 * elapsed );
276+ }
277+ if (FlxG .keys .pressed .S )
278+ {
279+ controller .incrementWalk (- 100 * elapsed );
280+ }
281+ if (FlxG .keys .pressed .A )
282+ {
283+ controller .incrementStrafe (- 100 * elapsed );
284+ }
285+ if (FlxG .keys .pressed .D )
286+ {
287+ controller .incrementStrafe (100 * elapsed );
288+ }
289+ if (FlxG .keys .pressed .SPACE )
290+ {
291+ view .camera .y + = elapsed * 100 ;
292+ }
293+ if (FlxG .keys .pressed .SHIFT )
294+ {
295+ view .camera .y - = elapsed * 100 ;
296+ }
297+
298+ controller .update (true );
299+
300+ Application .current .window .mouseLock = true ;
301+ }
302+
303+ public function makeSpriteObject (sprite : FlxSprite , geo : Geometry )
304+ {
305+ var mat = new TextureMaterial (Cast .bitmapTexture (sprite .updateFramePixels ()));
306+ // var spr3D:Sprite3D = new Sprite3D(new TextureMaterial(Cast.bitmapTexture("assets/images/icons/bf-icons.png")), 128, 128);
307+ var mesh : Mesh = new Mesh (geo , mat );
308+ view .scene .addChild (mesh );
309+ return mesh ;
310+ }
311+ public function makeSpriteBillboard (sprite : FlxSprite )
312+ {
313+ var mat = new TextureMaterial (Cast .bitmapTexture (sprite .updateFramePixels ()));
314+ var spr3D : Sprite3D = new Sprite3D (mat , 128 , 128 );
315+ view .scene .addChild (spr3D );
316+ return spr3D ;
317+ }
318+ }
0 commit comments