VRMLLoader.js 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162
  1. /**
  2. * @author Mugen87 / https://github.com/Mugen87
  3. */
  4. import {
  5. BackSide,
  6. BoxBufferGeometry,
  7. BufferAttribute,
  8. BufferGeometry,
  9. ClampToEdgeWrapping,
  10. Color,
  11. ConeBufferGeometry,
  12. CylinderBufferGeometry,
  13. DataTexture,
  14. DoubleSide,
  15. FileLoader,
  16. Float32BufferAttribute,
  17. FrontSide,
  18. Group,
  19. LineBasicMaterial,
  20. LineSegments,
  21. Loader,
  22. LoaderUtils,
  23. Mesh,
  24. MeshBasicMaterial,
  25. MeshPhongMaterial,
  26. Object3D,
  27. Points,
  28. PointsMaterial,
  29. RGBAFormat,
  30. RGBFormat,
  31. RepeatWrapping,
  32. Scene,
  33. SphereBufferGeometry,
  34. TextureLoader,
  35. Vector2,
  36. Vector3
  37. } from "../../../build/three.module.js";
  38. import { chevrotain } from "../libs/chevrotain.module.min.js";
  39. /* global chevrotain */
  40. var VRMLLoader = ( function () {
  41. // dependency check
  42. if ( typeof chevrotain === 'undefined' ) {
  43. throw Error( 'THREE.VRMLLoader: External library chevrotain.min.js required.' );
  44. }
  45. // class definitions
  46. function VRMLLoader( manager ) {
  47. Loader.call( this, manager );
  48. }
  49. VRMLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  50. constructor: VRMLLoader,
  51. load: function ( url, onLoad, onProgress, onError ) {
  52. var scope = this;
  53. var path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path;
  54. var loader = new FileLoader( this.manager );
  55. loader.setPath( scope.path );
  56. loader.load( url, function ( text ) {
  57. onLoad( scope.parse( text, path ) );
  58. }, onProgress, onError );
  59. },
  60. parse: function ( data, path ) {
  61. var nodeMap = {};
  62. function generateVRMLTree( data ) {
  63. // create lexer, parser and visitor
  64. var tokenData = createTokens();
  65. var lexer = new VRMLLexer( tokenData.tokens );
  66. var parser = new VRMLParser( tokenData.tokenVocabulary );
  67. var visitor = createVisitor( parser.getBaseCstVisitorConstructor() );
  68. // lexing
  69. var lexingResult = lexer.lex( data );
  70. parser.input = lexingResult.tokens;
  71. // parsing
  72. var cstOutput = parser.vrml();
  73. if ( parser.errors.length > 0 ) {
  74. console.error( parser.errors );
  75. throw Error( 'THREE.VRMLLoader: Parsing errors detected.' );
  76. }
  77. // actions
  78. var ast = visitor.visit( cstOutput );
  79. return ast;
  80. }
  81. function createTokens() {
  82. var createToken = chevrotain.createToken;
  83. // from http://gun.teipir.gr/VRML-amgem/spec/part1/concepts.html#SyntaxBasics
  84. var RouteIdentifier = createToken( { name: 'RouteIdentifier', pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*[\.][^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/ } );
  85. var Identifier = createToken( { name: 'Identifier', pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/, longer_alt: RouteIdentifier } );
  86. // from http://gun.teipir.gr/VRML-amgem/spec/part1/nodesRef.html
  87. var nodeTypes = [
  88. 'Anchor', 'Billboard', 'Collision', 'Group', 'Transform', // grouping nodes
  89. 'Inline', 'LOD', 'Switch', // special groups
  90. 'AudioClip', 'DirectionalLight', 'PointLight', 'Script', 'Shape', 'Sound', 'SpotLight', 'WorldInfo', // common nodes
  91. 'CylinderSensor', 'PlaneSensor', 'ProximitySensor', 'SphereSensor', 'TimeSensor', 'TouchSensor', 'VisibilitySensor', // sensors
  92. 'Box', 'Cone', 'Cylinder', 'ElevationGrid', 'Extrusion', 'IndexedFaceSet', 'IndexedLineSet', 'PointSet', 'Sphere', // geometries
  93. 'Color', 'Coordinate', 'Normal', 'TextureCoordinate', // geometric properties
  94. 'Appearance', 'FontStyle', 'ImageTexture', 'Material', 'MovieTexture', 'PixelTexture', 'TextureTransform', // appearance
  95. 'ColorInterpolator', 'CoordinateInterpolator', 'NormalInterpolator', 'OrientationInterpolator', 'PositionInterpolator', 'ScalarInterpolator', // interpolators
  96. 'Background', 'Fog', 'NavigationInfo', 'Viewpoint', // bindable nodes
  97. 'Text' // Text must be placed at the end of the regex so there are no matches for TextureTransform and TextureCoordinate
  98. ];
  99. //
  100. var Version = createToken( {
  101. name: 'Version',
  102. pattern: /#VRML.*/,
  103. longer_alt: Identifier
  104. } );
  105. var NodeName = createToken( {
  106. name: 'NodeName',
  107. pattern: new RegExp( nodeTypes.join( '|' ) ),
  108. longer_alt: Identifier
  109. } );
  110. var DEF = createToken( {
  111. name: 'DEF',
  112. pattern: /DEF/,
  113. longer_alt: Identifier
  114. } );
  115. var USE = createToken( {
  116. name: 'USE',
  117. pattern: /USE/,
  118. longer_alt: Identifier
  119. } );
  120. var ROUTE = createToken( {
  121. name: 'ROUTE',
  122. pattern: /ROUTE/,
  123. longer_alt: Identifier
  124. } );
  125. var TO = createToken( {
  126. name: 'TO',
  127. pattern: /TO/,
  128. longer_alt: Identifier
  129. } );
  130. //
  131. var StringLiteral = createToken( { name: "StringLiteral", pattern: /"(:?[^\\"\n\r]+|\\(:?[bfnrtv"\\/]|u[0-9a-fA-F]{4}))*"/ } );
  132. var HexLiteral = createToken( { name: 'HexLiteral', pattern: /0[xX][0-9a-fA-F]+/ } );
  133. var NumberLiteral = createToken( { name: 'NumberLiteral', pattern: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/ } );
  134. var TrueLiteral = createToken( { name: 'TrueLiteral', pattern: /TRUE/ } );
  135. var FalseLiteral = createToken( { name: 'FalseLiteral', pattern: /FALSE/ } );
  136. var NullLiteral = createToken( { name: 'NullLiteral', pattern: /NULL/ } );
  137. var LSquare = createToken( { name: 'LSquare', pattern: /\[/ } );
  138. var RSquare = createToken( { name: 'RSquare', pattern: /]/ } );
  139. var LCurly = createToken( { name: 'LCurly', pattern: /{/ } );
  140. var RCurly = createToken( { name: 'RCurly', pattern: /}/ } );
  141. var Comment = createToken( {
  142. name: 'Comment',
  143. pattern: /#.*/,
  144. group: chevrotain.Lexer.SKIPPED
  145. } );
  146. // commas, blanks, tabs, newlines and carriage returns are whitespace characters wherever they appear outside of string fields
  147. var WhiteSpace = createToken( {
  148. name: 'WhiteSpace',
  149. pattern: /[ ,\s]/,
  150. group: chevrotain.Lexer.SKIPPED
  151. } );
  152. var tokens = [
  153. WhiteSpace,
  154. // keywords appear before the Identifier
  155. NodeName,
  156. DEF,
  157. USE,
  158. ROUTE,
  159. TO,
  160. TrueLiteral,
  161. FalseLiteral,
  162. NullLiteral,
  163. // the Identifier must appear after the keywords because all keywords are valid identifiers
  164. Version,
  165. Identifier,
  166. RouteIdentifier,
  167. StringLiteral,
  168. HexLiteral,
  169. NumberLiteral,
  170. LSquare,
  171. RSquare,
  172. LCurly,
  173. RCurly,
  174. Comment
  175. ];
  176. var tokenVocabulary = {};
  177. for ( var i = 0, l = tokens.length; i < l; i ++ ) {
  178. var token = tokens[ i ];
  179. tokenVocabulary[ token.name ] = token;
  180. }
  181. return { tokens: tokens, tokenVocabulary: tokenVocabulary };
  182. }
  183. function createVisitor( BaseVRMLVisitor ) {
  184. // the visitor is created dynmaically based on the given base class
  185. function VRMLToASTVisitor() {
  186. BaseVRMLVisitor.call( this );
  187. this.validateVisitor();
  188. }
  189. VRMLToASTVisitor.prototype = Object.assign( Object.create( BaseVRMLVisitor.prototype ), {
  190. constructor: VRMLToASTVisitor,
  191. vrml: function ( ctx ) {
  192. var data = {
  193. version: this.visit( ctx.version ),
  194. nodes: [],
  195. routes: []
  196. };
  197. for ( var i = 0, l = ctx.node.length; i < l; i ++ ) {
  198. var node = ctx.node[ i ];
  199. data.nodes.push( this.visit( node ) );
  200. }
  201. if ( ctx.route ) {
  202. for ( var i = 0, l = ctx.route.length; i < l; i ++ ) {
  203. var route = ctx.route[ i ];
  204. data.routes.push( this.visit( route ) );
  205. }
  206. }
  207. return data;
  208. },
  209. version: function ( ctx ) {
  210. return ctx.Version[ 0 ].image;
  211. },
  212. node: function ( ctx ) {
  213. var data = {
  214. name: ctx.NodeName[ 0 ].image,
  215. fields: []
  216. };
  217. if ( ctx.field ) {
  218. for ( var i = 0, l = ctx.field.length; i < l; i ++ ) {
  219. var field = ctx.field[ i ];
  220. data.fields.push( this.visit( field ) );
  221. }
  222. }
  223. // DEF
  224. if ( ctx.def ) {
  225. data.DEF = this.visit( ctx.def[ 0 ] );
  226. }
  227. return data;
  228. },
  229. field: function ( ctx ) {
  230. var data = {
  231. name: ctx.Identifier[ 0 ].image,
  232. type: null,
  233. values: null
  234. };
  235. var result;
  236. // SFValue
  237. if ( ctx.singleFieldValue ) {
  238. result = this.visit( ctx.singleFieldValue[ 0 ] );
  239. }
  240. // MFValue
  241. if ( ctx.multiFieldValue ) {
  242. result = this.visit( ctx.multiFieldValue[ 0 ] );
  243. }
  244. data.type = result.type;
  245. data.values = result.values;
  246. return data;
  247. },
  248. def: function ( ctx ) {
  249. return ctx.Identifier[ 0 ].image;
  250. },
  251. use: function ( ctx ) {
  252. return { USE: ctx.Identifier[ 0 ].image };
  253. },
  254. singleFieldValue: function ( ctx ) {
  255. return processField( this, ctx );
  256. },
  257. multiFieldValue: function ( ctx ) {
  258. return processField( this, ctx );
  259. },
  260. route: function ( ctx ) {
  261. var data = {
  262. FROM: ctx.RouteIdentifier[ 0 ].image,
  263. TO: ctx.RouteIdentifier[ 1 ].image
  264. };
  265. return data;
  266. }
  267. } );
  268. function processField( scope, ctx ) {
  269. var field = {
  270. type: null,
  271. values: []
  272. };
  273. if ( ctx.node ) {
  274. field.type = 'node';
  275. for ( var i = 0, l = ctx.node.length; i < l; i ++ ) {
  276. var node = ctx.node[ i ];
  277. field.values.push( scope.visit( node ) );
  278. }
  279. }
  280. if ( ctx.use ) {
  281. field.type = 'use';
  282. for ( var i = 0, l = ctx.use.length; i < l; i ++ ) {
  283. var use = ctx.use[ i ];
  284. field.values.push( scope.visit( use ) );
  285. }
  286. }
  287. if ( ctx.StringLiteral ) {
  288. field.type = 'string';
  289. for ( var i = 0, l = ctx.StringLiteral.length; i < l; i ++ ) {
  290. var stringLiteral = ctx.StringLiteral[ i ];
  291. field.values.push( stringLiteral.image.replace( /'|"/g, '' ) );
  292. }
  293. }
  294. if ( ctx.NumberLiteral ) {
  295. field.type = 'number';
  296. for ( var i = 0, l = ctx.NumberLiteral.length; i < l; i ++ ) {
  297. var numberLiteral = ctx.NumberLiteral[ i ];
  298. field.values.push( parseFloat( numberLiteral.image ) );
  299. }
  300. }
  301. if ( ctx.HexLiteral ) {
  302. field.type = 'hex';
  303. for ( var i = 0, l = ctx.HexLiteral.length; i < l; i ++ ) {
  304. var hexLiteral = ctx.HexLiteral[ i ];
  305. field.values.push( hexLiteral.image );
  306. }
  307. }
  308. if ( ctx.TrueLiteral ) {
  309. field.type = 'boolean';
  310. for ( var i = 0, l = ctx.TrueLiteral.length; i < l; i ++ ) {
  311. var trueLiteral = ctx.TrueLiteral[ i ];
  312. if ( trueLiteral.image === 'TRUE' ) field.values.push( true );
  313. }
  314. }
  315. if ( ctx.FalseLiteral ) {
  316. field.type = 'boolean';
  317. for ( var i = 0, l = ctx.FalseLiteral.length; i < l; i ++ ) {
  318. var falseLiteral = ctx.FalseLiteral[ i ];
  319. if ( falseLiteral.image === 'FALSE' ) field.values.push( false );
  320. }
  321. }
  322. if ( ctx.NullLiteral ) {
  323. field.type = 'null';
  324. ctx.NullLiteral.forEach( function () {
  325. field.values.push( null );
  326. } );
  327. }
  328. return field;
  329. }
  330. return new VRMLToASTVisitor();
  331. }
  332. function parseTree( tree ) {
  333. // console.log( JSON.stringify( tree, null, 2 ) );
  334. var nodes = tree.nodes;
  335. var scene = new Scene();
  336. // first iteration: build nodemap based on DEF statements
  337. for ( var i = 0, l = nodes.length; i < l; i ++ ) {
  338. var node = nodes[ i ];
  339. buildNodeMap( node );
  340. }
  341. // second iteration: build nodes
  342. for ( var i = 0, l = nodes.length; i < l; i ++ ) {
  343. var node = nodes[ i ];
  344. var object = getNode( node );
  345. if ( object instanceof Object3D ) scene.add( object );
  346. }
  347. return scene;
  348. }
  349. function buildNodeMap( node ) {
  350. if ( node.DEF ) {
  351. nodeMap[ node.DEF ] = node;
  352. }
  353. var fields = node.fields;
  354. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  355. var field = fields[ i ];
  356. if ( field.type === 'node' ) {
  357. var fieldValues = field.values;
  358. for ( var j = 0, jl = fieldValues.length; j < jl; j ++ ) {
  359. buildNodeMap( fieldValues[ j ] );
  360. }
  361. }
  362. }
  363. }
  364. function getNode( node ) {
  365. // handle case where a node refers to a different one
  366. if ( node.USE ) {
  367. return resolveUSE( node.USE );
  368. }
  369. if ( node.build !== undefined ) return node.build;
  370. node.build = buildNode( node );
  371. return node.build;
  372. }
  373. // node builder
  374. function buildNode( node ) {
  375. var nodeName = node.name;
  376. var build;
  377. switch ( nodeName ) {
  378. case 'Group':
  379. case 'Transform':
  380. build = buildGroupingNode( node );
  381. break;
  382. case 'Background':
  383. build = buildBackgroundNode( node );
  384. break;
  385. case 'Shape':
  386. build = buildShapeNode( node );
  387. break;
  388. case 'Appearance':
  389. build = buildAppearanceNode( node );
  390. break;
  391. case 'Material':
  392. build = buildMaterialNode( node );
  393. break;
  394. case 'ImageTexture':
  395. build = buildImageTextureNode( node );
  396. break;
  397. case 'PixelTexture':
  398. build = buildPixelTextureNode( node );
  399. break;
  400. case 'TextureTransform':
  401. build = buildTextureTransformNode( node );
  402. break;
  403. case 'IndexedFaceSet':
  404. build = buildIndexedFaceSetNode( node );
  405. break;
  406. case 'IndexedLineSet':
  407. build = buildIndexedLineSetNode( node );
  408. break;
  409. case 'PointSet':
  410. build = buildPointSetNode( node );
  411. break;
  412. case 'Box':
  413. build = buildBoxNode( node );
  414. break;
  415. case 'Cone':
  416. build = buildConeNode( node );
  417. break;
  418. case 'Cylinder':
  419. build = buildCylinderNode( node );
  420. break;
  421. case 'Sphere':
  422. build = buildSphereNode( node );
  423. break;
  424. case 'ElevationGrid':
  425. build = buildElevationGridNode( node );
  426. break;
  427. case 'Color':
  428. case 'Coordinate':
  429. case 'Normal':
  430. case 'TextureCoordinate':
  431. build = buildGeometricNode( node );
  432. break;
  433. case 'Anchor':
  434. case 'Billboard':
  435. case 'Collision':
  436. case 'Inline':
  437. case 'LOD':
  438. case 'Switch':
  439. case 'AudioClip':
  440. case 'DirectionalLight':
  441. case 'PointLight':
  442. case 'Script':
  443. case 'Sound':
  444. case 'SpotLight':
  445. case 'WorldInfo':
  446. case 'CylinderSensor':
  447. case 'PlaneSensor':
  448. case 'ProximitySensor':
  449. case 'SphereSensor':
  450. case 'TimeSensor':
  451. case 'TouchSensor':
  452. case 'VisibilitySensor':
  453. case 'Extrusion':
  454. case 'Text':
  455. case 'FontStyle':
  456. case 'MovieTexture':
  457. case 'ColorInterpolator':
  458. case 'CoordinateInterpolator':
  459. case 'NormalInterpolator':
  460. case 'OrientationInterpolator':
  461. case 'PositionInterpolator':
  462. case 'ScalarInterpolator':
  463. case 'Fog':
  464. case 'NavigationInfo':
  465. case 'Viewpoint':
  466. // node not supported yet
  467. break;
  468. default:
  469. console.warn( 'THREE.VRMLLoader: Unknown node:', nodeName );
  470. break;
  471. }
  472. return build;
  473. }
  474. function buildGroupingNode( node ) {
  475. var object = new Group();
  476. //
  477. var fields = node.fields;
  478. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  479. var field = fields[ i ];
  480. var fieldName = field.name;
  481. var fieldValues = field.values;
  482. switch ( fieldName ) {
  483. case 'center':
  484. // field not supported
  485. break;
  486. case 'children':
  487. parseFieldChildren( fieldValues, object );
  488. break;
  489. case 'rotation':
  490. var axis = new Vector3( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] );
  491. var angle = fieldValues[ 3 ];
  492. object.quaternion.setFromAxisAngle( axis, angle );
  493. break;
  494. case 'scale':
  495. object.scale.set( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] );
  496. break;
  497. case 'scaleOrientation':
  498. // field not supported
  499. break;
  500. case 'translation':
  501. object.position.set( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] );
  502. break;
  503. case 'bboxCenter':
  504. // field not supported
  505. break;
  506. case 'bboxSize':
  507. // field not supported
  508. break;
  509. default:
  510. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  511. break;
  512. }
  513. }
  514. return object;
  515. }
  516. function buildBackgroundNode( node ) {
  517. var group = new Group();
  518. var groundAngle, groundColor;
  519. var skyAngle, skyColor;
  520. var fields = node.fields;
  521. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  522. var field = fields[ i ];
  523. var fieldName = field.name;
  524. var fieldValues = field.values;
  525. switch ( fieldName ) {
  526. case 'groundAngle':
  527. groundAngle = fieldValues;
  528. break;
  529. case 'groundColor':
  530. groundColor = fieldValues;
  531. break;
  532. case 'backUrl':
  533. // field not supported
  534. break;
  535. case 'bottomUrl':
  536. // field not supported
  537. break;
  538. case 'frontUrl':
  539. // field not supported
  540. break;
  541. case 'leftUrl':
  542. // field not supported
  543. break;
  544. case 'rightUrl':
  545. // field not supported
  546. break;
  547. case 'topUrl':
  548. // field not supported
  549. break;
  550. case 'skyAngle':
  551. skyAngle = fieldValues;
  552. break;
  553. case 'skyColor':
  554. skyColor = fieldValues;
  555. break;
  556. default:
  557. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  558. break;
  559. }
  560. }
  561. var radius = 10000;
  562. // sky
  563. if ( skyColor ) {
  564. var skyGeometry = new SphereBufferGeometry( radius, 32, 16 );
  565. var skyMaterial = new MeshBasicMaterial( { fog: false, side: BackSide, depthWrite: false, depthTest: false } );
  566. if ( skyColor.length > 3 ) {
  567. paintFaces( skyGeometry, radius, skyAngle, toColorArray( skyColor ), true );
  568. skyMaterial.vertexColors = true;
  569. } else {
  570. skyMaterial.color.setRGB( skyColor[ 0 ], skyColor[ 1 ], skyColor[ 2 ] );
  571. }
  572. var sky = new Mesh( skyGeometry, skyMaterial );
  573. group.add( sky );
  574. }
  575. // ground
  576. if ( groundColor ) {
  577. if ( groundColor.length > 0 ) {
  578. var groundGeometry = new SphereBufferGeometry( radius, 32, 16, 0, 2 * Math.PI, 0.5 * Math.PI, 1.5 * Math.PI );
  579. var groundMaterial = new MeshBasicMaterial( { fog: false, side: BackSide, vertexColors: true, depthWrite: false, depthTest: false } );
  580. paintFaces( groundGeometry, radius, groundAngle, toColorArray( groundColor ), false );
  581. var ground = new Mesh( groundGeometry, groundMaterial );
  582. group.add( ground );
  583. }
  584. }
  585. // render background group first
  586. group.renderOrder = - Infinity;
  587. return group;
  588. }
  589. function buildShapeNode( node ) {
  590. var fields = node.fields;
  591. // if the appearance field is NULL or unspecified, lighting is off and the unlit object color is (0, 0, 0)
  592. var material = new MeshBasicMaterial( { color: 0x000000 } );
  593. var geometry;
  594. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  595. var field = fields[ i ];
  596. var fieldName = field.name;
  597. var fieldValues = field.values;
  598. switch ( fieldName ) {
  599. case 'appearance':
  600. if ( fieldValues[ 0 ] !== null ) {
  601. material = getNode( fieldValues[ 0 ] );
  602. }
  603. break;
  604. case 'geometry':
  605. if ( fieldValues[ 0 ] !== null ) {
  606. geometry = getNode( fieldValues[ 0 ] );
  607. }
  608. break;
  609. default:
  610. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  611. break;
  612. }
  613. }
  614. // build 3D object
  615. var object;
  616. if ( geometry && geometry.attributes.position ) {
  617. var type = geometry._type;
  618. if ( type === 'points' ) { // points
  619. var pointsMaterial = new PointsMaterial( { color: 0xffffff } );
  620. if ( geometry.attributes.color !== undefined ) {
  621. pointsMaterial.vertexColors = true;
  622. } else {
  623. // if the color field is NULL and there is a material defined for the appearance affecting this PointSet, then use the emissiveColor of the material to draw the points
  624. if ( material.isMeshPhongMaterial ) {
  625. pointsMaterial.color.copy( material.emissive );
  626. }
  627. }
  628. object = new Points( geometry, pointsMaterial );
  629. } else if ( type === 'line' ) { // lines
  630. var lineMaterial = new LineBasicMaterial( { color: 0xffffff } );
  631. if ( geometry.attributes.color !== undefined ) {
  632. lineMaterial.vertexColors = true;
  633. } else {
  634. // if the color field is NULL and there is a material defined for the appearance affecting this IndexedLineSet, then use the emissiveColor of the material to draw the lines
  635. if ( material.isMeshPhongMaterial ) {
  636. lineMaterial.color.copy( material.emissive );
  637. }
  638. }
  639. object = new LineSegments( geometry, lineMaterial );
  640. } else { // consider meshes
  641. // check "solid" hint (it's placed in the geometry but affects the material)
  642. if ( geometry._solid !== undefined ) {
  643. material.side = ( geometry._solid ) ? FrontSide : DoubleSide;
  644. }
  645. // check for vertex colors
  646. if ( geometry.attributes.color !== undefined ) {
  647. material.vertexColors = true;
  648. }
  649. object = new Mesh( geometry, material );
  650. }
  651. } else {
  652. object = new Object3D();
  653. // if the geometry field is NULL or no vertices are defined the object is not drawn
  654. object.visible = false;
  655. }
  656. return object;
  657. }
  658. function buildAppearanceNode( node ) {
  659. var material = new MeshPhongMaterial();
  660. var transformData;
  661. var fields = node.fields;
  662. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  663. var field = fields[ i ];
  664. var fieldName = field.name;
  665. var fieldValues = field.values;
  666. switch ( fieldName ) {
  667. case 'material':
  668. if ( fieldValues[ 0 ] !== null ) {
  669. var materialData = getNode( fieldValues[ 0 ] );
  670. if ( materialData.diffuseColor ) material.color.copy( materialData.diffuseColor );
  671. if ( materialData.emissiveColor ) material.emissive.copy( materialData.emissiveColor );
  672. if ( materialData.shininess ) material.shininess = materialData.shininess;
  673. if ( materialData.specularColor ) material.specular.copy( materialData.specularColor );
  674. if ( materialData.transparency ) material.opacity = 1 - materialData.transparency;
  675. if ( materialData.transparency > 0 ) material.transparent = true;
  676. } else {
  677. // if the material field is NULL or unspecified, lighting is off and the unlit object color is (0, 0, 0)
  678. material = new MeshBasicMaterial( { color: 0x000000 } );
  679. }
  680. break;
  681. case 'texture':
  682. var textureNode = fieldValues[ 0 ];
  683. if ( textureNode !== null ) {
  684. if ( textureNode.name === 'ImageTexture' || textureNode.name === 'PixelTexture' ) {
  685. material.map = getNode( textureNode );
  686. } else {
  687. // MovieTexture not supported yet
  688. }
  689. }
  690. break;
  691. case 'textureTransform':
  692. if ( fieldValues[ 0 ] !== null ) {
  693. transformData = getNode( fieldValues[ 0 ] );
  694. }
  695. break;
  696. default:
  697. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  698. break;
  699. }
  700. }
  701. // only apply texture transform data if a texture was defined
  702. if ( material.map ) {
  703. // respect VRML lighting model
  704. if ( material.map.__type ) {
  705. switch ( material.map.__type ) {
  706. case TEXTURE_TYPE.INTENSITY_ALPHA:
  707. material.opacity = 1; // ignore transparency
  708. break;
  709. case TEXTURE_TYPE.RGB:
  710. material.color.set( 0xffffff ); // ignore material color
  711. break;
  712. case TEXTURE_TYPE.RGBA:
  713. material.color.set( 0xffffff ); // ignore material color
  714. material.opacity = 1; // ignore transparency
  715. break;
  716. default:
  717. }
  718. delete material.map.__type;
  719. }
  720. // apply texture transform
  721. if ( transformData ) {
  722. material.map.center.copy( transformData.center );
  723. material.map.rotation = transformData.rotation;
  724. material.map.repeat.copy( transformData.scale );
  725. material.map.offset.copy( transformData.translation );
  726. }
  727. }
  728. return material;
  729. }
  730. function buildMaterialNode( node ) {
  731. var materialData = {};
  732. var fields = node.fields;
  733. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  734. var field = fields[ i ];
  735. var fieldName = field.name;
  736. var fieldValues = field.values;
  737. switch ( fieldName ) {
  738. case 'ambientIntensity':
  739. // field not supported
  740. break;
  741. case 'diffuseColor':
  742. materialData.diffuseColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] );
  743. break;
  744. case 'emissiveColor':
  745. materialData.emissiveColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] );
  746. break;
  747. case 'shininess':
  748. materialData.shininess = fieldValues[ 0 ];
  749. break;
  750. case 'specularColor':
  751. materialData.emissiveColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] );
  752. break;
  753. case 'transparency':
  754. materialData.transparency = fieldValues[ 0 ];
  755. break;
  756. default:
  757. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  758. break;
  759. }
  760. }
  761. return materialData;
  762. }
  763. function parseHexColor( hex, textureType, color ) {
  764. switch ( textureType ) {
  765. case TEXTURE_TYPE.INTENSITY:
  766. // Intensity texture: A one-component image specifies one-byte hexadecimal or integer values representing the intensity of the image
  767. var value = parseInt( hex );
  768. color.r = value;
  769. color.g = value;
  770. color.b = value;
  771. break;
  772. case TEXTURE_TYPE.INTENSITY_ALPHA:
  773. // Intensity+Alpha texture: A two-component image specifies the intensity in the first (high) byte and the alpha opacity in the second (low) byte.
  774. var value = parseInt( "0x" + hex.substring( 2, 4 ) );
  775. color.r = value;
  776. color.g = value;
  777. color.b = value;
  778. color.a = parseInt( "0x" + hex.substring( 4, 6 ) );
  779. break;
  780. case TEXTURE_TYPE.RGB:
  781. // RGB texture: Pixels in a three-component image specify the red component in the first (high) byte, followed by the green and blue components
  782. color.r = parseInt( "0x" + hex.substring( 2, 4 ) );
  783. color.g = parseInt( "0x" + hex.substring( 4, 6 ) );
  784. color.b = parseInt( "0x" + hex.substring( 6, 8 ) );
  785. break;
  786. case TEXTURE_TYPE.RGBA:
  787. // RGBA texture: Four-component images specify the alpha opacity byte after red/green/blue
  788. color.r = parseInt( "0x" + hex.substring( 2, 4 ) );
  789. color.g = parseInt( "0x" + hex.substring( 4, 6 ) );
  790. color.b = parseInt( "0x" + hex.substring( 6, 8 ) );
  791. color.a = parseInt( "0x" + hex.substring( 8, 10 ) );
  792. break;
  793. default:
  794. }
  795. }
  796. function getTextureType( num_components ) {
  797. var type;
  798. switch ( num_components ) {
  799. case 1:
  800. type = TEXTURE_TYPE.INTENSITY;
  801. break;
  802. case 2:
  803. type = TEXTURE_TYPE.INTENSITY_ALPHA;
  804. break;
  805. case 3:
  806. type = TEXTURE_TYPE.RGB;
  807. break;
  808. case 4:
  809. type = TEXTURE_TYPE.RGBA;
  810. break;
  811. default:
  812. }
  813. return type;
  814. }
  815. function buildPixelTextureNode( node ) {
  816. var texture;
  817. var wrapS = RepeatWrapping;
  818. var wrapT = RepeatWrapping;
  819. var fields = node.fields;
  820. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  821. var field = fields[ i ];
  822. var fieldName = field.name;
  823. var fieldValues = field.values;
  824. switch ( fieldName ) {
  825. case 'image':
  826. var width = fieldValues[ 0 ];
  827. var height = fieldValues[ 1 ];
  828. var num_components = fieldValues[ 2 ];
  829. var useAlpha = ( num_components === 2 || num_components === 4 );
  830. var textureType = getTextureType( num_components );
  831. var size = ( ( useAlpha === true ) ? 4 : 3 ) * ( width * height );
  832. var data = new Uint8Array( size );
  833. var color = { r: 0, g: 0, b: 0, a: 0 };
  834. for ( var j = 3, k = 0, jl = fieldValues.length; j < jl; j ++, k ++ ) {
  835. parseHexColor( fieldValues[ j ], textureType, color );
  836. if ( useAlpha === true ) {
  837. var stride = k * 4;
  838. data[ stride + 0 ] = color.r;
  839. data[ stride + 1 ] = color.g;
  840. data[ stride + 2 ] = color.b;
  841. data[ stride + 3 ] = color.a;
  842. } else {
  843. var stride = k * 3;
  844. data[ stride + 0 ] = color.r;
  845. data[ stride + 1 ] = color.g;
  846. data[ stride + 2 ] = color.b;
  847. }
  848. }
  849. texture = new DataTexture( data, width, height, ( useAlpha === true ) ? RGBAFormat : RGBFormat );
  850. texture.__type = textureType; // needed for material modifications
  851. break;
  852. case 'repeatS':
  853. if ( fieldValues[ 0 ] === false ) wrapS = ClampToEdgeWrapping;
  854. break;
  855. case 'repeatT':
  856. if ( fieldValues[ 0 ] === false ) wrapT = ClampToEdgeWrapping;
  857. break;
  858. default:
  859. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  860. break;
  861. }
  862. }
  863. if ( texture ) {
  864. texture.wrapS = wrapS;
  865. texture.wrapT = wrapT;
  866. }
  867. return texture;
  868. }
  869. function buildImageTextureNode( node ) {
  870. var texture;
  871. var wrapS = RepeatWrapping;
  872. var wrapT = RepeatWrapping;
  873. var fields = node.fields;
  874. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  875. var field = fields[ i ];
  876. var fieldName = field.name;
  877. var fieldValues = field.values;
  878. switch ( fieldName ) {
  879. case 'url':
  880. var url = fieldValues[ 0 ];
  881. if ( url ) texture = textureLoader.load( url );
  882. break;
  883. case 'repeatS':
  884. if ( fieldValues[ 0 ] === false ) wrapS = ClampToEdgeWrapping;
  885. break;
  886. case 'repeatT':
  887. if ( fieldValues[ 0 ] === false ) wrapT = ClampToEdgeWrapping;
  888. break;
  889. default:
  890. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  891. break;
  892. }
  893. }
  894. if ( texture ) {
  895. texture.wrapS = wrapS;
  896. texture.wrapT = wrapT;
  897. }
  898. return texture;
  899. }
  900. function buildTextureTransformNode( node ) {
  901. var transformData = {
  902. center: new Vector2(),
  903. rotation: new Vector2(),
  904. scale: new Vector2(),
  905. translation: new Vector2()
  906. };
  907. var fields = node.fields;
  908. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  909. var field = fields[ i ];
  910. var fieldName = field.name;
  911. var fieldValues = field.values;
  912. switch ( fieldName ) {
  913. case 'center':
  914. transformData.center.set( fieldValues[ 0 ], fieldValues[ 1 ] );
  915. break;
  916. case 'rotation':
  917. transformData.rotation = fieldValues[ 0 ];
  918. break;
  919. case 'scale':
  920. transformData.scale.set( fieldValues[ 0 ], fieldValues[ 1 ] );
  921. break;
  922. case 'translation':
  923. transformData.translation.set( fieldValues[ 0 ], fieldValues[ 1 ] );
  924. break;
  925. default:
  926. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  927. break;
  928. }
  929. }
  930. return transformData;
  931. }
  932. function buildGeometricNode( node ) {
  933. return node.fields[ 0 ].values;
  934. }
  935. function buildIndexedFaceSetNode( node ) {
  936. var color, coord, normal, texCoord;
  937. var ccw = true, solid = true, creaseAngle = 0;
  938. var colorIndex, coordIndex, normalIndex, texCoordIndex;
  939. var colorPerVertex = true, normalPerVertex = true;
  940. var fields = node.fields;
  941. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  942. var field = fields[ i ];
  943. var fieldName = field.name;
  944. var fieldValues = field.values;
  945. switch ( fieldName ) {
  946. case 'color':
  947. var colorNode = fieldValues[ 0 ];
  948. if ( colorNode !== null ) {
  949. color = getNode( colorNode );
  950. }
  951. break;
  952. case 'coord':
  953. var coordNode = fieldValues[ 0 ];
  954. if ( coordNode !== null ) {
  955. coord = getNode( coordNode );
  956. }
  957. break;
  958. case 'normal':
  959. var normalNode = fieldValues[ 0 ];
  960. if ( normalNode !== null ) {
  961. normal = getNode( normalNode );
  962. }
  963. break;
  964. case 'texCoord':
  965. var texCoordNode = fieldValues[ 0 ];
  966. if ( texCoordNode !== null ) {
  967. texCoord = getNode( texCoordNode );
  968. }
  969. break;
  970. case 'ccw':
  971. ccw = fieldValues[ 0 ];
  972. break;
  973. case 'colorIndex':
  974. colorIndex = fieldValues;
  975. break;
  976. case 'colorPerVertex':
  977. colorPerVertex = fieldValues[ 0 ];
  978. break;
  979. case 'convex':
  980. // field not supported
  981. break;
  982. case 'coordIndex':
  983. coordIndex = fieldValues;
  984. break;
  985. case 'creaseAngle':
  986. creaseAngle = fieldValues[ 0 ];
  987. break;
  988. case 'normalIndex':
  989. normalIndex = fieldValues;
  990. break;
  991. case 'normalPerVertex':
  992. normalPerVertex = fieldValues[ 0 ];
  993. break;
  994. case 'solid':
  995. solid = fieldValues[ 0 ];
  996. break;
  997. case 'texCoordIndex':
  998. texCoordIndex = fieldValues;
  999. break;
  1000. default:
  1001. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  1002. break;
  1003. }
  1004. }
  1005. if ( coordIndex === undefined ) {
  1006. console.warn( 'THREE.VRMLLoader: Missing coordIndex.' );
  1007. return new BufferGeometry(); // handle VRML files with incomplete geometry definition
  1008. }
  1009. var triangulatedCoordIndex = triangulateFaceIndex( coordIndex, ccw );
  1010. var positionAttribute;
  1011. var colorAttribute;
  1012. var normalAttribute;
  1013. var uvAttribute;
  1014. if ( color ) {
  1015. if ( colorPerVertex === true ) {
  1016. if ( colorIndex && colorIndex.length > 0 ) {
  1017. // if the colorIndex field is not empty, then it is used to choose colors for each vertex of the IndexedFaceSet.
  1018. var triangulatedColorIndex = triangulateFaceIndex( colorIndex, ccw );
  1019. colorAttribute = computeAttributeFromIndexedData( triangulatedCoordIndex, triangulatedColorIndex, color, 3 );
  1020. } else {
  1021. // if the colorIndex field is empty, then the coordIndex field is used to choose colors from the Color node
  1022. colorAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( color, 3 ) );
  1023. }
  1024. } else {
  1025. if ( colorIndex && colorIndex.length > 0 ) {
  1026. // if the colorIndex field is not empty, then they are used to choose one color for each face of the IndexedFaceSet
  1027. var flattenFaceColors = flattenData( color, colorIndex );
  1028. var triangulatedFaceColors = triangulateFaceData( flattenFaceColors, coordIndex );
  1029. colorAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceColors );
  1030. } else {
  1031. // if the colorIndex field is empty, then the color are applied to each face of the IndexedFaceSet in order
  1032. var triangulatedFaceColors = triangulateFaceData( color, coordIndex );
  1033. colorAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceColors );
  1034. }
  1035. }
  1036. }
  1037. if ( normal ) {
  1038. if ( normalPerVertex === true ) {
  1039. // consider vertex normals
  1040. if ( normalIndex && normalIndex.length > 0 ) {
  1041. // if the normalIndex field is not empty, then it is used to choose normals for each vertex of the IndexedFaceSet.
  1042. var triangulatedNormalIndex = triangulateFaceIndex( normalIndex, ccw );
  1043. normalAttribute = computeAttributeFromIndexedData( triangulatedCoordIndex, triangulatedNormalIndex, normal, 3 );
  1044. } else {
  1045. // if the normalIndex field is empty, then the coordIndex field is used to choose normals from the Normal node
  1046. normalAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( normal, 3 ) );
  1047. }
  1048. } else {
  1049. // consider face normals
  1050. if ( normalIndex && normalIndex.length > 0 ) {
  1051. // if the normalIndex field is not empty, then they are used to choose one normal for each face of the IndexedFaceSet
  1052. var flattenFaceNormals = flattenData( normal, normalIndex );
  1053. var triangulatedFaceNormals = triangulateFaceData( flattenFaceNormals, coordIndex );
  1054. normalAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceNormals );
  1055. } else {
  1056. // if the normalIndex field is empty, then the normals are applied to each face of the IndexedFaceSet in order
  1057. var triangulatedFaceNormals = triangulateFaceData( normal, coordIndex );
  1058. normalAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceNormals );
  1059. }
  1060. }
  1061. } else {
  1062. // if the normal field is NULL, then the loader should automatically generate normals, using creaseAngle to determine if and how normals are smoothed across shared vertices
  1063. normalAttribute = computeNormalAttribute( triangulatedCoordIndex, coord, creaseAngle );
  1064. }
  1065. if ( texCoord ) {
  1066. // texture coordinates are always defined on vertex level
  1067. if ( texCoordIndex && texCoordIndex.length > 0 ) {
  1068. // if the texCoordIndex field is not empty, then it is used to choose texture coordinates for each vertex of the IndexedFaceSet.
  1069. var triangulatedTexCoordIndex = triangulateFaceIndex( texCoordIndex, ccw );
  1070. uvAttribute = computeAttributeFromIndexedData( triangulatedCoordIndex, triangulatedTexCoordIndex, texCoord, 2 );
  1071. } else {
  1072. // if the texCoordIndex field is empty, then the coordIndex array is used to choose texture coordinates from the TextureCoordinate node
  1073. uvAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( texCoord, 2 ) );
  1074. }
  1075. }
  1076. var geometry = new BufferGeometry();
  1077. positionAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( coord, 3 ) );
  1078. geometry.setAttribute( 'position', positionAttribute );
  1079. geometry.setAttribute( 'normal', normalAttribute );
  1080. // optional attributes
  1081. if ( colorAttribute ) geometry.setAttribute( 'color', colorAttribute );
  1082. if ( uvAttribute ) geometry.setAttribute( 'uv', uvAttribute );
  1083. // "solid" influences the material so let's store it for later use
  1084. geometry._solid = solid;
  1085. geometry._type = 'mesh';
  1086. return geometry;
  1087. }
  1088. function buildIndexedLineSetNode( node ) {
  1089. var color, coord;
  1090. var colorIndex, coordIndex;
  1091. var colorPerVertex = true;
  1092. var fields = node.fields;
  1093. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  1094. var field = fields[ i ];
  1095. var fieldName = field.name;
  1096. var fieldValues = field.values;
  1097. switch ( fieldName ) {
  1098. case 'color':
  1099. var colorNode = fieldValues[ 0 ];
  1100. if ( colorNode !== null ) {
  1101. color = getNode( colorNode );
  1102. }
  1103. break;
  1104. case 'coord':
  1105. var coordNode = fieldValues[ 0 ];
  1106. if ( coordNode !== null ) {
  1107. coord = getNode( coordNode );
  1108. }
  1109. break;
  1110. case 'colorIndex':
  1111. colorIndex = fieldValues;
  1112. break;
  1113. case 'colorPerVertex':
  1114. colorPerVertex = fieldValues[ 0 ];
  1115. break;
  1116. case 'coordIndex':
  1117. coordIndex = fieldValues;
  1118. break;
  1119. default:
  1120. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  1121. break;
  1122. }
  1123. }
  1124. // build lines
  1125. var colorAttribute;
  1126. var expandedLineIndex = expandLineIndex( coordIndex ); // create an index for three.js's linesegment primitive
  1127. if ( color ) {
  1128. if ( colorPerVertex === true ) {
  1129. if ( colorIndex.length > 0 ) {
  1130. // if the colorIndex field is not empty, then one color is used for each polyline of the IndexedLineSet.
  1131. var expandedColorIndex = expandLineIndex( colorIndex ); // compute colors for each line segment (rendering primitve)
  1132. colorAttribute = computeAttributeFromIndexedData( expandedLineIndex, expandedColorIndex, color, 3 ); // compute data on vertex level
  1133. } else {
  1134. // if the colorIndex field is empty, then the colors are applied to each polyline of the IndexedLineSet in order.
  1135. colorAttribute = toNonIndexedAttribute( expandedLineIndex, new Float32BufferAttribute( color, 3 ) );
  1136. }
  1137. } else {
  1138. if ( colorIndex.length > 0 ) {
  1139. // if the colorIndex field is not empty, then colors are applied to each vertex of the IndexedLineSet
  1140. var flattenLineColors = flattenData( color, colorIndex ); // compute colors for each VRML primitve
  1141. var expandedLineColors = expandLineData( flattenLineColors, coordIndex ); // compute colors for each line segment (rendering primitve)
  1142. colorAttribute = computeAttributeFromLineData( expandedLineIndex, expandedLineColors ); // compute data on vertex level
  1143. } else {
  1144. // if the colorIndex field is empty, then the coordIndex field is used to choose colors from the Color node
  1145. var expandedLineColors = expandLineData( color, coordIndex ); // compute colors for each line segment (rendering primitve)
  1146. colorAttribute = computeAttributeFromLineData( expandedLineIndex, expandedLineColors ); // compute data on vertex level
  1147. }
  1148. }
  1149. }
  1150. //
  1151. var geometry = new BufferGeometry();
  1152. var positionAttribute = toNonIndexedAttribute( expandedLineIndex, new Float32BufferAttribute( coord, 3 ) );
  1153. geometry.setAttribute( 'position', positionAttribute );
  1154. if ( colorAttribute ) geometry.setAttribute( 'color', colorAttribute );
  1155. geometry._type = 'line';
  1156. return geometry;
  1157. }
  1158. function buildPointSetNode( node ) {
  1159. var geometry;
  1160. var color, coord;
  1161. var fields = node.fields;
  1162. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  1163. var field = fields[ i ];
  1164. var fieldName = field.name;
  1165. var fieldValues = field.values;
  1166. switch ( fieldName ) {
  1167. case 'color':
  1168. var colorNode = fieldValues[ 0 ];
  1169. if ( colorNode !== null ) {
  1170. color = getNode( colorNode );
  1171. }
  1172. break;
  1173. case 'coord':
  1174. var coordNode = fieldValues[ 0 ];
  1175. if ( coordNode !== null ) {
  1176. coord = getNode( coordNode );
  1177. }
  1178. break;
  1179. default:
  1180. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  1181. break;
  1182. }
  1183. }
  1184. var geometry = new BufferGeometry();
  1185. geometry.setAttribute( 'position', new Float32BufferAttribute( coord, 3 ) );
  1186. if ( color ) geometry.setAttribute( 'color', new Float32BufferAttribute( color, 3 ) );
  1187. geometry._type = 'points';
  1188. return geometry;
  1189. }
  1190. function buildBoxNode( node ) {
  1191. var size = new Vector3( 2, 2, 2 );
  1192. var fields = node.fields;
  1193. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  1194. var field = fields[ i ];
  1195. var fieldName = field.name;
  1196. var fieldValues = field.values;
  1197. switch ( fieldName ) {
  1198. case 'size':
  1199. size.x = fieldValues[ 0 ];
  1200. size.y = fieldValues[ 1 ];
  1201. size.z = fieldValues[ 2 ];
  1202. break;
  1203. default:
  1204. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  1205. break;
  1206. }
  1207. }
  1208. var geometry = new BoxBufferGeometry( size.x, size.y, size.z );
  1209. return geometry;
  1210. }
  1211. function buildConeNode( node ) {
  1212. var radius = 1, height = 2, openEnded = false;
  1213. var fields = node.fields;
  1214. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  1215. var field = fields[ i ];
  1216. var fieldName = field.name;
  1217. var fieldValues = field.values;
  1218. switch ( fieldName ) {
  1219. case 'bottom':
  1220. openEnded = ! fieldValues[ 0 ];
  1221. break;
  1222. case 'bottomRadius':
  1223. radius = fieldValues[ 0 ];
  1224. break;
  1225. case 'height':
  1226. height = fieldValues[ 0 ];
  1227. break;
  1228. case 'side':
  1229. // field not supported
  1230. break;
  1231. default:
  1232. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  1233. break;
  1234. }
  1235. }
  1236. var geometry = new ConeBufferGeometry( radius, height, 16, 1, openEnded );
  1237. return geometry;
  1238. }
  1239. function buildCylinderNode( node ) {
  1240. var radius = 1, height = 2;
  1241. var fields = node.fields;
  1242. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  1243. var field = fields[ i ];
  1244. var fieldName = field.name;
  1245. var fieldValues = field.values;
  1246. switch ( fieldName ) {
  1247. case 'bottom':
  1248. // field not supported
  1249. break;
  1250. case 'radius':
  1251. radius = fieldValues[ 0 ];
  1252. break;
  1253. case 'height':
  1254. height = fieldValues[ 0 ];
  1255. break;
  1256. case 'side':
  1257. // field not supported
  1258. break;
  1259. case 'top':
  1260. // field not supported
  1261. break;
  1262. default:
  1263. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  1264. break;
  1265. }
  1266. }
  1267. var geometry = new CylinderBufferGeometry( radius, radius, height, 16, 1 );
  1268. return geometry;
  1269. }
  1270. function buildSphereNode( node ) {
  1271. var radius = 1;
  1272. var fields = node.fields;
  1273. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  1274. var field = fields[ i ];
  1275. var fieldName = field.name;
  1276. var fieldValues = field.values;
  1277. switch ( fieldName ) {
  1278. case 'radius':
  1279. radius = fieldValues[ 0 ];
  1280. break;
  1281. default:
  1282. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  1283. break;
  1284. }
  1285. }
  1286. var geometry = new SphereBufferGeometry( radius, 16, 16 );
  1287. return geometry;
  1288. }
  1289. function buildElevationGridNode( node ) {
  1290. var color;
  1291. var normal;
  1292. var texCoord;
  1293. var height;
  1294. var colorPerVertex = true;
  1295. var normalPerVertex = true;
  1296. var solid = true;
  1297. var ccw = true;
  1298. var creaseAngle = 0;
  1299. var xDimension = 2;
  1300. var zDimension = 2;
  1301. var xSpacing = 1;
  1302. var zSpacing = 1;
  1303. var fields = node.fields;
  1304. for ( var i = 0, l = fields.length; i < l; i ++ ) {
  1305. var field = fields[ i ];
  1306. var fieldName = field.name;
  1307. var fieldValues = field.values;
  1308. switch ( fieldName ) {
  1309. case 'color':
  1310. var colorNode = fieldValues[ 0 ];
  1311. if ( colorNode !== null ) {
  1312. color = getNode( colorNode );
  1313. }
  1314. break;
  1315. case 'normal':
  1316. var normalNode = fieldValues[ 0 ];
  1317. if ( normalNode !== null ) {
  1318. normal = getNode( normalNode );
  1319. }
  1320. break;
  1321. case 'texCoord':
  1322. var texCoordNode = fieldValues[ 0 ];
  1323. if ( texCoordNode !== null ) {
  1324. texCoord = getNode( texCoordNode );
  1325. }
  1326. break;
  1327. case 'height':
  1328. height = fieldValues;
  1329. break;
  1330. case 'ccw':
  1331. ccw = fieldValues[ 0 ];
  1332. break;
  1333. case 'colorPerVertex':
  1334. colorPerVertex = fieldValues[ 0 ];
  1335. break;
  1336. case 'creaseAngle':
  1337. creaseAngle = fieldValues[ 0 ];
  1338. break;
  1339. case 'normalPerVertex':
  1340. normalPerVertex = fieldValues[ 0 ];
  1341. break;
  1342. case 'solid':
  1343. solid = fieldValues[ 0 ];
  1344. break;
  1345. case 'xDimension':
  1346. xDimension = fieldValues[ 0 ];
  1347. break;
  1348. case 'xSpacing':
  1349. xSpacing = fieldValues[ 0 ];
  1350. break;
  1351. case 'zDimension':
  1352. zDimension = fieldValues[ 0 ];
  1353. break;
  1354. case 'zSpacing':
  1355. zSpacing = fieldValues[ 0 ];
  1356. break;
  1357. default:
  1358. console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
  1359. break;
  1360. }
  1361. }
  1362. // vertex data
  1363. var vertices = [];
  1364. var normals = [];
  1365. var colors = [];
  1366. var uvs = [];
  1367. for ( var i = 0; i < zDimension; i ++ ) {
  1368. for ( var j = 0; j < xDimension; j ++ ) {
  1369. // compute a row major index
  1370. var index = ( i * xDimension ) + j;
  1371. // vertices
  1372. var x = xSpacing * i;
  1373. var y = height[ index ];
  1374. var z = zSpacing * j;
  1375. vertices.push( x, y, z );
  1376. // colors
  1377. if ( color && colorPerVertex === true ) {
  1378. var r = color[ index * 3 + 0 ];
  1379. var g = color[ index * 3 + 1 ];
  1380. var b = color[ index * 3 + 2 ];
  1381. colors.push( r, g, b );
  1382. }
  1383. // normals
  1384. if ( normal && normalPerVertex === true ) {
  1385. var xn = normal[ index * 3 + 0 ];
  1386. var yn = normal[ index * 3 + 1 ];
  1387. var zn = normal[ index * 3 + 2 ];
  1388. normals.push( xn, yn, zn );
  1389. }
  1390. // uvs
  1391. if ( texCoord ) {
  1392. var s = texCoord[ index * 2 + 0 ];
  1393. var t = texCoord[ index * 2 + 1 ];
  1394. uvs.push( s, t );
  1395. } else {
  1396. uvs.push( i / ( xDimension - 1 ), j / ( zDimension - 1 ) );
  1397. }
  1398. }
  1399. }
  1400. // indices
  1401. var indices = [];
  1402. for ( var i = 0; i < xDimension - 1; i ++ ) {
  1403. for ( var j = 0; j < zDimension - 1; j ++ ) {
  1404. // from https://tecfa.unige.ch/guides/vrml/vrml97/spec/part1/nodesRef.html#ElevationGrid
  1405. var a = i + j * xDimension;
  1406. var b = i + ( j + 1 ) * xDimension;
  1407. var c = ( i + 1 ) + ( j + 1 ) * xDimension;
  1408. var d = ( i + 1 ) + j * xDimension;
  1409. // faces
  1410. if ( ccw === true ) {
  1411. indices.push( a, c, b );
  1412. indices.push( c, a, d );
  1413. } else {
  1414. indices.push( a, b, c );
  1415. indices.push( c, d, a );
  1416. }
  1417. }
  1418. }
  1419. //
  1420. var positionAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( vertices, 3 ) );
  1421. var uvAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( uvs, 2 ) );
  1422. var colorAttribute;
  1423. var normalAttribute;
  1424. // color attribute
  1425. if ( color ) {
  1426. if ( colorPerVertex === false ) {
  1427. for ( var i = 0; i < xDimension - 1; i ++ ) {
  1428. for ( var j = 0; j < zDimension - 1; j ++ ) {
  1429. var index = i + j * ( xDimension - 1 );
  1430. var r = color[ index * 3 + 0 ];
  1431. var g = color[ index * 3 + 1 ];
  1432. var b = color[ index * 3 + 2 ];
  1433. // one color per quad
  1434. colors.push( r, g, b ); colors.push( r, g, b ); colors.push( r, g, b );
  1435. colors.push( r, g, b ); colors.push( r, g, b ); colors.push( r, g, b );
  1436. }
  1437. }
  1438. colorAttribute = new Float32BufferAttribute( colors, 3 );
  1439. } else {
  1440. colorAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( colors, 3 ) );
  1441. }
  1442. }
  1443. // normal attribute
  1444. if ( normal ) {
  1445. if ( normalPerVertex === false ) {
  1446. for ( var i = 0; i < xDimension - 1; i ++ ) {
  1447. for ( var j = 0; j < zDimension - 1; j ++ ) {
  1448. var index = i + j * ( xDimension - 1 );
  1449. var xn = normal[ index * 3 + 0 ];
  1450. var yn = normal[ index * 3 + 1 ];
  1451. var zn = normal[ index * 3 + 2 ];
  1452. // one normal per quad
  1453. normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); normals.push( xn, yn, zn );
  1454. normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); normals.push( xn, yn, zn );
  1455. }
  1456. }
  1457. normalAttribute = new Float32BufferAttribute( normals, 3 );
  1458. } else {
  1459. normalAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( normals, 3 ) );
  1460. }
  1461. } else {
  1462. normalAttribute = computeNormalAttribute( indices, vertices, creaseAngle );
  1463. }
  1464. // build geometry
  1465. var geometry = new BufferGeometry();
  1466. geometry.setAttribute( 'position', positionAttribute );
  1467. geometry.setAttribute( 'normal', normalAttribute );
  1468. geometry.setAttribute( 'uv', uvAttribute );
  1469. if ( colorAttribute ) geometry.setAttribute( 'color', colorAttribute );
  1470. // "solid" influences the material so let's store it for later use
  1471. geometry._solid = solid;
  1472. geometry._type = 'mesh';
  1473. return geometry;
  1474. }
  1475. // helper functions
  1476. function resolveUSE( identifier ) {
  1477. var node = nodeMap[ identifier ];
  1478. var build = getNode( node );
  1479. // because the same 3D objects can have different transformations, it's necessary to clone them.
  1480. // materials can be influenced by the geometry (e.g. vertex normals). cloning is necessary to avoid
  1481. // any side effects
  1482. return ( build.isObject3D || build.isMaterial ) ? build.clone() : build;
  1483. }
  1484. function parseFieldChildren( children, owner ) {
  1485. for ( var i = 0, l = children.length; i < l; i ++ ) {
  1486. var object = getNode( children[ i ] );
  1487. if ( object instanceof Object3D ) owner.add( object );
  1488. }
  1489. }
  1490. function triangulateFaceIndex( index, ccw ) {
  1491. var indices = [];
  1492. // since face defintions can have more than three vertices, it's necessary to
  1493. // perform a simple triangulation
  1494. var start = 0;
  1495. for ( var i = 0, l = index.length; i < l; i ++ ) {
  1496. var i1 = index[ start ];
  1497. var i2 = index[ i + ( ccw ? 1 : 2 ) ];
  1498. var i3 = index[ i + ( ccw ? 2 : 1 ) ];
  1499. indices.push( i1, i2, i3 );
  1500. // an index of -1 indicates that the current face has ended and the next one begins
  1501. if ( index[ i + 3 ] === - 1 || i + 3 >= l ) {
  1502. i += 3;
  1503. start = i + 1;
  1504. }
  1505. }
  1506. return indices;
  1507. }
  1508. function triangulateFaceData( data, index ) {
  1509. var triangulatedData = [];
  1510. var start = 0;
  1511. for ( var i = 0, l = index.length; i < l; i ++ ) {
  1512. var stride = start * 3;
  1513. var x = data[ stride ];
  1514. var y = data[ stride + 1 ];
  1515. var z = data[ stride + 2 ];
  1516. triangulatedData.push( x, y, z );
  1517. // an index of -1 indicates that the current face has ended and the next one begins
  1518. if ( index[ i + 3 ] === - 1 || i + 3 >= l ) {
  1519. i += 3;
  1520. start ++;
  1521. }
  1522. }
  1523. return triangulatedData;
  1524. }
  1525. function flattenData( data, index ) {
  1526. var flattenData = [];
  1527. for ( var i = 0, l = index.length; i < l; i ++ ) {
  1528. var i1 = index[ i ];
  1529. var stride = i1 * 3;
  1530. var x = data[ stride ];
  1531. var y = data[ stride + 1 ];
  1532. var z = data[ stride + 2 ];
  1533. flattenData.push( x, y, z );
  1534. }
  1535. return flattenData;
  1536. }
  1537. function expandLineIndex( index ) {
  1538. var indices = [];
  1539. for ( var i = 0, l = index.length; i < l; i ++ ) {
  1540. var i1 = index[ i ];
  1541. var i2 = index[ i + 1 ];
  1542. indices.push( i1, i2 );
  1543. // an index of -1 indicates that the current line has ended and the next one begins
  1544. if ( index[ i + 2 ] === - 1 || i + 2 >= l ) {
  1545. i += 2;
  1546. }
  1547. }
  1548. return indices;
  1549. }
  1550. function expandLineData( data, index ) {
  1551. var triangulatedData = [];
  1552. var start = 0;
  1553. for ( var i = 0, l = index.length; i < l; i ++ ) {
  1554. var stride = start * 3;
  1555. var x = data[ stride ];
  1556. var y = data[ stride + 1 ];
  1557. var z = data[ stride + 2 ];
  1558. triangulatedData.push( x, y, z );
  1559. // an index of -1 indicates that the current line has ended and the next one begins
  1560. if ( index[ i + 2 ] === - 1 || i + 2 >= l ) {
  1561. i += 2;
  1562. start ++;
  1563. }
  1564. }
  1565. return triangulatedData;
  1566. }
  1567. var vA = new Vector3();
  1568. var vB = new Vector3();
  1569. var vC = new Vector3();
  1570. var uvA = new Vector2();
  1571. var uvB = new Vector2();
  1572. var uvC = new Vector2();
  1573. function computeAttributeFromIndexedData( coordIndex, index, data, itemSize ) {
  1574. var array = [];
  1575. // we use the coordIndex.length as delimiter since normalIndex must contain at least as many indices
  1576. for ( var i = 0, l = coordIndex.length; i < l; i += 3 ) {
  1577. var a = index[ i ];
  1578. var b = index[ i + 1 ];
  1579. var c = index[ i + 2 ];
  1580. if ( itemSize === 2 ) {
  1581. uvA.fromArray( data, a * itemSize );
  1582. uvB.fromArray( data, b * itemSize );
  1583. uvC.fromArray( data, c * itemSize );
  1584. array.push( uvA.x, uvA.y );
  1585. array.push( uvB.x, uvB.y );
  1586. array.push( uvC.x, uvC.y );
  1587. } else {
  1588. vA.fromArray( data, a * itemSize );
  1589. vB.fromArray( data, b * itemSize );
  1590. vC.fromArray( data, c * itemSize );
  1591. array.push( vA.x, vA.y, vA.z );
  1592. array.push( vB.x, vB.y, vB.z );
  1593. array.push( vC.x, vC.y, vC.z );
  1594. }
  1595. }
  1596. return new Float32BufferAttribute( array, itemSize );
  1597. }
  1598. function computeAttributeFromFaceData( index, faceData ) {
  1599. var array = [];
  1600. for ( var i = 0, j = 0, l = index.length; i < l; i += 3, j ++ ) {
  1601. vA.fromArray( faceData, j * 3 );
  1602. array.push( vA.x, vA.y, vA.z );
  1603. array.push( vA.x, vA.y, vA.z );
  1604. array.push( vA.x, vA.y, vA.z );
  1605. }
  1606. return new Float32BufferAttribute( array, 3 );
  1607. }
  1608. function computeAttributeFromLineData( index, lineData ) {
  1609. var array = [];
  1610. for ( var i = 0, j = 0, l = index.length; i < l; i += 2, j ++ ) {
  1611. vA.fromArray( lineData, j * 3 );
  1612. array.push( vA.x, vA.y, vA.z );
  1613. array.push( vA.x, vA.y, vA.z );
  1614. }
  1615. return new Float32BufferAttribute( array, 3 );
  1616. }
  1617. function toNonIndexedAttribute( indices, attribute ) {
  1618. var array = attribute.array;
  1619. var itemSize = attribute.itemSize;
  1620. var array2 = new array.constructor( indices.length * itemSize );
  1621. var index = 0, index2 = 0;
  1622. for ( var i = 0, l = indices.length; i < l; i ++ ) {
  1623. index = indices[ i ] * itemSize;
  1624. for ( var j = 0; j < itemSize; j ++ ) {
  1625. array2[ index2 ++ ] = array[ index ++ ];
  1626. }
  1627. }
  1628. return new Float32BufferAttribute( array2, itemSize );
  1629. }
  1630. var ab = new Vector3();
  1631. var cb = new Vector3();
  1632. function computeNormalAttribute( index, coord, creaseAngle ) {
  1633. var faces = [];
  1634. var vertexNormals = {};
  1635. // prepare face and raw vertex normals
  1636. for ( var i = 0, l = index.length; i < l; i += 3 ) {
  1637. var a = index[ i ];
  1638. var b = index[ i + 1 ];
  1639. var c = index[ i + 2 ];
  1640. var face = new Face( a, b, c );
  1641. vA.fromArray( coord, a * 3 );
  1642. vB.fromArray( coord, b * 3 );
  1643. vC.fromArray( coord, c * 3 );
  1644. cb.subVectors( vC, vB );
  1645. ab.subVectors( vA, vB );
  1646. cb.cross( ab );
  1647. cb.normalize();
  1648. face.normal.copy( cb );
  1649. if ( vertexNormals[ a ] === undefined ) vertexNormals[ a ] = [];
  1650. if ( vertexNormals[ b ] === undefined ) vertexNormals[ b ] = [];
  1651. if ( vertexNormals[ c ] === undefined ) vertexNormals[ c ] = [];
  1652. vertexNormals[ a ].push( face.normal );
  1653. vertexNormals[ b ].push( face.normal );
  1654. vertexNormals[ c ].push( face.normal );
  1655. faces.push( face );
  1656. }
  1657. // compute vertex normals and build final geometry
  1658. var normals = [];
  1659. for ( var i = 0, l = faces.length; i < l; i ++ ) {
  1660. var face = faces[ i ];
  1661. var nA = weightedNormal( vertexNormals[ face.a ], face.normal, creaseAngle );
  1662. var nB = weightedNormal( vertexNormals[ face.b ], face.normal, creaseAngle );
  1663. var nC = weightedNormal( vertexNormals[ face.c ], face.normal, creaseAngle );
  1664. vA.fromArray( coord, face.a * 3 );
  1665. vB.fromArray( coord, face.b * 3 );
  1666. vC.fromArray( coord, face.c * 3 );
  1667. normals.push( nA.x, nA.y, nA.z );
  1668. normals.push( nB.x, nB.y, nB.z );
  1669. normals.push( nC.x, nC.y, nC.z );
  1670. }
  1671. return new Float32BufferAttribute( normals, 3 );
  1672. }
  1673. function weightedNormal( normals, vector, creaseAngle ) {
  1674. var normal = new Vector3();
  1675. if ( creaseAngle === 0 ) {
  1676. normal.copy( vector );
  1677. } else {
  1678. for ( var i = 0, l = normals.length; i < l; i ++ ) {
  1679. if ( normals[ i ].angleTo( vector ) < creaseAngle ) {
  1680. normal.add( normals[ i ] );
  1681. }
  1682. }
  1683. }
  1684. return normal.normalize();
  1685. }
  1686. function toColorArray( colors ) {
  1687. var array = [];
  1688. for ( var i = 0, l = colors.length; i < l; i += 3 ) {
  1689. array.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) );
  1690. }
  1691. return array;
  1692. }
  1693. /**
  1694. * Vertically paints the faces interpolating between the
  1695. * specified colors at the specified angels. This is used for the Background
  1696. * node, but could be applied to other nodes with multiple faces as well.
  1697. *
  1698. * When used with the Background node, default is directionIsDown is true if
  1699. * interpolating the skyColor down from the Zenith. When interpolationg up from
  1700. * the Nadir i.e. interpolating the groundColor, the directionIsDown is false.
  1701. *
  1702. * The first angle is never specified, it is the Zenith (0 rad). Angles are specified
  1703. * in radians. The geometry is thought a sphere, but could be anything. The color interpolation
  1704. * is linear along the Y axis in any case.
  1705. *
  1706. * You must specify one more color than you have angles at the beginning of the colors array.
  1707. * This is the color of the Zenith (the top of the shape).
  1708. *
  1709. * @param {BufferGeometry} geometry
  1710. * @param {number} radius
  1711. * @param {array} angles
  1712. * @param {array} colors
  1713. * @param {boolean} topDown - Whether to work top down or bottom up.
  1714. */
  1715. function paintFaces( geometry, radius, angles, colors, topDown ) {
  1716. // compute threshold values
  1717. var thresholds = [];
  1718. var startAngle = ( topDown === true ) ? 0 : Math.PI;
  1719. for ( var i = 0, l = colors.length; i < l; i ++ ) {
  1720. var angle = ( i === 0 ) ? 0 : angles[ i - 1 ];
  1721. angle = ( topDown === true ) ? angle : ( startAngle - angle );
  1722. var point = new Vector3();
  1723. point.setFromSphericalCoords( radius, angle, 0 );
  1724. thresholds.push( point );
  1725. }
  1726. // generate vertex colors
  1727. var indices = geometry.index;
  1728. var positionAttribute = geometry.attributes.position;
  1729. var colorAttribute = new BufferAttribute( new Float32Array( geometry.attributes.position.count * 3 ), 3 );
  1730. var position = new Vector3();
  1731. var color = new Color();
  1732. for ( var i = 0; i < indices.count; i ++ ) {
  1733. var index = indices.getX( i );
  1734. position.fromBufferAttribute( positionAttribute, index );
  1735. var thresholdIndexA, thresholdIndexB;
  1736. var t = 1;
  1737. for ( var j = 1; j < thresholds.length; j ++ ) {
  1738. thresholdIndexA = j - 1;
  1739. thresholdIndexB = j;
  1740. var thresholdA = thresholds[ thresholdIndexA ];
  1741. var thresholdB = thresholds[ thresholdIndexB ];
  1742. if ( topDown === true ) {
  1743. // interpolation for sky color
  1744. if ( position.y <= thresholdA.y && position.y > thresholdB.y ) {
  1745. t = Math.abs( thresholdA.y - position.y ) / Math.abs( thresholdA.y - thresholdB.y );
  1746. break;
  1747. }
  1748. } else {
  1749. // interpolation for ground color
  1750. if ( position.y >= thresholdA.y && position.y < thresholdB.y ) {
  1751. t = Math.abs( thresholdA.y - position.y ) / Math.abs( thresholdA.y - thresholdB.y );
  1752. break;
  1753. }
  1754. }
  1755. }
  1756. var colorA = colors[ thresholdIndexA ];
  1757. var colorB = colors[ thresholdIndexB ];
  1758. color.copy( colorA ).lerp( colorB, t );
  1759. colorAttribute.setXYZ( index, color.r, color.g, color.b );
  1760. }
  1761. geometry.setAttribute( 'color', colorAttribute );
  1762. }
  1763. //
  1764. var textureLoader = new TextureLoader( this.manager );
  1765. textureLoader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );
  1766. // create JSON representing the tree structure of the VRML asset
  1767. var tree = generateVRMLTree( data );
  1768. // check version (only 2.0 is supported)
  1769. if ( tree.version.indexOf( 'V2.0' ) === - 1 ) {
  1770. throw Error( 'THREE.VRMLLexer: Version of VRML asset not supported.' );
  1771. }
  1772. // parse the tree structure to a three.js scene
  1773. var scene = parseTree( tree );
  1774. return scene;
  1775. }
  1776. } );
  1777. function VRMLLexer( tokens ) {
  1778. this.lexer = new chevrotain.Lexer( tokens );
  1779. }
  1780. VRMLLexer.prototype = {
  1781. constructor: VRMLLexer,
  1782. lex: function ( inputText ) {
  1783. var lexingResult = this.lexer.tokenize( inputText );
  1784. if ( lexingResult.errors.length > 0 ) {
  1785. console.error( lexingResult.errors );
  1786. throw Error( 'THREE.VRMLLexer: Lexing errors detected.' );
  1787. }
  1788. return lexingResult;
  1789. }
  1790. };
  1791. function VRMLParser( tokenVocabulary ) {
  1792. chevrotain.Parser.call( this, tokenVocabulary );
  1793. var $ = this;
  1794. var Version = tokenVocabulary[ 'Version' ];
  1795. var LCurly = tokenVocabulary[ 'LCurly' ];
  1796. var RCurly = tokenVocabulary[ 'RCurly' ];
  1797. var LSquare = tokenVocabulary[ 'LSquare' ];
  1798. var RSquare = tokenVocabulary[ 'RSquare' ];
  1799. var Identifier = tokenVocabulary[ 'Identifier' ];
  1800. var RouteIdentifier = tokenVocabulary[ 'RouteIdentifier' ];
  1801. var StringLiteral = tokenVocabulary[ 'StringLiteral' ];
  1802. var HexLiteral = tokenVocabulary[ 'HexLiteral' ];
  1803. var NumberLiteral = tokenVocabulary[ 'NumberLiteral' ];
  1804. var TrueLiteral = tokenVocabulary[ 'TrueLiteral' ];
  1805. var FalseLiteral = tokenVocabulary[ 'FalseLiteral' ];
  1806. var NullLiteral = tokenVocabulary[ 'NullLiteral' ];
  1807. var DEF = tokenVocabulary[ 'DEF' ];
  1808. var USE = tokenVocabulary[ 'USE' ];
  1809. var ROUTE = tokenVocabulary[ 'ROUTE' ];
  1810. var TO = tokenVocabulary[ 'TO' ];
  1811. var NodeName = tokenVocabulary[ 'NodeName' ];
  1812. $.RULE( 'vrml', function () {
  1813. $.SUBRULE( $.version );
  1814. $.AT_LEAST_ONE( function () {
  1815. $.SUBRULE( $.node );
  1816. } );
  1817. $.MANY( function () {
  1818. $.SUBRULE( $.route );
  1819. } );
  1820. } );
  1821. $.RULE( 'version', function () {
  1822. $.CONSUME( Version );
  1823. } );
  1824. $.RULE( 'node', function () {
  1825. $.OPTION( function () {
  1826. $.SUBRULE( $.def );
  1827. } );
  1828. $.CONSUME( NodeName );
  1829. $.CONSUME( LCurly );
  1830. $.MANY( function () {
  1831. $.SUBRULE( $.field );
  1832. } );
  1833. $.CONSUME( RCurly );
  1834. } );
  1835. $.RULE( 'field', function () {
  1836. $.CONSUME( Identifier );
  1837. $.OR2( [
  1838. { ALT: function () {
  1839. $.SUBRULE( $.singleFieldValue );
  1840. } },
  1841. { ALT: function () {
  1842. $.SUBRULE( $.multiFieldValue );
  1843. } }
  1844. ] );
  1845. } );
  1846. $.RULE( 'def', function () {
  1847. $.CONSUME( DEF );
  1848. $.CONSUME( Identifier );
  1849. } );
  1850. $.RULE( 'use', function () {
  1851. $.CONSUME( USE );
  1852. $.CONSUME( Identifier );
  1853. } );
  1854. $.RULE( 'singleFieldValue', function () {
  1855. $.AT_LEAST_ONE( function () {
  1856. $.OR( [
  1857. { ALT: function () {
  1858. $.SUBRULE( $.node );
  1859. } },
  1860. { ALT: function () {
  1861. $.SUBRULE( $.use );
  1862. } },
  1863. { ALT: function () {
  1864. $.CONSUME( StringLiteral );
  1865. } },
  1866. { ALT: function () {
  1867. $.CONSUME( HexLiteral );
  1868. } },
  1869. { ALT: function () {
  1870. $.CONSUME( NumberLiteral );
  1871. } },
  1872. { ALT: function () {
  1873. $.CONSUME( TrueLiteral );
  1874. } },
  1875. { ALT: function () {
  1876. $.CONSUME( FalseLiteral );
  1877. } },
  1878. { ALT: function () {
  1879. $.CONSUME( NullLiteral );
  1880. } }
  1881. ] );
  1882. } );
  1883. } );
  1884. $.RULE( 'multiFieldValue', function () {
  1885. $.CONSUME( LSquare );
  1886. $.MANY( function () {
  1887. $.OR( [
  1888. { ALT: function () {
  1889. $.SUBRULE( $.node );
  1890. } },
  1891. { ALT: function () {
  1892. $.SUBRULE( $.use );
  1893. } },
  1894. { ALT: function () {
  1895. $.CONSUME( StringLiteral );
  1896. } },
  1897. { ALT: function () {
  1898. $.CONSUME( HexLiteral );
  1899. } },
  1900. { ALT: function () {
  1901. $.CONSUME( NumberLiteral );
  1902. } },
  1903. { ALT: function () {
  1904. $.CONSUME( NullLiteral );
  1905. } }
  1906. ] );
  1907. } );
  1908. $.CONSUME( RSquare );
  1909. } );
  1910. $.RULE( 'route', function () {
  1911. $.CONSUME( ROUTE );
  1912. $.CONSUME( RouteIdentifier );
  1913. $.CONSUME( TO );
  1914. $.CONSUME2( RouteIdentifier );
  1915. } );
  1916. this.performSelfAnalysis();
  1917. }
  1918. VRMLParser.prototype = Object.create( chevrotain.Parser.prototype );
  1919. VRMLParser.prototype.constructor = VRMLParser;
  1920. function Face( a, b, c ) {
  1921. this.a = a;
  1922. this.b = b;
  1923. this.c = c;
  1924. this.normal = new Vector3();
  1925. }
  1926. var TEXTURE_TYPE = {
  1927. INTENSITY: 1,
  1928. INTENSITY_ALPHA: 2,
  1929. RGB: 3,
  1930. RGBA: 4
  1931. };
  1932. return VRMLLoader;
  1933. } )();
  1934. export { VRMLLoader };