PageRenderTime 75ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/Game/Src/ColladaMeshFormat/ColladaMeshFormatLoader.cs

https://bitbucket.org/drjedd/krill
C# | 3578 lines | 2797 code | 634 blank | 147 comment | 483 complexity | b9461053347adf456fb7fc9c081bed39 MD5 | raw file
  1. // Copyright (C) 2006-2011 NeoAxis Group Ltd.
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Runtime.InteropServices;
  5. using System.IO;
  6. using Engine;
  7. using Engine.FileSystem;
  8. using Engine.Renderer;
  9. using Engine.MathEx;
  10. using Engine.Utils;
  11. using GAPLA_COMMON;
  12. using System.Xml;
  13. using GeneralMeshUtils;
  14. namespace ColladaMeshFormat
  15. {
  16. [CustomMeshFormatLoaderExtensions( new string[] { "dae" } )]
  17. public class ColladaMeshFormatLoader : CustomMeshFormatLoader
  18. {
  19. string currentFileName;
  20. Mesh currentMesh;
  21. float globalScale = 1;
  22. bool yAxisUp = true;
  23. ColladaExportingTools colladaExportingTool = ColladaExportingTools.Unknown;
  24. //parsed material info
  25. Dictionary<string, string> generatedEffects;//<effectId, materialId>
  26. Dictionary<string, string> generatedBindedMaterials;//<materialId, originalMaterialName>
  27. Dictionary<string, MySceneMaterial> generatedMaterials;//<material name, material>
  28. Dictionary<string, string> generatedImages;//<imageId, textureFilePath>
  29. Dictionary<string, GeometryItem> generatedGeometries;
  30. List<MySceneSubMesh> generatedSubMeshes;
  31. /////////////////////////////////////////////////////////////////////////////////////////////
  32. class MySceneMaterial : ISceneMaterial
  33. {
  34. string name;
  35. ColorValue diffuseColor = new ColorValue( 1, 1, 1 );
  36. string diffuse1Map = "";
  37. string diffuse2Map = "";
  38. string diffuse3Map = "";
  39. string diffuse4Map = "";
  40. string diffuse1TexCoord = "";
  41. string diffuse2TexCoord = "";
  42. string diffuse3TexCoord = "";
  43. string diffuse4TexCoord = "";
  44. string diffuse2MapBlending = "";
  45. string diffuse3MapBlending = "";
  46. string diffuse4MapBlending = "";
  47. string specularMap = "";
  48. string specularTexCoord;
  49. ColorValue specularColor;
  50. string emissionMap = "";
  51. string emissionTexCoord;
  52. ColorValue emissionColor;
  53. float shininess;
  54. float transparency;
  55. ColorValue transparentColor;
  56. bool opaque;
  57. bool culling = true;
  58. //
  59. public MySceneMaterial( string name )
  60. {
  61. this.name = name;
  62. }
  63. public string Name
  64. {
  65. get { return name; }
  66. set { name = value; }
  67. }
  68. public ColorValue DiffuseColor
  69. {
  70. get { return diffuseColor; }
  71. set { diffuseColor = value; }
  72. }
  73. public string Diffuse1Map
  74. {
  75. get { return diffuse1Map; }
  76. set { diffuse1Map = value; }
  77. }
  78. public string Diffuse2Map
  79. {
  80. get { return diffuse2Map; }
  81. set { diffuse2Map = value; }
  82. }
  83. public string Diffuse3Map
  84. {
  85. get { return diffuse3Map; }
  86. set { diffuse3Map = value; }
  87. }
  88. public string Diffuse4Map
  89. {
  90. get { return diffuse4Map; }
  91. set { diffuse4Map = value; }
  92. }
  93. public string Diffuse1TexCoord
  94. {
  95. get { return diffuse1TexCoord; }
  96. set { diffuse1TexCoord = value; }
  97. }
  98. public string Diffuse2TexCoord
  99. {
  100. get { return diffuse2TexCoord; }
  101. set { diffuse2TexCoord = value; }
  102. }
  103. public string Diffuse3TexCoord
  104. {
  105. get { return diffuse3TexCoord; }
  106. set { diffuse3TexCoord = value; }
  107. }
  108. public string Diffuse4TexCoord
  109. {
  110. get { return diffuse4TexCoord; }
  111. set { diffuse4TexCoord = value; }
  112. }
  113. public string Diffuse2MapBlending
  114. {
  115. get { return diffuse2MapBlending; }
  116. set { diffuse2MapBlending = value; }
  117. }
  118. public string Diffuse3MapBlending
  119. {
  120. get { return diffuse3MapBlending; }
  121. set { diffuse3MapBlending = value; }
  122. }
  123. public string Diffuse4MapBlending
  124. {
  125. get { return diffuse4MapBlending; }
  126. set { diffuse4MapBlending = value; }
  127. }
  128. public float Transparency
  129. {
  130. get { return transparency; }
  131. set { transparency = value; }
  132. }
  133. public ColorValue TransparentColor
  134. {
  135. get { return transparentColor; }
  136. set { transparentColor = value; }
  137. }
  138. public bool Opaque
  139. {
  140. get { return opaque; }
  141. set { opaque = value; }
  142. }
  143. public float GetAlpha()
  144. {
  145. if( opaque )
  146. return transparency;
  147. if( transparentColor.Red > 0 || transparentColor.Green > 0 || transparentColor.Blue > 0 )
  148. return 1.0f - transparency;
  149. return 1;
  150. }
  151. public string SpecularMap
  152. {
  153. get { return specularMap; }
  154. set { specularMap = value; }
  155. }
  156. public string SpecularTexCoord
  157. {
  158. get { return specularTexCoord; }
  159. set { specularTexCoord = value; }
  160. }
  161. public ColorValue SpecularColor
  162. {
  163. get { return specularColor; }
  164. set { specularColor = value; }
  165. }
  166. public float Shininess
  167. {
  168. get { return shininess; }
  169. set { shininess = value; }
  170. }
  171. public string EmissionMap
  172. {
  173. get { return emissionMap; }
  174. set { emissionMap = value; }
  175. }
  176. public string EmissionTexCoord
  177. {
  178. get { return emissionTexCoord; }
  179. set { emissionTexCoord = value; }
  180. }
  181. public ColorValue EmissionColor
  182. {
  183. get { return emissionColor; }
  184. set { emissionColor = value; }
  185. }
  186. public bool Culling
  187. {
  188. get { return culling; }
  189. set { culling = value; }
  190. }
  191. }
  192. /////////////////////////////////////////////////////////////////////////////////////////////
  193. class GeometryItem
  194. {
  195. string id;
  196. SubMesh[] subMeshes;
  197. //
  198. public class SubMesh
  199. {
  200. SubMeshVertex[] vertices;
  201. int[] indices;
  202. int textureCoordCount;
  203. bool vertexColors;
  204. MySceneMaterial material;
  205. //
  206. public SubMesh( SubMeshVertex[] vertices, int[] indices, int textureCoordCount,
  207. bool vertexColors, MySceneMaterial material )
  208. {
  209. this.vertices = vertices;
  210. this.indices = indices;
  211. this.textureCoordCount = textureCoordCount;
  212. this.vertexColors = vertexColors;
  213. this.material = material;
  214. }
  215. public SubMeshVertex[] Vertices
  216. {
  217. get { return vertices; }
  218. }
  219. public int[] Indices
  220. {
  221. get { return indices; }
  222. }
  223. public int TextureCoordCount
  224. {
  225. get { return textureCoordCount; }
  226. }
  227. public bool VertexColors
  228. {
  229. get { return vertexColors; }
  230. }
  231. public MySceneMaterial Material
  232. {
  233. get { return material; }
  234. }
  235. }
  236. //
  237. public GeometryItem( string id, SubMesh[] subMeshes )
  238. {
  239. this.id = id;
  240. this.subMeshes = subMeshes;
  241. }
  242. public string Id
  243. {
  244. get { return id; }
  245. }
  246. public SubMesh[] SubMeshes
  247. {
  248. get { return subMeshes; }
  249. }
  250. }
  251. /////////////////////////////////////////////////////////////////////////////////////////////
  252. class MySceneSubMesh : ISceneSubMesh
  253. {
  254. SubMeshVertex[] vertices;
  255. int[] indices;
  256. int textureCoordCount;
  257. bool vertexColors;
  258. MySceneMaterial material;
  259. //
  260. public MySceneSubMesh( SubMeshVertex[] vertices, int[] indices, int textureCoordCount,
  261. bool vertexColors, MySceneMaterial material )
  262. {
  263. this.vertices = vertices;
  264. this.indices = indices;
  265. this.textureCoordCount = textureCoordCount;
  266. this.vertexColors = vertexColors;
  267. this.material = material;
  268. }
  269. public void GetGeometry( out SubMeshVertex[] vertices, out int[] indices )
  270. {
  271. vertices = this.vertices;
  272. indices = this.indices;
  273. }
  274. public int GetTextureCoordCount()
  275. {
  276. return textureCoordCount;
  277. }
  278. public bool VertexColors
  279. {
  280. get { return vertexColors; }
  281. }
  282. public ISceneMaterial Material
  283. {
  284. get { return material; }
  285. }
  286. public SceneBoneAssignmentItem[] GetVertexBoneAssignment( int vertexIndex )
  287. {
  288. return null;
  289. }
  290. public void GetVerticesByTime( float timeFrame, out Vec3[] vertices, bool skeletonOn )
  291. {
  292. vertices = null;
  293. skeletonOn = false;
  294. }
  295. public bool HasPoses()
  296. {
  297. return false;
  298. }
  299. public void GetPoses( out PoseInfo[] poses )
  300. {
  301. poses = null;
  302. }
  303. public void GetPoseReferenceByTime( float timeFrame, out PoseReference[] poseReferences )
  304. {
  305. poseReferences = null;
  306. }
  307. public bool AllowCollision
  308. {
  309. get { return true; }
  310. }
  311. public UVUnwrapChannels UVUnwrapChannel
  312. {
  313. get { return UVUnwrapChannels.None; }
  314. }
  315. public bool HasVertexColors()
  316. {
  317. return vertexColors;
  318. }
  319. }
  320. /////////////////////////////////////////////////////////////////////////////////////////////
  321. class MyMeshSceneObject : IMeshSceneObject
  322. {
  323. MySceneSubMesh[] subMeshes;
  324. //
  325. public MyMeshSceneObject( MySceneSubMesh[] subMeshes )
  326. {
  327. this.subMeshes = subMeshes;
  328. }
  329. public ISceneSubMesh[] SubMeshes
  330. {
  331. get { return subMeshes; }
  332. }
  333. public IList<ISceneBone> SkinBones
  334. {
  335. get
  336. {
  337. return new ISceneBone[ 0 ];
  338. }
  339. }
  340. public int AnimationFrameRate
  341. {
  342. get
  343. {
  344. return 0;
  345. }
  346. }
  347. public void GetBoundsByTime( float timeFrame, out Bounds bounds, out float radius )
  348. {
  349. Log.Fatal( "GetBoundsByTime" );
  350. bounds = Bounds.Cleared;
  351. radius = -1;
  352. }
  353. }
  354. /////////////////////////////////////////////////////////////////////////////////////////////
  355. class SourceItem
  356. {
  357. string id;
  358. float[] data;
  359. int offset;
  360. int stride;
  361. //
  362. public SourceItem( string id, float[] data, int offset, int stride )
  363. {
  364. this.id = id;
  365. this.data = data;
  366. this.offset = offset;
  367. this.stride = stride;
  368. }
  369. public string Id
  370. {
  371. get { return id; }
  372. }
  373. public float[] Data
  374. {
  375. get { return data; }
  376. }
  377. public int Offset
  378. {
  379. get { return offset; }
  380. }
  381. public int Stride
  382. {
  383. get { return stride; }
  384. }
  385. public Vec2 GetItemVec2( int index )
  386. {
  387. int index2 = offset + index * stride;
  388. return new Vec2(
  389. data[ index2 + 0 ],
  390. data[ index2 + 1 ] );
  391. }
  392. public Vec3 GetItemVec3( int index )
  393. {
  394. int index2 = offset + index * stride;
  395. return new Vec3(
  396. data[ index2 + 0 ],
  397. data[ index2 + 1 ],
  398. data[ index2 + 2 ] );
  399. }
  400. }
  401. /////////////////////////////////////////////////////////////////////////////////////////////
  402. enum ChannelTypes
  403. {
  404. Unknown,
  405. POSITION,
  406. NORMAL,
  407. COLOR,
  408. TEXCOORD0,
  409. TEXCOORD1,
  410. TEXCOORD2,
  411. TEXCOORD3,
  412. TANGENT,
  413. }
  414. /////////////////////////////////////////////////////////////////////////////////////////////
  415. enum ColladaExportingTools
  416. {
  417. Unknown,
  418. FBX,
  419. XSI,
  420. Blender,
  421. Unwrap3d,
  422. NeoAxis,
  423. }
  424. /////////////////////////////////////////////////////////////////////////////////////////////
  425. void Error( string format, params object[] args )
  426. {
  427. Log.Warning(
  428. string.Format( "ColladaMeshFormatLoader: Cannot load file \"{0}\". ", currentFileName ) +
  429. string.Format( format, args ) );
  430. }
  431. static float[] ConvertStringToFloatArray( string str )
  432. {
  433. if( string.IsNullOrEmpty( str ) )
  434. return new float[ 0 ];
  435. string fixedStr = str.Replace( ',', '.' );
  436. string[] strings = fixedStr.Split( new char[] { ' ', '\n', '\t', '\r' },
  437. StringSplitOptions.RemoveEmptyEntries );
  438. float[] array = new float[ strings.Length ];
  439. for( int n = 0; n < strings.Length; n++ )
  440. {
  441. float value;
  442. if( !float.TryParse( strings[ n ], out value ) )
  443. return null;
  444. array[ n ] = value;
  445. }
  446. return array;
  447. }
  448. static ColorValue ConvertStringToColorValue( string str )
  449. {
  450. if( string.IsNullOrEmpty( str ) )
  451. return new ColorValue();
  452. string fixedStr = str.Replace( ',', '.' );
  453. string[] strings = fixedStr.Split( new char[] { ' ', '\n', '\t', '\r' },
  454. StringSplitOptions.RemoveEmptyEntries );
  455. ColorValue color = new ColorValue();
  456. if( strings.Length >= 3 )
  457. {
  458. float red;
  459. if( !float.TryParse( strings[ 0 ], out red ) )
  460. return color;
  461. float green;
  462. if( !float.TryParse( strings[ 1 ], out green ) )
  463. return color;
  464. float blue;
  465. if( !float.TryParse( strings[ 2 ], out blue ) )
  466. return color;
  467. color.Red = red;
  468. color.Green = green;
  469. color.Blue = blue;
  470. if( strings.Length == 4 )
  471. {
  472. float alpha;
  473. if( !float.TryParse( strings[ 3 ], out alpha ) )
  474. return color;
  475. color.Alpha = alpha;
  476. }
  477. }
  478. return color;
  479. }
  480. static int[] ConvertStringToIntArray( string str )
  481. {
  482. if( string.IsNullOrEmpty( str ) )
  483. return new int[ 0 ];
  484. string fixedStr = str.Replace( ',', '.' );
  485. string[] strings = fixedStr.Split( new char[] { ' ', '\n', '\t', '\r' },
  486. StringSplitOptions.RemoveEmptyEntries );
  487. int[] array = new int[ strings.Length ];
  488. for( int n = 0; n < strings.Length; n++ )
  489. {
  490. int value;
  491. if( !int.TryParse( strings[ n ], out value ) )
  492. return null;
  493. array[ n ] = value;
  494. }
  495. return array;
  496. }
  497. static Vec2 ConvertColladaTexCoordToNeoAxisTexCoord( Vec2 colladaTexCoord )
  498. {
  499. return new Vec2( colladaTexCoord.X, 1 - colladaTexCoord.Y );
  500. }
  501. ColladaExportingTools GetColladaExportingTool( string authoringTool )
  502. {
  503. if( authoringTool.Contains( "FBX" ) )
  504. return ColladaExportingTools.FBX;
  505. if( authoringTool.Contains( "Softimage" ) )
  506. return ColladaExportingTools.XSI;
  507. if( authoringTool.Contains( "Blender" ) )
  508. return ColladaExportingTools.Blender;
  509. if( authoringTool.Contains( "Unwrap3D" ) )
  510. return ColladaExportingTools.Unwrap3d;
  511. if( authoringTool.Contains( "NeoAxis" ) )
  512. return ColladaExportingTools.NeoAxis;
  513. return ColladaExportingTools.Unknown;
  514. }
  515. string GetVirtualPath( string colladaFileDirectory, string path )
  516. {
  517. if( path.IndexOf( "file://" ) >= 0 )
  518. path = path.Remove( 0, 7 );
  519. if( path.Length > 0 && ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) )
  520. path = path.Remove( 0, 1 );
  521. if( Path.IsPathRooted( path ) )
  522. {
  523. string virtualPath = VirtualFileSystem.GetVirtualPathByReal( path );
  524. if( string.IsNullOrEmpty( virtualPath ) )
  525. virtualPath = Path.Combine( colladaFileDirectory, Path.GetFileName( path ) );
  526. return virtualPath;
  527. }
  528. else
  529. {
  530. if( path.Length > 1 && path[ 0 ] == '.' && ( path[ 1 ] == '/' || path[ 1 ] == '\\' ) )
  531. path = path.Remove( 0, 2 );
  532. return Path.Combine( colladaFileDirectory, path );
  533. }
  534. }
  535. ShaderBaseMaterial.DiffuseMapItem.MapBlendingTypes GetMapBlendingType( string blendingMode )
  536. {
  537. if( blendingMode == "ADD" )
  538. return ShaderBaseMaterial.DiffuseMapItem.MapBlendingTypes.Add;
  539. if( blendingMode == "BLEND" )
  540. return ShaderBaseMaterial.DiffuseMapItem.MapBlendingTypes.AlphaBlend;
  541. return ShaderBaseMaterial.DiffuseMapItem.MapBlendingTypes.Modulate;
  542. }
  543. ShaderBaseMaterial.TexCoordIndexes GetNeoAxisTexCoordByColladaTexCoord( string texCoord )
  544. {
  545. if( texCoord == "CHANNEL1" )
  546. return ShaderBaseMaterial.TexCoordIndexes.TexCoord1;
  547. if( texCoord == "CHANNEL2" )
  548. return ShaderBaseMaterial.TexCoordIndexes.TexCoord2;
  549. if( texCoord == "CHANNEL3" )
  550. return ShaderBaseMaterial.TexCoordIndexes.TexCoord3;
  551. return ShaderBaseMaterial.TexCoordIndexes.TexCoord0;
  552. }
  553. MySceneMaterial GetOrCreateMaterial( string materialName )
  554. {
  555. MySceneMaterial material;
  556. if( !generatedMaterials.TryGetValue( materialName, out material ) )
  557. {
  558. material = new MySceneMaterial( materialName );
  559. generatedMaterials.Add( material.Name, material );
  560. }
  561. return material;
  562. }
  563. bool ParseSource( XmlNode sourceNode, out SourceItem source )
  564. {
  565. source = null;
  566. string id = XmlUtils.GetAttribute( sourceNode, "id" );
  567. XmlNode floatArrayNode = XmlUtils.FindChildNode( sourceNode, "float_array" );
  568. if( floatArrayNode == null )
  569. {
  570. Error( "\"float_array\" node is not exists. Source: \"{0}\".", id );
  571. return false;
  572. }
  573. int floatsCount;
  574. if( !int.TryParse( XmlUtils.GetAttribute( floatArrayNode, "count" ), out floatsCount ) )
  575. {
  576. Error( "Invalid \"count\" attribute of floats array. Source: \"{0}\".", id );
  577. return false;
  578. }
  579. float[] data = ConvertStringToFloatArray( floatArrayNode.InnerText );
  580. if( data == null )
  581. {
  582. Error( "Cannot read array with name \"{0}\".", XmlUtils.GetAttribute( floatArrayNode, "id" ) );
  583. return false;
  584. }
  585. if( data.Length != floatsCount )
  586. {
  587. Error( "Invalid amount of items in \"float_array\". Required amount: \"{0}\". " +
  588. "Real amount: \"{1}\". Source: \"{2}\".", floatsCount, data.Length, id );
  589. return false;
  590. }
  591. XmlNode techniqueCommonNode = XmlUtils.FindChildNode( sourceNode, "technique_common" );
  592. if( techniqueCommonNode == null )
  593. {
  594. Error( "\"technique_common\" node is not exists. Source: \"{0}\".", id );
  595. return false;
  596. }
  597. XmlNode accessorNode = XmlUtils.FindChildNode( techniqueCommonNode, "accessor" );
  598. if( accessorNode == null )
  599. {
  600. Error( "\"accessor\" node is not exists. Source: \"{0}\".", id );
  601. return false;
  602. }
  603. int offset = 0;
  604. {
  605. string offsetAttribute = XmlUtils.GetAttribute( accessorNode, "offset" );
  606. if( !string.IsNullOrEmpty( offsetAttribute ) )
  607. {
  608. if( !int.TryParse( offsetAttribute, out offset ) )
  609. {
  610. Error( "Invalid \"offset\" attribute of accessor. Source: \"{0}\".", id );
  611. return false;
  612. }
  613. }
  614. }
  615. int stride = 1;
  616. {
  617. string strideAttribute = XmlUtils.GetAttribute( accessorNode, "stride" );
  618. if( !string.IsNullOrEmpty( strideAttribute ) )
  619. {
  620. if( !int.TryParse( strideAttribute, out stride ) )
  621. {
  622. Error( "Invalid \"stride\" attribute of accessor. Source: \"{0}\".", id );
  623. return false;
  624. }
  625. }
  626. }
  627. int count;
  628. if( !int.TryParse( XmlUtils.GetAttribute( accessorNode, "count" ), out count ) )
  629. {
  630. Error( "Invalid \"count\" attribute of accessor. Source: \"{0}\".", id );
  631. return false;
  632. }
  633. source = new SourceItem( id, data, offset, stride );
  634. return true;
  635. }
  636. bool ParseMeshSources( XmlNode meshNode, out List<SourceItem> sources )
  637. {
  638. sources = new List<SourceItem>();
  639. foreach( XmlNode childNode in meshNode.ChildNodes )
  640. {
  641. if( childNode.Name != "source" )
  642. continue;
  643. SourceItem source;
  644. if( !ParseSource( childNode, out source ) )
  645. return false;
  646. sources.Add( source );
  647. }
  648. return true;
  649. }
  650. string GetIdFromURL( string url )
  651. {
  652. if( string.IsNullOrEmpty( url ) )
  653. return "";
  654. if( url[ 0 ] != '#' )
  655. return "";
  656. return url.Substring( 1 );
  657. }
  658. bool ParseInputNode( string geometryId, Dictionary<string, string> vertexSemanticDictionary,
  659. XmlNode inputNode, out int offset, out string sourceId, out ChannelTypes channelType )
  660. {
  661. offset = 0;
  662. sourceId = null;
  663. channelType = ChannelTypes.Unknown;
  664. //offset
  665. if( !int.TryParse( XmlUtils.GetAttribute( inputNode, "offset" ), out offset ) )
  666. {
  667. Error( "Invalid \"offset\" attribute. Geometry: \"{0}\".", geometryId );
  668. return false;
  669. }
  670. string semantic = XmlUtils.GetAttribute( inputNode, "semantic" );
  671. //channelType
  672. {
  673. int set = 0;
  674. {
  675. string setAsString = XmlUtils.GetAttribute( inputNode, "set" );
  676. if( !string.IsNullOrEmpty( setAsString ) )
  677. {
  678. if( !int.TryParse( setAsString, out set ) )
  679. {
  680. Error( "Invalid \"set\" attribute. Geometry: \"{0}\".", geometryId );
  681. return false;
  682. }
  683. }
  684. }
  685. if( semantic == "VERTEX" )
  686. channelType = ChannelTypes.POSITION;
  687. else if( semantic == "POSITION" )
  688. channelType = ChannelTypes.POSITION;
  689. else if( semantic == "NORMAL" )
  690. channelType = ChannelTypes.NORMAL;
  691. else if( semantic == "COLOR" )
  692. channelType = ChannelTypes.COLOR;
  693. else if( semantic == "TEXCOORD" )
  694. {
  695. switch( set )
  696. {
  697. case 0: channelType = ChannelTypes.TEXCOORD0; break;
  698. case 1: channelType = ChannelTypes.TEXCOORD1; break;
  699. case 2: channelType = ChannelTypes.TEXCOORD2; break;
  700. case 3: channelType = ChannelTypes.TEXCOORD3; break;
  701. default: channelType = ChannelTypes.Unknown; break;
  702. }
  703. }
  704. else if( semantic == "TANGENT" )
  705. channelType = ChannelTypes.TANGENT;
  706. else
  707. {
  708. channelType = ChannelTypes.Unknown;
  709. }
  710. }
  711. //sourceId
  712. {
  713. string sourceUrl = XmlUtils.GetAttribute( inputNode, "source" );
  714. sourceId = GetIdFromURL( sourceUrl );
  715. if( string.IsNullOrEmpty( sourceId ) )
  716. {
  717. Error( "Invalid \"source\" attribute for input node. Source url: \"{0}\". Geometry: \"{1}\".",
  718. sourceUrl, geometryId );
  719. return false;
  720. }
  721. if( semantic == "VERTEX" )
  722. {
  723. string newSourceId;
  724. if( !vertexSemanticDictionary.TryGetValue( sourceId, out newSourceId ) )
  725. {
  726. Error( "Cannot find vertices node with \"{0}\". Geometry: \"{1}\".",
  727. sourceId, geometryId );
  728. return false;
  729. }
  730. sourceId = newSourceId;
  731. }
  732. }
  733. return true;
  734. }
  735. bool ParseInputs( string geometryId, Dictionary<string, SourceItem> sourceDictionary,
  736. Dictionary<string, string> vertexSemanticDictionary, XmlNode primitiveElementsNode,
  737. out Pair<ChannelTypes, SourceItem>[] inputs )
  738. {
  739. inputs = null;
  740. List<Pair<ChannelTypes, SourceItem>> inputList = new List<Pair<ChannelTypes, SourceItem>>();
  741. foreach( XmlNode inputNode in primitiveElementsNode.ChildNodes )
  742. {
  743. if( inputNode.Name != "input" )
  744. continue;
  745. int offset;
  746. string sourceId;
  747. ChannelTypes channelType;
  748. if( !ParseInputNode( geometryId, vertexSemanticDictionary, inputNode, out offset, out sourceId,
  749. out channelType ) )
  750. {
  751. return false;
  752. }
  753. while( inputList.Count < offset + 1 )
  754. inputList.Add( new Pair<ChannelTypes, SourceItem>( ChannelTypes.Unknown, null ) );
  755. if( channelType != ChannelTypes.Unknown )
  756. {
  757. if( inputList[ offset ].Second != null )
  758. {
  759. Error( "Input with offset \"{0}\" is already defined.", offset );
  760. return false;
  761. }
  762. SourceItem source;
  763. if( !sourceDictionary.TryGetValue( sourceId, out source ) )
  764. {
  765. Error( "Source with id \"{0}\" is not exists.", sourceId );
  766. return false;
  767. }
  768. inputList[ offset ] = new Pair<ChannelTypes, SourceItem>( channelType, source );
  769. }
  770. }
  771. inputs = inputList.ToArray();
  772. return true;
  773. }
  774. SubMeshVertex[] GenerateSubMeshVertices( Pair<ChannelTypes, SourceItem>[] inputs, int vertexCount,
  775. int[] indices, int startIndex )
  776. {
  777. SubMeshVertex[] itemVertices = new SubMeshVertex[ vertexCount ];
  778. int currentIndex = startIndex;
  779. for( int nVertex = 0; nVertex < itemVertices.Length; nVertex++ )
  780. {
  781. SubMeshVertex vertex = new SubMeshVertex();
  782. foreach( Pair<ChannelTypes, SourceItem> input in inputs )
  783. {
  784. ChannelTypes channelType = input.First;
  785. SourceItem source = input.Second;
  786. int indexValue = indices[ currentIndex ];
  787. currentIndex++;
  788. switch( channelType )
  789. {
  790. case ChannelTypes.POSITION:
  791. vertex.position = source.GetItemVec3( indexValue );
  792. break;
  793. case ChannelTypes.NORMAL:
  794. vertex.normal = source.GetItemVec3( indexValue );
  795. break;
  796. case ChannelTypes.TEXCOORD0:
  797. vertex.texCoord0 = ConvertColladaTexCoordToNeoAxisTexCoord(
  798. source.GetItemVec2( indexValue ) );
  799. break;
  800. case ChannelTypes.TEXCOORD1:
  801. vertex.texCoord1 = ConvertColladaTexCoordToNeoAxisTexCoord(
  802. source.GetItemVec2( indexValue ) );
  803. break;
  804. case ChannelTypes.TEXCOORD2:
  805. vertex.texCoord2 = ConvertColladaTexCoordToNeoAxisTexCoord(
  806. source.GetItemVec2( indexValue ) );
  807. break;
  808. case ChannelTypes.TEXCOORD3:
  809. vertex.texCoord3 = ConvertColladaTexCoordToNeoAxisTexCoord(
  810. source.GetItemVec2( indexValue ) );
  811. break;
  812. case ChannelTypes.COLOR:
  813. {
  814. Vec3 c = source.GetItemVec3( indexValue ); ;
  815. vertex.color = new ColorValue( c.X, c.Y, c.Z, 1 );
  816. }
  817. break;
  818. //maybe need use "TEXTANGENT".
  819. //case ChannelTypes.TANGENT:
  820. // vertex.tangent = source.GetItemVec3( indexValue );
  821. // break;
  822. }
  823. }
  824. itemVertices[ nVertex ] = vertex;
  825. }
  826. return itemVertices;
  827. }
  828. bool ParseMeshNode( string geometryId, XmlNode meshNode )
  829. {
  830. List<SourceItem> sources;
  831. if( !ParseMeshSources( meshNode, out sources ) )
  832. return false;
  833. Dictionary<string, SourceItem> sourceDictionary = new Dictionary<string, SourceItem>();
  834. foreach( SourceItem source in sources )
  835. sourceDictionary.Add( source.Id, source );
  836. //vertexSemanticDictionary
  837. Dictionary<string, string> vertexSemanticDictionary = new Dictionary<string, string>();
  838. {
  839. foreach( XmlNode verticesNode in meshNode.ChildNodes )
  840. {
  841. if( verticesNode.Name != "vertices" )
  842. continue;
  843. string id = XmlUtils.GetAttribute( verticesNode, "id" );
  844. XmlNode inputNode = XmlUtils.FindChildNode( verticesNode, "input" );
  845. if( inputNode == null )
  846. {
  847. Error( "\"input\" node is not defined for vertices node \"{0}\". Geometry: \"{1}\".",
  848. id, geometryId );
  849. return false;
  850. }
  851. string sourceUrl = XmlUtils.GetAttribute( inputNode, "source" );
  852. string sourceId = GetIdFromURL( sourceUrl );
  853. if( string.IsNullOrEmpty( sourceId ) )
  854. {
  855. Error( "Invalid \"source\" attribute for vertices node \"{0}\". Source url: \"{1}\". " +
  856. "Geometry: \"{2}\".", id, sourceUrl, geometryId );
  857. return false;
  858. }
  859. vertexSemanticDictionary.Add( id, sourceId );
  860. }
  861. }
  862. List<GeometryItem.SubMesh> geometrySubMeshes = new List<GeometryItem.SubMesh>();
  863. //polygons, triangles, ...
  864. foreach( XmlNode primitiveElementsNode in meshNode.ChildNodes )
  865. {
  866. bool lines = primitiveElementsNode.Name == "lines";
  867. bool linestrips = primitiveElementsNode.Name == "linestrips";
  868. bool polygons = primitiveElementsNode.Name == "polygons";
  869. bool polylist = primitiveElementsNode.Name == "polylist";
  870. bool triangles = primitiveElementsNode.Name == "triangles";
  871. bool trifans = primitiveElementsNode.Name == "trifans";
  872. bool tristrips = primitiveElementsNode.Name == "tristrips";
  873. if( lines || linestrips || trifans || tristrips )
  874. {
  875. Log.Warning( "\"{0}\" primitive element is not supported. Geometry: \"{1}\". " +
  876. "\n\nElement was skipped.", primitiveElementsNode.Name, geometryId );
  877. continue;
  878. }
  879. if( polygons || triangles || polylist )
  880. {
  881. int itemCount;
  882. if( !int.TryParse( XmlUtils.GetAttribute( primitiveElementsNode, "count" ), out itemCount ) )
  883. {
  884. Error( "Invalid \"count\" attribute of \"{0}\". Geometry: \"{1}\".",
  885. primitiveElementsNode.Name, geometryId );
  886. return false;
  887. }
  888. Pair<ChannelTypes, SourceItem>[] inputs;
  889. if( !ParseInputs( geometryId, sourceDictionary, vertexSemanticDictionary,
  890. primitiveElementsNode, out inputs ) )
  891. {
  892. return false;
  893. }
  894. int textureCoordCount = 0;
  895. bool vertexColors = false;
  896. {
  897. foreach( Pair<ChannelTypes, SourceItem> input in inputs )
  898. {
  899. ChannelTypes channelType = input.First;
  900. if( channelType >= ChannelTypes.TEXCOORD0 && channelType <= ChannelTypes.TEXCOORD3 )
  901. {
  902. int v = channelType - ChannelTypes.TEXCOORD0;
  903. if( ( v + 1 ) > textureCoordCount )
  904. textureCoordCount = v + 1;
  905. }
  906. if( channelType == ChannelTypes.COLOR )
  907. vertexColors = true;
  908. }
  909. }
  910. List<SubMeshVertex> vertices = new List<SubMeshVertex>( itemCount );
  911. if( polygons )
  912. {
  913. foreach( XmlNode pNode in primitiveElementsNode.ChildNodes )
  914. {
  915. if( pNode.Name != "p" )
  916. continue;
  917. int[] indexValues = ConvertStringToIntArray( pNode.InnerText );
  918. if( indexValues == null )
  919. {
  920. Error( "Cannot read index array of geometry \"{0}\".", geometryId );
  921. return false;
  922. }
  923. int vertexCount = indexValues.Length / inputs.Length;
  924. SubMeshVertex[] itemVertices = GenerateSubMeshVertices( inputs,
  925. vertexCount, indexValues, 0 );
  926. //generate triangles
  927. for( int n = 1; n < itemVertices.Length - 1; n++ )
  928. {
  929. vertices.Add( itemVertices[ 0 ] );
  930. vertices.Add( itemVertices[ n ] );
  931. vertices.Add( itemVertices[ n + 1 ] );
  932. }
  933. }
  934. }
  935. if( triangles )
  936. {
  937. XmlNode pNode = XmlUtils.FindChildNode( primitiveElementsNode, "p" );
  938. if( pNode != null )
  939. {
  940. int[] indexValues = ConvertStringToIntArray( pNode.InnerText );
  941. if( indexValues == null )
  942. {
  943. Error( "Cannot read \"p\" node of geometry \"{0}\".", geometryId );
  944. return false;
  945. }
  946. int vertexCount = indexValues.Length / inputs.Length;
  947. if( itemCount != vertexCount / 3 )
  948. {
  949. Error( "Invalid item amount of \"p\" node of geometry \"{0}\".", geometryId );
  950. return false;
  951. }
  952. SubMeshVertex[] itemVertices = GenerateSubMeshVertices( inputs,
  953. vertexCount, indexValues, 0 );
  954. //generate triangles
  955. for( int n = 0; n < vertexCount; n++ )
  956. vertices.Add( itemVertices[ n ] );
  957. }
  958. }
  959. if( polylist )
  960. {
  961. XmlNode vCountNode = XmlUtils.FindChildNode( primitiveElementsNode, "vcount" );
  962. XmlNode pNode = XmlUtils.FindChildNode( primitiveElementsNode, "p" );
  963. if( vCountNode != null && pNode != null )
  964. {
  965. int[] vCount = ConvertStringToIntArray( vCountNode.InnerText );
  966. if( vCount == null )
  967. {
  968. Error( "Cannot read \"vcount\" node of geometry \"{0}\".", geometryId );
  969. return false;
  970. }
  971. if( vCount.Length != itemCount )
  972. {
  973. Error( "Invalid item amount of \"vcount\" node of geometry \"{0}\".", geometryId );
  974. return false;
  975. }
  976. int[] indexValues = ConvertStringToIntArray( pNode.InnerText );
  977. if( indexValues == null )
  978. {
  979. Error( "Cannot read \"p\" node of geometry \"{0}\".", geometryId );
  980. return false;
  981. }
  982. int currentIndex = 0;
  983. foreach( int polyCount in vCount )
  984. {
  985. SubMeshVertex[] itemVertices = GenerateSubMeshVertices( inputs, polyCount,
  986. indexValues, currentIndex );
  987. currentIndex += polyCount * inputs.Length;
  988. //generate triangles
  989. for( int n = 1; n < itemVertices.Length - 1; n++ )
  990. {
  991. vertices.Add( itemVertices[ 0 ] );
  992. vertices.Add( itemVertices[ n ] );
  993. vertices.Add( itemVertices[ n + 1 ] );
  994. }
  995. }
  996. if( currentIndex != indexValues.Length )
  997. {
  998. Error( "Invalid indices of geometry \"{0}\".", geometryId );
  999. return false;
  1000. }
  1001. }
  1002. }
  1003. if( vertices.Count != 0 )
  1004. {
  1005. int[] indices = new int[ vertices.Count ];
  1006. for( int n = 0; n < indices.Length; n++ )
  1007. indices[ n ] = n;
  1008. MySceneMaterial material = null;
  1009. {
  1010. string materialName = XmlUtils.GetAttribute( primitiveElementsNode, "material" );
  1011. if( !string.IsNullOrEmpty( materialName ) )
  1012. material = GetOrCreateMaterial( materialName );
  1013. }
  1014. //add to geometrySubMeshes
  1015. GeometryItem.SubMesh geometrySubMesh = new GeometryItem.SubMesh(
  1016. vertices.ToArray(), indices, textureCoordCount, vertexColors, material );
  1017. geometrySubMeshes.Add( geometrySubMesh );
  1018. }
  1019. continue;
  1020. }
  1021. }
  1022. //add to generatedGeometries
  1023. {
  1024. GeometryItem geometry = new GeometryItem( geometryId, geometrySubMeshes.ToArray() );
  1025. generatedGeometries.Add( geometry.Id, geometry );
  1026. }
  1027. return true;
  1028. }
  1029. bool ParseGeometry( XmlNode geometryNode )
  1030. {
  1031. string geometryId = XmlUtils.GetAttribute( geometryNode, "id" );
  1032. //find mesh node
  1033. XmlNode meshNode = XmlUtils.FindChildNode( geometryNode, "mesh" );
  1034. if( meshNode == null )
  1035. {
  1036. Error( "Mesh node is not exists for geometry \"{0}\".", geometryId );
  1037. return false;
  1038. }
  1039. if( !ParseMeshNode( geometryId, meshNode ) )
  1040. return false;
  1041. return true;
  1042. }
  1043. bool ParseGeometries( XmlNode colladaNode )
  1044. {
  1045. foreach( XmlNode libraryGeometriesNode in colladaNode.ChildNodes )
  1046. {
  1047. if( libraryGeometriesNode.Name != "library_geometries" )
  1048. continue;
  1049. foreach( XmlNode geometryNode in libraryGeometriesNode.ChildNodes )
  1050. {
  1051. if( geometryNode.Name != "geometry" )
  1052. continue;
  1053. if( !ParseGeometry( geometryNode ) )
  1054. return false;
  1055. }
  1056. }
  1057. return true;
  1058. }
  1059. bool ParseNodeInstanceGeometry( Mat4 nodeTransform, XmlNode instanceGeometry )
  1060. {
  1061. string url = XmlUtils.GetAttribute( instanceGeometry, "url" );
  1062. bool nodeTransformIdentity = nodeTransform.Equals( Mat4.Identity, .0001f );
  1063. string geometryId = GetIdFromURL( url );
  1064. if( string.IsNullOrEmpty( geometryId ) )
  1065. {
  1066. Error( "Invalid \"url\" attribute specified for \"instance_geometry\". Url: \"{0}\".", url );
  1067. return false;
  1068. }
  1069. GeometryItem geometry;
  1070. if( !generatedGeometries.TryGetValue( geometryId, out geometry ) )
  1071. {
  1072. Error( "Geometry with id \"{0}\" is not exists.", geometryId );
  1073. return false;
  1074. }
  1075. foreach( GeometryItem.SubMesh geometrySubMesh in geometry.SubMeshes )
  1076. {
  1077. SubMeshVertex[] newVertices = new SubMeshVertex[ geometrySubMesh.Vertices.Length ];
  1078. for( int n = 0; n < newVertices.Length; n++ )
  1079. {
  1080. SubMeshVertex vertex = geometrySubMesh.Vertices[ n ];
  1081. if( !nodeTransformIdentity )
  1082. {
  1083. Vec3 oldPosition = vertex.position;
  1084. vertex.position = nodeTransform * vertex.position;
  1085. Vec3 p2 = nodeTransform * ( oldPosition + vertex.normal );
  1086. vertex.normal = ( p2 - vertex.position ).GetNormalize();
  1087. }
  1088. newVertices[ n ] = vertex;
  1089. }
  1090. MySceneSubMesh sceneSubMesh = new MySceneSubMesh( newVertices, geometrySubMesh.Indices,
  1091. geometrySubMesh.TextureCoordCount, geometrySubMesh.VertexColors, geometrySubMesh.Material );
  1092. generatedSubMeshes.Add( sceneSubMesh );
  1093. }
  1094. XmlNode bindMaterialNode = XmlUtils.FindChildNode( instanceGeometry, "bind_material" );
  1095. if( bindMaterialNode != null )
  1096. {
  1097. XmlNode techniqueCommonNode = XmlUtils.FindChildNode( bindMaterialNode, "technique_common" );
  1098. if( techniqueCommonNode == null )
  1099. {
  1100. Error( "Technique_common node is not exists for geometry \"{0}\".", geometryId );
  1101. return false;
  1102. }
  1103. foreach( XmlNode instanceMaterialNode in techniqueCommonNode.ChildNodes )
  1104. {
  1105. if( instanceMaterialNode.Name == "instance_material" )
  1106. {
  1107. string target = GetIdFromURL( XmlUtils.GetAttribute( instanceMaterialNode, "target" ) );
  1108. string symbol = XmlUtils.GetAttribute( instanceMaterialNode, "symbol" );
  1109. if( !generatedBindedMaterials.ContainsKey( target ) )
  1110. generatedBindedMaterials.Add( target, symbol );
  1111. }
  1112. }
  1113. }
  1114. return true;
  1115. }
  1116. bool ParseNode( Mat4 nodeTransform, XmlNode node )
  1117. {
  1118. string nodeId = XmlUtils.GetAttribute( node, "id" );
  1119. Mat4 currentTransform = nodeTransform;
  1120. foreach( XmlNode childNode in node.ChildNodes )
  1121. {
  1122. if( childNode.Name == "matrix" )
  1123. {
  1124. float[] values = ConvertStringToFloatArray( childNode.InnerText );
  1125. if( values == null || values.Length != 16 )
  1126. {
  1127. Error( "Invalid format of \"matrix\" node. Node \"{0}\".", nodeId );
  1128. return false;
  1129. }
  1130. Mat4 matrix = new Mat4( values );
  1131. currentTransform *= matrix;
  1132. continue;
  1133. }
  1134. if( childNode.Name == "translate" )
  1135. {
  1136. float[] values = ConvertStringToFloatArray( childNode.InnerText );
  1137. if( values == null || values.Length != 3 )
  1138. {
  1139. Error( "Invalid format of \"translate\" node. Node \"{0}\".", nodeId );
  1140. return false;
  1141. }
  1142. Vec3 translate = new Vec3( values[ 0 ], values[ 1 ], values[ 2 ] );
  1143. currentTransform *= Mat4.FromTranslate( translate );
  1144. continue;
  1145. }
  1146. if( childNode.Name == "rotate" )
  1147. {
  1148. float[] values = ConvertStringToFloatArray( childNode.InnerText );
  1149. if( values == null || values.Length != 4 )
  1150. {
  1151. Error( "Invalid format of \"rotate\" node. Node \"{0}\".", nodeId );
  1152. return false;
  1153. }
  1154. Vec3 axis = new Vec3( values[ 0 ], values[ 1 ], values[ 2 ] );
  1155. Radian angle = new Degree( values[ 3 ] ).InRadians();
  1156. if( axis != Vec3.Zero )
  1157. {
  1158. axis.Normalize();
  1159. float halfAngle = .5f * angle;
  1160. float sin = MathFunctions.Sin( halfAngle );
  1161. float cos = MathFunctions.Cos( halfAngle );
  1162. Quat r = new Quat( axis * sin, cos );
  1163. r.Normalize();
  1164. currentTransform *= r.ToMat3().ToMat4();
  1165. }
  1166. continue;
  1167. }
  1168. if( childNode.Name == "scale" )
  1169. {
  1170. float[] values = ConvertStringToFloatArray( childNode.InnerText );
  1171. if( values == null || values.Length != 3 )
  1172. {
  1173. Error( "Invalid format of \"scale\" node. Node \"{0}\".", nodeId );
  1174. return false;
  1175. }
  1176. Vec3 scale = new Vec3( values[ 0 ], values[ 1 ], values[ 2 ] );
  1177. currentTransform *= Mat3.FromScale( scale ).ToMat4();
  1178. continue;
  1179. }
  1180. if( childNode.Name == "node" )
  1181. {
  1182. if( !ParseNode( currentTransform, childNode ) )
  1183. return false;
  1184. continue;
  1185. }
  1186. if( childNode.Name == "instance_geometry" )
  1187. {
  1188. if( !ParseNodeInstanceGeometry( currentTransform, childNode ) )
  1189. return false;
  1190. continue;
  1191. }
  1192. }
  1193. return true;
  1194. }
  1195. bool ParseImage( XmlNode imageNode )
  1196. {
  1197. string imageId = XmlUtils.GetAttribute( imageNode, "id" );
  1198. //find profile node
  1199. XmlNode initFromNode = XmlUtils.FindChildNode( imageNode, "init_from" );
  1200. if( initFromNode == null )
  1201. {
  1202. Error( "Init_from node is not exists for image \"{0}\".", imageId );
  1203. return false;
  1204. }
  1205. generatedImages.Add( imageId, initFromNode.InnerText );
  1206. return true;
  1207. }
  1208. bool ParseImages( XmlNode colladaNode )
  1209. {
  1210. foreach( XmlNode libraryImagesNode in colladaNode.ChildNodes )
  1211. {
  1212. if( libraryImagesNode.Name != "library_images" )
  1213. continue;
  1214. foreach( XmlNode imageNode in libraryImagesNode.ChildNodes )
  1215. {
  1216. if( imageNode.Name != "image" )
  1217. continue;
  1218. if( !ParseImage( imageNode ) )
  1219. return false;
  1220. }
  1221. }
  1222. return true;
  1223. }
  1224. bool ParseMaterial( XmlNode materialNode )
  1225. {
  1226. string materialId = XmlUtils.GetAttribute( materialNode, "id" );
  1227. string materialName = XmlUtils.GetAttribute( materialNode, "name" );
  1228. //find profile node
  1229. XmlNode instanceEffectNode = XmlUtils.FindChildNode( materialNode, "instance_effect" );
  1230. if( instanceEffectNode == null )
  1231. {
  1232. Error( "Instance_effect node is not exists for material \"{0}\".", materialId );
  1233. return false;
  1234. }
  1235. string effectId = GetIdFromURL( XmlUtils.GetAttribute( instanceEffectNode, "url" ) );
  1236. generatedEffects.Add( effectId, materialId );
  1237. return true;
  1238. }
  1239. bool ParseMaterials( XmlNode colladaNode )
  1240. {
  1241. foreach( XmlNode libraryMaterialsNode in colladaNode.ChildNodes )
  1242. {
  1243. if( libraryMaterialsNode.Name != "library_materials" )
  1244. continue;
  1245. foreach( XmlNode materialNode in libraryMaterialsNode.ChildNodes )
  1246. {
  1247. if( materialNode.Name != "material" )
  1248. continue;
  1249. if( !ParseMaterial( materialNode ) )
  1250. return false;
  1251. }
  1252. }
  1253. return true;
  1254. }
  1255. bool ParseTextureBlendingMode( XmlNode textureNode, out string blendingMode,
  1256. string materialAttributeName )
  1257. {
  1258. blendingMode = "";
  1259. XmlNode extraNode = XmlUtils.FindChildNode( textureNode, "extra" );
  1260. if( extraNode == null )
  1261. {
  1262. return true;
  1263. }
  1264. XmlNode techniqueNode = XmlUtils.FindChildNode( extraNode, "technique" );
  1265. if( techniqueNode == null )
  1266. {
  1267. Error( "Technique node is not exists for texture node of matterial attribute \"{0}\".",
  1268. materialAttributeName );
  1269. return false;
  1270. }
  1271. XmlNode blendMode = XmlUtils.FindChildNode( techniqueNode, "blend_mode" );
  1272. if( techniqueNode == null )
  1273. {
  1274. Error( "Blend_mode node is not exists for technique node of matterial attribute \"{0}\".",
  1275. materialAttributeName );
  1276. return false;
  1277. }
  1278. blendingMode = blendMode.InnerText;
  1279. return true;
  1280. }
  1281. bool ParseEffectAttribute( XmlNode materialAttributeNode, ref ColorValue color,
  1282. ref string textureId1, ref string textureCoord1, ref string textureId2,
  1283. ref string textureCoord2, ref string blendingMode2, ref string textureId3,
  1284. ref string textureCoord3, ref string blendingMode3, ref string textureId4,
  1285. ref string textureCoord4, ref string blendingMode4 )
  1286. {
  1287. if( materialAttributeNode.ChildNodes.Count == 0 )
  1288. {
  1289. Error( "Parameter is not exists for matterial attribute \"{0}\".",
  1290. materialAttributeNode.Name );
  1291. return false;
  1292. }
  1293. int texturesCount = 0;
  1294. foreach( XmlNode parameterNode in materialAttributeNode.ChildNodes )
  1295. {
  1296. if( parameterNode.Name == "texture" )
  1297. {
  1298. string texCoord = XmlUtils.GetAttribute( parameterNode, "texcoord" );
  1299. string textureId = XmlUtils.GetAttribute( parameterNode, "texture" );
  1300. string blendingMode;
  1301. if( !ParseTextureBlendingMode( parameterNode, out blendingMode,
  1302. materialAttributeNode.Name ) )
  1303. return false;
  1304. switch( texturesCount )
  1305. {
  1306. case 0:
  1307. textureId1 = textureId;
  1308. textureCoord1 = texCoord;
  1309. break;
  1310. case 1:
  1311. textureId2 = textureId;
  1312. textureCoord2 = texCoord;
  1313. blendingMode2 = blendingMode;
  1314. break;
  1315. case 2:
  1316. textureId3 = textureId;
  1317. textureCoord3 = texCoord;
  1318. blendingMode3 = blendingMode;
  1319. break;
  1320. case 3:
  1321. textureId4 = textureId;
  1322. textureCoord4 = texCoord;
  1323. blendingMode4 = blendingMode;
  1324. break;
  1325. }
  1326. texturesCount++;
  1327. }
  1328. if( parameterNode.Name == "color" )
  1329. color = ConvertStringToColorValue( parameterNode.InnerText );
  1330. }
  1331. return true;
  1332. }
  1333. string GetTextureFileName( XmlNode profileNode, string imageId )
  1334. {
  1335. string textureFileName;
  1336. //XSI specified
  1337. foreach( XmlNode newParamNode in profileNode )
  1338. {
  1339. if( newParamNode.Name != "newparam" )
  1340. continue;
  1341. if( XmlUtils.GetAttribute( newParamNode, "sid" ) == imageId )
  1342. {
  1343. XmlNode sampler2D = XmlUtils.FindChildNode( newParamNode, "sampler2D" );
  1344. if( sampler2D == null )
  1345. continue;
  1346. XmlNode source = XmlUtils.FindChildNode( sampler2D, "source" );
  1347. if( source == null )
  1348. continue;
  1349. string surfaceId = source.InnerText;
  1350. foreach( XmlNode newParamSurfaceNode in profileNode )
  1351. {
  1352. if( newParamNode.Name != "newparam" )
  1353. continue;
  1354. if( XmlUtils.GetAttribute( newParamSurfaceNode, "sid" ) == surfaceId )
  1355. {
  1356. XmlNode surface = XmlUtils.FindChildNode( newParamSurfaceNode, "surface" );
  1357. if( surface == null )
  1358. continue;
  1359. XmlNode initFrom = XmlUtils.FindChildNode( surface, "init_from" );
  1360. if( initFrom == null )
  1361. continue;
  1362. if( generatedImages.TryGetValue( initFrom.InnerText, out textureFileName ) )
  1363. return textureFileName;
  1364. }
  1365. }
  1366. }
  1367. }
  1368. //Max\Maya specified
  1369. if( generatedImages.TryGetValue( imageId, out textureFileName ) )
  1370. return textureFileName;
  1371. return "";
  1372. }
  1373. bool ParseEffectNode( XmlNode profileNode, XmlNode effectNode, ref MySceneMaterial material )
  1374. {
  1375. foreach( XmlNode materialAttributeNode in effectNode.ChildNodes )
  1376. {
  1377. if( materialAttributeNode.Name == "diffuse" )
  1378. {
  1379. ColorValue diffuseColor = new ColorValue( 1, 1, 1 );
  1380. string textureId1 = "";
  1381. string textureId2 = "";
  1382. string textureId3 = "";
  1383. string textureId4 = "";
  1384. string textureCoord1 = "";
  1385. string textureCoord2 = "";
  1386. string textureCoord3 = "";
  1387. string textureCoord4 = "";
  1388. string blendingMode2 = "";
  1389. string blendingMode3 = "";
  1390. string blendingMode4 = "";
  1391. if( !ParseEffectAttribute( materialAttributeNode, ref diffuseColor, ref textureId1,
  1392. ref textureCoord1, ref textureId2, ref textureCoord2, ref blendingMode2,
  1393. ref textureId3, ref textureCoord3, ref blendingMode3, ref textureId4,
  1394. ref textureCoord4, ref blendingMode4 ) )
  1395. return false;
  1396. material.DiffuseColor = diffuseColor;
  1397. if( !string.IsNullOrEmpty( textureId1 ) )
  1398. {
  1399. material.Diffuse1Map = GetTextureFileName( profileNode, textureId1 );
  1400. material.Diffuse1TexCoord = textureCoord1;
  1401. }
  1402. if( !string.IsNullOrEmpty( textureId2 ) )
  1403. {
  1404. material.Diffuse2Map = GetTextureFileName( profileNode, textureId2 );
  1405. material.Diffuse2TexCoord = textureCoord2;
  1406. material.Diffuse2MapBlending = blendingMode2;
  1407. }
  1408. if( !string.IsNullOrEmpty( textureId3 ) )
  1409. {
  1410. material.Diffuse3Map = GetTextureFileName( profileNode, textureId3 );
  1411. material.Diffuse3TexCoord = textureCoord3;
  1412. material.Diffuse3MapBlending = blendingMode3;
  1413. }
  1414. if( !string.IsNullOrEmpty( textureId4 ) )
  1415. {
  1416. material.Diffuse4Map = GetTextureFileName( profileNode, textureId4 );
  1417. material.Diffuse4TexCoord = textureCoord4;
  1418. material.Diffuse4MapBlending = blendingMode4;
  1419. }
  1420. }
  1421. if( materialAttributeNode.Name == "specular" )
  1422. {
  1423. ColorValue specularColor = new ColorValue( 0, 0, 0 );
  1424. string textureId1 = "";
  1425. string textureId2 = "";
  1426. string textureId3 = "";
  1427. string textureId4 = "";
  1428. string textureCoord1 = "";
  1429. string textureCoord2 = "";
  1430. string textureCoord3 = "";
  1431. string textureCoord4 = "";
  1432. string blendingMode2 = "";
  1433. string blendingMode3 = "";
  1434. string blendingMode4 = "";
  1435. if( !ParseEffectAttribute( materialAttributeNode, ref specularColor, ref textureId1,
  1436. ref textureCoord1, ref textureId2, ref textureCoord2, ref blendingMode2,
  1437. ref textureId3, ref textureCoord3, ref blendingMode3, ref textureId4,
  1438. ref textureCoord4, ref blendingMode4 ) )
  1439. return false;
  1440. material.SpecularColor = specularColor;
  1441. if( !string.IsNullOrEmpty( textureId1 ) )
  1442. {
  1443. material.SpecularMap = GetTextureFileName( profileNode, textureId1 );
  1444. material.SpecularTexCoord = textureCoord1;
  1445. }
  1446. }
  1447. if( materialAttributeNode.Name == "shininess" )
  1448. {
  1449. XmlNode floatNode = XmlUtils.FindChildNode( materialAttributeNode, "float" );
  1450. if( floatNode == null )
  1451. {
  1452. Error( "\"float\" node is not exists for material attribute \"{0}\".",
  1453. materialAttributeNode.Name );
  1454. return false;
  1455. }
  1456. float shininess;
  1457. if( !float.TryParse( floatNode.InnerText, out shininess ) )
  1458. {
  1459. Error( "Invalid \"float\" attribute of \"shininess\" node." );
  1460. return false;
  1461. }
  1462. material.Shininess = shininess;
  1463. }
  1464. if( materialAttributeNode.Name == "emission" )
  1465. {
  1466. ColorValue emissionColor = new ColorValue( 0, 0, 0 );
  1467. string textureId1 = "";
  1468. string textureId2 = "";
  1469. string textureId3 = "";
  1470. string textureId4 = "";
  1471. string textureCoord1 = "";
  1472. string textureCoord2 = "";
  1473. string textureCoord3 = "";
  1474. string textureCoord4 = "";
  1475. string blendingMode2 = "";
  1476. string blendingMode3 = "";
  1477. string blendingMode4 = "";
  1478. if( !ParseEffectAttribute( materialAttributeNode, ref emissionColor, ref textureId1,
  1479. ref textureCoord1, ref textureId2, ref textureCoord2, ref blendingMode2,
  1480. ref textureId3, ref textureCoord3, ref blendingMode3, ref textureId4,
  1481. ref textureCoord4, ref blendingMode4 ) )
  1482. return false;
  1483. material.EmissionColor = emissionColor;
  1484. if( !string.IsNullOrEmpty( textureId1 ) )
  1485. {
  1486. material.EmissionMap = GetTextureFileName( profileNode, textureId1 );
  1487. material.EmissionTexCoord = textureCoord1;
  1488. }
  1489. }
  1490. if( materialAttributeNode.Name == "transparent" )
  1491. {
  1492. string opaque = XmlUtils.GetAttribute( materialAttributeNode, "opaque" );
  1493. if( opaque == "RGB_ZERO" )
  1494. {
  1495. material.Opaque = true;
  1496. }
  1497. XmlNode colorNode = XmlUtils.FindChildNode( materialAttributeNode, "color" );
  1498. if( colorNode == null )
  1499. {
  1500. material.TransparentColor = new ColorValue( 1, 1, 1 );
  1501. }
  1502. else
  1503. {
  1504. material.TransparentColor = ConvertStringToColorValue( colorNode.InnerText );
  1505. }
  1506. }
  1507. if( materialAttributeNode.Name == "transparency" )
  1508. {
  1509. XmlNode floatNode = XmlUtils.FindChildNode( materialAttributeNode, "float" );
  1510. if( floatNode == null )
  1511. {
  1512. Error( "\"float\" node is not exists for material attribute \"{0}\".",
  1513. materialAttributeNode.Name );
  1514. return false;
  1515. }
  1516. float transparency;
  1517. if( !float.TryParse( floatNode.InnerText, out transparency ) )
  1518. {
  1519. Error( "Invalid \"float\" attribute of \"transparency\" node." );
  1520. return false;
  1521. }
  1522. material.Transparency = transparency;
  1523. }
  1524. }
  1525. return true;
  1526. }
  1527. bool ParseEffectExtraNode( XmlNode extraNode, string effectId, ref MySceneMaterial material )
  1528. {
  1529. foreach( XmlNode extraAttributeNode in extraNode.ChildNodes )
  1530. {
  1531. if( extraAttributeNode.Name == "technique" )
  1532. {
  1533. string profile = XmlUtils.GetAttribute( extraAttributeNode, "profile" );
  1534. if( profile == "MAX3D" )
  1535. {
  1536. foreach( XmlNode techniqueAtttributeNode in extraAttributeNode.ChildNodes )
  1537. {
  1538. if( techniqueAtttributeNode.Name == "double_sided" )
  1539. {
  1540. int doubleSided;
  1541. if( !int.TryParse( techniqueAtttributeNode.InnerText, out doubleSided ) )
  1542. {
  1543. Error( "Invalid \"double_sided\" attribute of \"technique\" node " +
  1544. "for effect {0}.", effectId );
  1545. return false;
  1546. }
  1547. if( doubleSided == 1 )
  1548. material.Culling = false;
  1549. }
  1550. }
  1551. }
  1552. }
  1553. }
  1554. return true;
  1555. }
  1556. bool ParseEffect( XmlNode effectNode )
  1557. {
  1558. string effectId = XmlUtils.GetAttribute( effectNode, "id" );
  1559. MySceneMaterial material;
  1560. string effectName;
  1561. if( !generatedEffects.TryGetValue( effectId, out effectName ) )
  1562. {
  1563. Error( "Generated effect is not exists for effect \"{0}\".", effectId );
  1564. return false;
  1565. }
  1566. string materialName;
  1567. if( !generatedBindedMaterials.TryGetValue( effectName, out materialName ) )
  1568. {
  1569. //Effect exist in library_effects, but not used in visual scenes
  1570. return true;
  1571. }
  1572. if( !generatedMaterials.TryGetValue( materialName, out material ) )
  1573. {
  1574. //Effect exist in library_effects, but not used in geometries
  1575. return true;
  1576. }
  1577. //find profile node
  1578. XmlNode profileNode = XmlUtils.FindChildNode( effectNode, "profile_COMMON" );
  1579. if( profileNode == null )
  1580. {
  1581. Error( "Profile node is not exists for effect \"{0}\".", effectId );
  1582. return false;
  1583. }
  1584. //find technique node
  1585. XmlNode techniqueNode = XmlUtils.FindChildNode( profileNode, "technique" );
  1586. if( techniqueNode == null )
  1587. {
  1588. Error( "Technique node is not exists for effect \"{0}\".", effectId );
  1589. return false;
  1590. }
  1591. if( techniqueNode.ChildNodes.Count == 0 )
  1592. {
  1593. Error( "Material node is not exists for effect \"{0}\".", effectId );
  1594. return false;
  1595. }
  1596. foreach( XmlNode effectMaterialNode in techniqueNode.ChildNodes )
  1597. {
  1598. if( effectMaterialNode.Name == "blinn" || effectMaterialNode.Name == "lambert" ||
  1599. effectMaterialNode.Name == "phong" )
  1600. {
  1601. if( !ParseEffectNode( profileNode, techniqueNode.ChildNodes[ 0 ], ref material ) )
  1602. return false;
  1603. XmlNode extraNode = XmlUtils.FindChildNode( effectNode, "extra" );
  1604. if( extraNode != null )
  1605. {
  1606. if( !ParseEffectExtraNode( extraNode, effectId, ref material ) )
  1607. return false;
  1608. }
  1609. generatedMaterials[ materialName ] = material;
  1610. return true;
  1611. }
  1612. }
  1613. Error( "Material node is not exists for effect \"{0}\".", effectId );
  1614. return false;
  1615. }
  1616. bool ParseEffects( XmlNode colladaNode )
  1617. {
  1618. foreach( XmlNode libraryEffectsNode in colladaNode.ChildNodes )
  1619. {
  1620. if( libraryEffectsNode.Name != "library_effects" )
  1621. continue;
  1622. foreach( XmlNode effectNode in libraryEffectsNode.ChildNodes )
  1623. {
  1624. if( effectNode.Name != "effect" )
  1625. continue;
  1626. if( !ParseEffect( effectNode ) )
  1627. return false;
  1628. }
  1629. }
  1630. return true;
  1631. }
  1632. bool ParseVisualScenes( XmlNode colladaNode )
  1633. {
  1634. foreach( XmlNode visualScenesNode in colladaNode.ChildNodes )
  1635. {
  1636. if( visualScenesNode.Name != "library_visual_scenes" )
  1637. continue;
  1638. foreach( XmlNode visualSceneNode in visualScenesNode.ChildNodes )
  1639. {
  1640. if( visualSceneNode.Name != "visual_scene" )
  1641. continue;
  1642. foreach( XmlNode nodeNode in visualSceneNode.ChildNodes )
  1643. {
  1644. if( nodeNode.Name != "node" )
  1645. continue;
  1646. Mat4 currentTransform = Mat4.Identity;
  1647. if( globalScale != 1 )
  1648. {
  1649. Mat4 m = Mat3.FromScale( new Vec3( globalScale, globalScale, globalScale ) ).ToMat4();
  1650. currentTransform *= m;
  1651. }
  1652. if( yAxisUp )
  1653. {
  1654. //good for xsi, blender
  1655. Mat4 rotationMatrix = Mat3.FromRotateByX( new Degree( -90 ) ).ToMat4();
  1656. //good for 3dsmax
  1657. //Mat4 rotationMatrix = Mat3.FromRotateByX( new Degree( 90 ) ).ToMat4();
  1658. currentTransform *= rotationMatrix;
  1659. }
  1660. if( !ParseNode( currentTransform, nodeNode ) )
  1661. return false;
  1662. }
  1663. }
  1664. }
  1665. return true;
  1666. }
  1667. bool ParseColladaNode( XmlNode colladaNode )
  1668. {
  1669. //colladaExportingTool, globalScale, yAxisUp
  1670. {
  1671. XmlNode assetNode = XmlUtils.FindChildNode( colladaNode, "asset" );
  1672. if( assetNode != null )
  1673. {
  1674. XmlNode contributorNode = XmlUtils.FindChildNode( assetNode, "contributor" );
  1675. if( contributorNode != null )
  1676. {
  1677. XmlNode authoringToolNode = XmlUtils.FindChildNode( contributorNode,
  1678. "authoring_tool" );
  1679. if( authoringToolNode != null )
  1680. {
  1681. colladaExportingTool = GetColladaExportingTool( authoringToolNode.InnerText );
  1682. }
  1683. }
  1684. XmlNode upAxisNode = XmlUtils.FindChildNode( assetNode, "up_axis" );
  1685. if( upAxisNode != null )
  1686. {
  1687. if( upAxisNode.InnerText == "Z_UP" )
  1688. yAxisUp = false;
  1689. else if( upAxisNode.InnerText == "X_UP" )
  1690. {
  1691. Error( "X up axis is not supported." );
  1692. return false;
  1693. }
  1694. }
  1695. XmlNode unitNode = XmlUtils.FindChildNode( assetNode, "unit" );
  1696. if( unitNode != null )
  1697. {
  1698. string meterStr = XmlUtils.GetAttribute( unitNode, "meter" );
  1699. if( !string.IsNullOrEmpty( meterStr ) )
  1700. {
  1701. string fixedStr = meterStr.Replace( ',', '.' );
  1702. if( !float.TryParse( fixedStr, out globalScale ) )
  1703. {
  1704. Error( "Invalid \"meter\" attribute of \"unit\" node." );
  1705. return false;
  1706. }
  1707. }
  1708. }
  1709. }
  1710. }
  1711. //library_geometries
  1712. if( !ParseGeometries( colladaNode ) )
  1713. return false;
  1714. //library_visual_scenes
  1715. if( !ParseVisualScenes( colladaNode ) )
  1716. return false;
  1717. //library_images
  1718. if( !ParseImages( colladaNode ) )
  1719. return false;
  1720. //library_materials
  1721. if( !ParseMaterials( colladaNode ) )
  1722. return false;
  1723. //library_effects
  1724. if( !ParseEffects( colladaNode ) )
  1725. return false;
  1726. return true;
  1727. }
  1728. void ClearTemporaryFields()
  1729. {
  1730. currentFileName = null;
  1731. currentMesh = null;
  1732. globalScale = 1;
  1733. yAxisUp = true;
  1734. colladaExportingTool = ColladaExportingTools.Unknown;
  1735. generatedMaterials = null;
  1736. generatedGeometries = null;
  1737. generatedSubMeshes = null;
  1738. generatedImages = null;
  1739. generatedEffects = null;
  1740. generatedBindedMaterials = null;
  1741. }
  1742. string GetUniqueMaterialName( string prefix )
  1743. {
  1744. int counter = 1;
  1745. while( true )
  1746. {
  1747. string name = prefix;
  1748. if( counter != 1 )
  1749. name += counter.ToString();
  1750. if( MaterialManager.Instance.GetByName( name ) == null &&
  1751. !generatedMaterials.ContainsKey( name ) )
  1752. {
  1753. return name;
  1754. }
  1755. counter++;
  1756. }
  1757. }
  1758. void MakeUniqueNamesForMaterials()
  1759. {
  1760. List<MySceneMaterial> oldList = new List<MySceneMaterial>( generatedMaterials.Values );
  1761. generatedMaterials = new Dictionary<string, MySceneMaterial>();
  1762. foreach( MySceneMaterial material in oldList )
  1763. {
  1764. string uniqueMaterialName = GetUniqueMaterialName( material.Name );
  1765. material.Name = uniqueMaterialName;
  1766. generatedMaterials[ uniqueMaterialName ] = material;
  1767. }
  1768. }
  1769. bool DoExportMaterials()
  1770. {
  1771. string colladaFileDirectory = Path.GetDirectoryName( currentFileName );
  1772. foreach( MySceneMaterial material in generatedMaterials.Values )
  1773. {
  1774. ShaderBaseMaterial shaderBaseMaterial = (ShaderBaseMaterial)
  1775. HighLevelMaterialManager.Instance.CreateMaterial( material.Name, "ShaderBaseMaterial" );
  1776. if( shaderBaseMaterial == null )
  1777. {
  1778. Error( "Unable to create ShaderBaseMaterial material with name \"{0}\".", material.Name );
  1779. return false;
  1780. }
  1781. currentMesh.AttachDependentMaterial( shaderBaseMaterial );
  1782. //blending
  1783. float alpha = material.GetAlpha();
  1784. if( alpha < 1 )
  1785. shaderBaseMaterial.Blending = ShaderBaseMaterial.MaterialBlendingTypes.AlphaBlend;
  1786. //culling
  1787. if( !material.Culling )
  1788. shaderBaseMaterial.Culling = false;
  1789. //diffuseColor
  1790. if( material.DiffuseColor.Red < 1 || material.DiffuseColor.Green < 1 ||
  1791. material.DiffuseColor.Blue < 1 || alpha < 1 )
  1792. {
  1793. Vec3 color = new Vec3( material.DiffuseColor.Red, material.DiffuseColor.Green,
  1794. material.DiffuseColor.Blue );
  1795. float power = Math.Max( Math.Max( color.X, color.Y ), color.Z );
  1796. if( power > 1 )
  1797. color /= power;
  1798. if( alpha < 1 )
  1799. shaderBaseMaterial.DiffuseColor = new ColorValue( color.X, color.Y, color.Z, alpha );
  1800. else
  1801. shaderBaseMaterial.DiffuseColor = new ColorValue( color.X, color.Y, color.Z );
  1802. if( power > 1 )
  1803. shaderBaseMaterial.DiffusePower = power;
  1804. }
  1805. //diffuseMap1
  1806. if( !string.IsNullOrEmpty( material.Diffuse1Map ) )
  1807. {
  1808. shaderBaseMaterial.Diffuse1Map.Texture =
  1809. GetVirtualPath( colladaFileDirectory, material.Diffuse1Map );
  1810. shaderBaseMaterial.Diffuse1Map.TexCoord = GetNeoAxisTexCoordByColladaTexCoord(
  1811. material.Diffuse1TexCoord );
  1812. }
  1813. //diffuseMap2
  1814. if( !string.IsNullOrEmpty( material.Diffuse2Map ) )
  1815. {
  1816. shaderBaseMaterial.Diffuse2Map.Texture =
  1817. GetVirtualPath( colladaFileDirectory, material.Diffuse2Map );
  1818. shaderBaseMaterial.Diffuse2Map.Blending = GetMapBlendingType(
  1819. material.Diffuse2MapBlending );
  1820. shaderBaseMaterial.Diffuse2Map.TexCoord = GetNeoAxisTexCoordByColladaTexCoord(
  1821. material.Diffuse2TexCoord );
  1822. }
  1823. //diffuseMap3
  1824. if( !string.IsNullOrEmpty( material.Diffuse3Map ) )
  1825. {
  1826. shaderBaseMaterial.Diffuse3Map.Texture =
  1827. GetVirtualPath( colladaFileDirectory, material.Diffuse3Map );
  1828. shaderBaseMaterial.Diffuse3Map.Blending = GetMapBlendingType(
  1829. material.Diffuse3MapBlending );
  1830. shaderBaseMaterial.Diffuse3Map.TexCoord = GetNeoAxisTexCoordByColladaTexCoord(
  1831. material.Diffuse3TexCoord );
  1832. }
  1833. //diffuseMap4
  1834. if( !string.IsNullOrEmpty( material.Diffuse4Map ) )
  1835. {
  1836. shaderBaseMaterial.Diffuse4Map.Texture =
  1837. GetVirtualPath( colladaFileDirectory, material.Diffuse4Map );
  1838. shaderBaseMaterial.Diffuse4Map.Blending = GetMapBlendingType(
  1839. material.Diffuse4MapBlending );
  1840. shaderBaseMaterial.Diffuse4Map.TexCoord = GetNeoAxisTexCoordByColladaTexCoord(
  1841. material.Diffuse4TexCoord );
  1842. }
  1843. //specularMap
  1844. if( !string.IsNullOrEmpty( material.SpecularMap ) )
  1845. {
  1846. shaderBaseMaterial.SpecularMap.Texture =
  1847. GetVirtualPath( colladaFileDirectory, material.SpecularMap );
  1848. shaderBaseMaterial.SpecularMap.TexCoord = GetNeoAxisTexCoordByColladaTexCoord(
  1849. material.SpecularTexCoord );
  1850. }
  1851. //specularColor
  1852. if( material.SpecularColor.Red > 0 || material.SpecularColor.Green > 0 ||
  1853. material.SpecularColor.Blue > 0 )
  1854. {
  1855. shaderBaseMaterial.SpecularColor = material.SpecularColor;
  1856. }
  1857. //specularShininess
  1858. if( !string.IsNullOrEmpty( material.SpecularMap ) || material.SpecularColor.Red > 0 ||
  1859. material.SpecularColor.Green > 0 || material.SpecularColor.Blue > 0 )
  1860. {
  1861. //conversion can be configured better.
  1862. switch( colladaExportingTool )
  1863. {
  1864. case ColladaExportingTools.FBX:
  1865. case ColladaExportingTools.NeoAxis:
  1866. shaderBaseMaterial.SpecularShininess = material.Shininess * 3;
  1867. break;
  1868. default:
  1869. shaderBaseMaterial.SpecularShininess = material.Shininess;
  1870. break;
  1871. }
  1872. }
  1873. //emissionMap
  1874. if( !string.IsNullOrEmpty( material.EmissionMap ) )
  1875. {
  1876. shaderBaseMaterial.EmissionMap.Texture =
  1877. GetVirtualPath( colladaFileDirectory, material.EmissionMap );
  1878. shaderBaseMaterial.EmissionMap.TexCoord = GetNeoAxisTexCoordByColladaTexCoord(
  1879. material.EmissionTexCoord );
  1880. }
  1881. //emissionColor
  1882. if( material.EmissionColor.Red > 0 || material.EmissionColor.Green > 0 ||
  1883. material.EmissionColor.Blue > 0 )
  1884. {
  1885. shaderBaseMaterial.EmissionColor = material.EmissionColor;
  1886. }
  1887. shaderBaseMaterial.UpdateBaseMaterial();
  1888. }
  1889. return true;
  1890. }
  1891. protected override bool Load( string virtualFileName, Mesh mesh )
  1892. {
  1893. currentFileName = virtualFileName;
  1894. currentMesh = mesh;
  1895. globalScale = 1;
  1896. yAxisUp = true;
  1897. colladaExportingTool = ColladaExportingTools.Unknown;
  1898. generatedMaterials = new Dictionary<string, MySceneMaterial>();
  1899. generatedGeometries = new Dictionary<string, GeometryItem>();
  1900. generatedSubMeshes = new List<MySceneSubMesh>();
  1901. generatedImages = new Dictionary<string, string>();
  1902. generatedEffects = new Dictionary<string, string>();
  1903. generatedBindedMaterials = new Dictionary<string, string>();
  1904. //load file
  1905. XmlNode colladaNode;
  1906. {
  1907. try
  1908. {
  1909. using( Stream stream = VirtualFile.Open( virtualFileName ) )
  1910. {
  1911. string fileText = new StreamReader( stream ).ReadToEnd();
  1912. colladaNode = XmlUtils.LoadFromText( fileText );
  1913. }
  1914. }
  1915. catch( Exception ex )
  1916. {
  1917. Error( ex.Message );
  1918. return false;
  1919. }
  1920. }
  1921. //parse
  1922. if( !ParseColladaNode( colladaNode ) )
  1923. {
  1924. ClearTemporaryFields();
  1925. return false;
  1926. }
  1927. MakeUniqueNamesForMaterials();
  1928. if( !DoExportMaterials() )
  1929. {
  1930. ClearTemporaryFields();
  1931. return false;
  1932. }
  1933. //generate mesh
  1934. const bool tangents = true;
  1935. const bool edgeList = true;
  1936. const bool allowMergeSubMeshes = true;
  1937. MeshConstructor meshConstructor = new MeshConstructor( tangents, edgeList, allowMergeSubMeshes );
  1938. MyMeshSceneObject meshSceneObject = new MyMeshSceneObject( generatedSubMeshes.ToArray() );
  1939. if( !meshConstructor.DoExport( meshSceneObject, mesh ) )
  1940. {
  1941. ClearTemporaryFields();
  1942. return false;
  1943. }
  1944. ClearTemporaryFields();
  1945. return true;
  1946. }
  1947. /////////////////////////////////////////////////////////////////////////////////////////////////////
  1948. float[] ConvertVertexBufferInfoToFloatArray( VertexBufferBinding bufferBinding,
  1949. VertexElement element, int elementsCount, int valuesPerElement )
  1950. {
  1951. float[] floatArray = new float[ elementsCount * valuesPerElement ];
  1952. HardwareVertexBuffer buffer = bufferBinding.GetBuffer( element.Source );
  1953. unsafe
  1954. {
  1955. byte* pointer = (byte*)buffer.Lock( HardwareBuffer.LockOptions.Normal ).ToPointer();
  1956. byte* p = pointer + element.Offset;
  1957. for( int n = 0; n < elementsCount; n++ )
  1958. {
  1959. for( int i = 0; i < valuesPerElement; i++ )
  1960. {
  1961. floatArray[ n * valuesPerElement + i ] = *(float*)( p + sizeof( float ) * i );
  1962. }
  1963. p += buffer.VertexSizeInBytes;
  1964. }
  1965. }
  1966. buffer.Unlock();
  1967. return floatArray;
  1968. }
  1969. void ConvertMeshVerticesInfoToFloatArrays( Mesh mesh, out float[] floatVerticesArray,
  1970. out float[] floatNormalsArray, out float[] floatUV0Array, out float[] floatUV1Array,
  1971. out float[] floatUV2Array, out float[] floatUV3Array, out int trianglesCount )
  1972. {
  1973. floatUV0Array = null;
  1974. floatUV1Array = null;
  1975. floatUV2Array = null;
  1976. floatUV3Array = null;
  1977. List<float> floatVerticesList = new List<float>();
  1978. List<float> floatNormalsList = new List<float>();
  1979. List<float> floatUV0List = new List<float>();
  1980. List<float> floatUV1List = new List<float>();
  1981. List<float> floatUV2List = new List<float>();
  1982. List<float> floatUV3List = new List<float>();
  1983. trianglesCount = 0;
  1984. foreach( SubMesh subMesh in mesh.SubMeshes )
  1985. {
  1986. VertexData vertexData = subMesh.UseSharedVertices ?
  1987. mesh.SharedVertexData : subMesh.VertexData;
  1988. IndexData indexData = subMesh.IndexData;
  1989. trianglesCount += indexData.IndexCount;
  1990. int vertexCount = vertexData.VertexCount;
  1991. VertexDeclaration declaration = vertexData.VertexDeclaration;
  1992. VertexBufferBinding bufferBinding = vertexData.VertexBufferBinding;
  1993. //positions
  1994. {
  1995. int positionIndex = declaration.FindElementBySemantic( VertexElementSemantic.Position );
  1996. VertexElement positionElement = declaration.Elements[ positionIndex ];
  1997. float[] positions = ConvertVertexBufferInfoToFloatArray( bufferBinding, positionElement,
  1998. vertexCount, 3 );
  1999. foreach( float position in positions )
  2000. {
  2001. floatVerticesList.Add( position );
  2002. }
  2003. }
  2004. //normals
  2005. {
  2006. int normalIndex = declaration.FindElementBySemantic( VertexElementSemantic.Normal );
  2007. VertexElement normalElement = declaration.Elements[ normalIndex ];
  2008. float[] normals = ConvertVertexBufferInfoToFloatArray( bufferBinding, normalElement,
  2009. vertexCount, 3 );
  2010. foreach( float normal in normals )
  2011. {
  2012. floatNormalsList.Add( normal );
  2013. }
  2014. }
  2015. //UVs
  2016. {
  2017. foreach( VertexElement element in declaration.Elements )
  2018. {
  2019. if( element.Semantic == VertexElementSemantic.TextureCoordinates )
  2020. {
  2021. float[] floatUVArray = ConvertVertexBufferInfoToFloatArray( bufferBinding,
  2022. element, vertexCount, 2 );
  2023. switch( element.Index )
  2024. {
  2025. case 0:
  2026. for( int i = 0; i < floatUVArray.Length; i += 2 )
  2027. {
  2028. floatUV0List.Add( floatUVArray[ i ] );
  2029. floatUV0List.Add( 1 - floatUVArray[ i + 1 ] );
  2030. }
  2031. break;
  2032. case 1:
  2033. for( int i = 0; i < floatUVArray.Length; i += 2 )
  2034. {
  2035. floatUV0List.Add( floatUVArray[ i ] );
  2036. floatUV0List.Add( 1 - floatUVArray[ i + 1 ] );
  2037. }
  2038. break;
  2039. case 2:
  2040. for( int i = 0; i < floatUVArray.Length; i += 2 )
  2041. {
  2042. floatUV0List.Add( floatUVArray[ i ] );
  2043. floatUV0List.Add( 1 - floatUVArray[ i + 1 ] );
  2044. }
  2045. break;
  2046. case 3:
  2047. for( int i = 0; i < floatUVArray.Length; i += 2 )
  2048. {
  2049. floatUV0List.Add( floatUVArray[ i ] );
  2050. floatUV0List.Add( 1 - floatUVArray[ i + 1 ] );
  2051. }
  2052. break;
  2053. }
  2054. }
  2055. }
  2056. }
  2057. }
  2058. floatVerticesArray = floatVerticesList.ToArray();
  2059. floatNormalsArray = floatNormalsList.ToArray();
  2060. if( floatUV0List.Count > 0 )
  2061. floatUV0Array = floatUV0List.ToArray();
  2062. if( floatUV1List.Count > 0 )
  2063. floatUV1Array = floatUV1List.ToArray();
  2064. if( floatUV2List.Count > 0 )
  2065. floatUV2Array = floatUV2List.ToArray();
  2066. if( floatUV2List.Count > 0 )
  2067. floatUV2Array = floatUV2List.ToArray();
  2068. }
  2069. List<string> GetMeshMaterialNamesList( Mesh mesh )
  2070. {
  2071. List<string> materialNamesList = new List<string>();
  2072. foreach( SubMesh subMesh in mesh.SubMeshes )
  2073. {
  2074. if( !string.IsNullOrEmpty( subMesh.MaterialName ) )
  2075. materialNamesList.Add( subMesh.MaterialName );
  2076. }
  2077. return materialNamesList;
  2078. }
  2079. Dictionary<string, string> GetGeneratedImages( Mesh mesh )
  2080. {
  2081. Dictionary<string, string> generatedImages = new Dictionary<string, string>();
  2082. int filesCount = 0;
  2083. foreach( SubMesh subMesh in mesh.SubMeshes )
  2084. {
  2085. string materialName = subMesh.MaterialName;
  2086. if( !string.IsNullOrEmpty( materialName ) )
  2087. {
  2088. ShaderBaseMaterial material =
  2089. HighLevelMaterialManager.Instance.GetMaterialByName( materialName ) as ShaderBaseMaterial;
  2090. if( material != null )
  2091. {
  2092. if( !string.IsNullOrEmpty( material.EmissionMap.Texture ) )
  2093. {
  2094. string fileName = material.EmissionMap.Texture;
  2095. if( !generatedImages.ContainsKey( fileName ) )
  2096. {
  2097. string imageName = "file" + filesCount.ToString();
  2098. generatedImages.Add( fileName, imageName );
  2099. filesCount++;
  2100. }
  2101. }
  2102. if( !string.IsNullOrEmpty( material.Diffuse1Map.Texture ) )
  2103. {
  2104. string fileName = material.Diffuse1Map.Texture;
  2105. if( !generatedImages.ContainsKey( fileName ) )
  2106. {
  2107. string imageName = "file" + filesCount.ToString();
  2108. generatedImages.Add( fileName, imageName );
  2109. filesCount++;
  2110. }
  2111. }
  2112. if( !string.IsNullOrEmpty( material.Diffuse2Map.Texture ) )
  2113. {
  2114. string fileName = material.Diffuse2Map.Texture;
  2115. if( !generatedImages.ContainsKey( fileName ) )
  2116. {
  2117. string imageName = "file" + filesCount.ToString();
  2118. generatedImages.Add( fileName, imageName );
  2119. filesCount++;
  2120. }
  2121. }
  2122. if( !string.IsNullOrEmpty( material.Diffuse3Map.Texture ) )
  2123. {
  2124. string fileName = material.Diffuse3Map.Texture;
  2125. if( !generatedImages.ContainsKey( fileName ) )
  2126. {
  2127. string imageName = "file" + filesCount.ToString();
  2128. generatedImages.Add( fileName, imageName );
  2129. filesCount++;
  2130. }
  2131. }
  2132. if( !string.IsNullOrEmpty( material.Diffuse4Map.Texture ) )
  2133. {
  2134. string fileName = material.Diffuse4Map.Texture;
  2135. if( !generatedImages.ContainsKey( fileName ) )
  2136. {
  2137. string imageName = "file" + filesCount.ToString();
  2138. generatedImages.Add( fileName, imageName );
  2139. filesCount++;
  2140. }
  2141. }
  2142. if( !string.IsNullOrEmpty( material.SpecularMap.Texture ) )
  2143. {
  2144. string fileName = material.SpecularMap.Texture;
  2145. if( !generatedImages.ContainsKey( fileName ) )
  2146. {
  2147. string imageName = "file" + filesCount.ToString();
  2148. generatedImages.Add( fileName, imageName );
  2149. filesCount++;
  2150. }
  2151. }
  2152. }
  2153. }
  2154. }
  2155. return generatedImages;
  2156. }
  2157. string ConvertFloatArrayToString( float[] floatArray )
  2158. {
  2159. string result = "";
  2160. if( floatArray.Length > 0 )
  2161. result = floatArray[ 0 ].ToString();
  2162. for( int i = 1; i < floatArray.Length; i++ )
  2163. result += " " + floatArray[ i ].ToString( "f6" );
  2164. return result;
  2165. }
  2166. string ConvertIntArrayToString( int[] intArray )
  2167. {
  2168. string result = "";
  2169. if( intArray.Length > 0 )
  2170. result = intArray[ 0 ].ToString();
  2171. for( int i = 1; i < intArray.Length; i++ )
  2172. result += " " + intArray[ i ].ToString();
  2173. return result;
  2174. }
  2175. bool IsEqualFloats( float float1, float float2 )
  2176. {
  2177. return Math.Abs( float1 - float2 ) < 0.0000001f;
  2178. }
  2179. bool IsEqualElements( float[] floatArray, int arrayStartIndex, List<float> floatList,
  2180. int listStartIndex, int stride )
  2181. {
  2182. bool isEqual = true;
  2183. for( int i = 0; isEqual && i < stride; i++ )
  2184. {
  2185. isEqual = IsEqualFloats( floatArray[ arrayStartIndex * stride + i ],
  2186. floatList[ listStartIndex * stride + i ] );
  2187. }
  2188. return isEqual;
  2189. }
  2190. void CompressFloatArray( float[] floatArray, int stride, out float[] compressedFloatArray,
  2191. out int[] floatArrayToCompressedFloatArrayIndices )
  2192. {
  2193. int arrayLength = floatArray.Length;
  2194. int elementsCount = arrayLength / stride;
  2195. List<float> compressedFloatList = new List<float>();
  2196. floatArrayToCompressedFloatArrayIndices = new int[ arrayLength ];
  2197. for( int i = 0; i < elementsCount; i++ )
  2198. {
  2199. int foundedIndex = -1;
  2200. for( int j = 0; j < compressedFloatList.Count / stride; j++ )
  2201. {
  2202. if( IsEqualElements( floatArray, i, compressedFloatList, j, stride ) )
  2203. {
  2204. foundedIndex = j;
  2205. break;
  2206. }
  2207. }
  2208. if( foundedIndex > -1 )
  2209. {
  2210. floatArrayToCompressedFloatArrayIndices[ i ] = foundedIndex;
  2211. }
  2212. else
  2213. {
  2214. floatArrayToCompressedFloatArrayIndices[ i ] = compressedFloatList.Count / stride;
  2215. for( int j = 0; j < stride; j++ )
  2216. compressedFloatList.Add( floatArray[ i * stride + j ] );
  2217. }
  2218. }
  2219. compressedFloatArray = compressedFloatList.ToArray();
  2220. }
  2221. string GetMapBlendingType( ShaderBaseMaterial.DiffuseMapItem.MapBlendingTypes blendingMode )
  2222. {
  2223. if( blendingMode == ShaderBaseMaterial.DiffuseMapItem.MapBlendingTypes.Add )
  2224. return "ADD";
  2225. if( blendingMode == ShaderBaseMaterial.DiffuseMapItem.MapBlendingTypes.AlphaBlend )
  2226. return "BLEND";
  2227. return "MODULATE";
  2228. }
  2229. string GetTexCoordByIndex( ShaderBaseMaterial.TexCoordIndexes texCoord )
  2230. {
  2231. switch( texCoord )
  2232. {
  2233. case ShaderBaseMaterial.TexCoordIndexes.TexCoord0:
  2234. return "CHANNEL0";
  2235. case ShaderBaseMaterial.TexCoordIndexes.TexCoord1:
  2236. return "CHANNEL1";
  2237. case ShaderBaseMaterial.TexCoordIndexes.TexCoord2:
  2238. return "CHANNEL2";
  2239. case ShaderBaseMaterial.TexCoordIndexes.TexCoord3:
  2240. return "CHANNEL3";
  2241. }
  2242. return "CHANNEL0";
  2243. }
  2244. string GetTexCoordNumberByIndex( ShaderBaseMaterial.TexCoordIndexes texCoord )
  2245. {
  2246. switch( texCoord )
  2247. {
  2248. case ShaderBaseMaterial.TexCoordIndexes.TexCoord0:
  2249. return "0";
  2250. case ShaderBaseMaterial.TexCoordIndexes.TexCoord1:
  2251. return "1";
  2252. case ShaderBaseMaterial.TexCoordIndexes.TexCoord2:
  2253. return "2";
  2254. case ShaderBaseMaterial.TexCoordIndexes.TexCoord3:
  2255. return "3";
  2256. }
  2257. return "0";
  2258. }
  2259. void WriteMatrix( XmlTextWriter xmlTextWriter, string sid, Mat4 matrix )
  2260. {
  2261. xmlTextWriter.WriteStartElement( "matrix" );
  2262. xmlTextWriter.WriteAttributeString( "sid", sid );
  2263. xmlTextWriter.WriteString( matrix.ToString() );
  2264. xmlTextWriter.WriteEndElement();
  2265. }
  2266. void WriteFloatSource( XmlTextWriter xmlTextWriter, float[] floatArray, string name,
  2267. int count, string stride, string[] parameters )
  2268. {
  2269. xmlTextWriter.WriteStartElement( "source" );
  2270. xmlTextWriter.WriteAttributeString( "id", name );
  2271. //float_array
  2272. {
  2273. xmlTextWriter.WriteStartElement( "float_array" );
  2274. xmlTextWriter.WriteAttributeString( "id", name + "-array" );
  2275. xmlTextWriter.WriteAttributeString( "count", floatArray.Length.ToString() );
  2276. xmlTextWriter.WriteString( ConvertFloatArrayToString( floatArray ) );
  2277. xmlTextWriter.WriteEndElement();
  2278. }
  2279. //technique_common
  2280. {
  2281. xmlTextWriter.WriteStartElement( "technique_common" );
  2282. //accessor
  2283. {
  2284. xmlTextWriter.WriteStartElement( "accessor" );
  2285. xmlTextWriter.WriteAttributeString( "source", "#" + name + "-array" );
  2286. xmlTextWriter.WriteAttributeString( "count", count.ToString() );
  2287. if( !string.IsNullOrEmpty( stride ) )
  2288. xmlTextWriter.WriteAttributeString( "stride", stride );
  2289. for( int i = 0; i < parameters.Length; i++ )
  2290. {
  2291. //param
  2292. {
  2293. xmlTextWriter.WriteStartElement( "param" );
  2294. xmlTextWriter.WriteAttributeString( "name", parameters[ i ] );
  2295. xmlTextWriter.WriteAttributeString( "type", "float" );
  2296. xmlTextWriter.WriteEndElement();
  2297. }
  2298. }
  2299. xmlTextWriter.WriteEndElement();//accessor
  2300. }
  2301. xmlTextWriter.WriteEndElement();//technique_common
  2302. }
  2303. xmlTextWriter.WriteEndElement();//source
  2304. }
  2305. void WriteInput( XmlTextWriter xmlTextWriter, string semantic, string offset, string source )
  2306. {
  2307. xmlTextWriter.WriteStartElement( "input" );
  2308. xmlTextWriter.WriteAttributeString( "semantic", semantic );
  2309. if( !string.IsNullOrEmpty( offset ) )
  2310. xmlTextWriter.WriteAttributeString( "offset", offset );
  2311. xmlTextWriter.WriteAttributeString( "source", source );
  2312. xmlTextWriter.WriteEndElement();
  2313. }
  2314. bool WriteAsset( XmlTextWriter xmlTextWriter )
  2315. {
  2316. //asset
  2317. {
  2318. xmlTextWriter.WriteStartElement( "asset" );
  2319. //contributor
  2320. xmlTextWriter.WriteStartElement( "contributor" );
  2321. xmlTextWriter.WriteElementString( "authoring_tool",
  2322. "NeoAxis Engine " + EngineVersionInformation.Version );
  2323. xmlTextWriter.WriteEndElement();
  2324. //created
  2325. xmlTextWriter.WriteElementString( "created",
  2326. DateTime.UtcNow.ToString( "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'" ) );
  2327. //modified
  2328. xmlTextWriter.WriteElementString( "modified",
  2329. DateTime.UtcNow.ToString( "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'" ) );
  2330. //revision
  2331. xmlTextWriter.WriteElementString( "revision", "1.4.1" );
  2332. //unit
  2333. xmlTextWriter.WriteStartElement( "unit" );
  2334. xmlTextWriter.WriteAttributeString( "meter", "1" );
  2335. xmlTextWriter.WriteAttributeString( "name", "meter" );
  2336. xmlTextWriter.WriteEndElement();
  2337. //up_axis
  2338. xmlTextWriter.WriteElementString( "up_axis", "Z_UP" );
  2339. xmlTextWriter.WriteEndElement();//asset
  2340. }
  2341. return true;
  2342. }
  2343. bool WriteLibraryImages( XmlTextWriter xmlTextWriter, Dictionary<string, string> generatedImages )
  2344. {
  2345. //library_images
  2346. {
  2347. xmlTextWriter.WriteStartElement( "library_images" );
  2348. foreach( string fileName in generatedImages.Keys )
  2349. {
  2350. string imageName = generatedImages[ fileName ];
  2351. //image
  2352. {
  2353. xmlTextWriter.WriteStartElement( "image" );
  2354. xmlTextWriter.WriteAttributeString( "id", imageName + "-image" );
  2355. xmlTextWriter.WriteAttributeString( "name", imageName );
  2356. //init_from
  2357. xmlTextWriter.WriteElementString( "init_from", "file://" +
  2358. VirtualFileSystem.GetRealPathByVirtual( fileName ) );
  2359. xmlTextWriter.WriteEndElement();
  2360. }
  2361. }
  2362. xmlTextWriter.WriteEndElement();//library_images
  2363. }
  2364. return true;
  2365. }
  2366. bool WriteLibraryMaterials( XmlTextWriter xmlTextWriter, List<string> meshMaterialNamesList )
  2367. {
  2368. //library_materials
  2369. {
  2370. xmlTextWriter.WriteStartElement( "library_materials" );
  2371. foreach( string materialName in meshMaterialNamesList )
  2372. {
  2373. //material
  2374. {
  2375. xmlTextWriter.WriteStartElement( "material" );
  2376. xmlTextWriter.WriteAttributeString( "id", materialName );
  2377. xmlTextWriter.WriteAttributeString( "name", materialName );
  2378. //instance_effect
  2379. {
  2380. xmlTextWriter.WriteStartElement( "instance_effect" );
  2381. xmlTextWriter.WriteAttributeString( "url", "#" + materialName + "-fx" );
  2382. xmlTextWriter.WriteEndElement();
  2383. }
  2384. xmlTextWriter.WriteEndElement();
  2385. }
  2386. }
  2387. xmlTextWriter.WriteEndElement();//library_materials
  2388. }
  2389. return true;
  2390. }
  2391. void WriteFloatNode( XmlTextWriter xmlTextWriter, float value, string sid )
  2392. {
  2393. string floatString = value.ToString( "f6" );
  2394. //float
  2395. xmlTextWriter.WriteStartElement( "float" );
  2396. xmlTextWriter.WriteAttributeString( "sid", sid );
  2397. xmlTextWriter.WriteString( floatString );
  2398. xmlTextWriter.WriteEndElement();
  2399. }
  2400. void WriteColorNode( XmlTextWriter xmlTextWriter, ColorValue color, string sid )
  2401. {
  2402. string colorString = string.Format( "{0:f6} {1:f6} {2:f6} {3:f6}", color.Red, color.Green,
  2403. color.Blue, color.Alpha );
  2404. //color
  2405. xmlTextWriter.WriteStartElement( "color" );
  2406. xmlTextWriter.WriteAttributeString( "sid", sid );
  2407. xmlTextWriter.WriteString( colorString );
  2408. xmlTextWriter.WriteEndElement();
  2409. }
  2410. void WriteTextureAttribute( XmlTextWriter xmlTextWriter, string imageName, string texCoord,
  2411. string texCoordNumber, string blendMode )
  2412. {
  2413. //texture
  2414. {
  2415. xmlTextWriter.WriteStartElement( "texture" );
  2416. xmlTextWriter.WriteAttributeString( "texture", imageName + "-image" );
  2417. xmlTextWriter.WriteAttributeString( "texcoord", texCoord );
  2418. //extra
  2419. {
  2420. xmlTextWriter.WriteStartElement( "extra" );
  2421. //technique
  2422. {
  2423. xmlTextWriter.WriteStartElement( "technique" );
  2424. xmlTextWriter.WriteAttributeString( "profile", "MAYA" );
  2425. //wrapU
  2426. {
  2427. xmlTextWriter.WriteStartElement( "wrapU" );
  2428. xmlTextWriter.WriteAttributeString( "sid", "wrapU" + texCoordNumber );
  2429. xmlTextWriter.WriteString( "TRUE" );
  2430. xmlTextWriter.WriteEndElement();
  2431. }
  2432. //wrapV
  2433. {
  2434. xmlTextWriter.WriteStartElement( "wrapV" );
  2435. xmlTextWriter.WriteAttributeString( "sid", "wrapV" + texCoordNumber );
  2436. xmlTextWriter.WriteString( "TRUE" );
  2437. xmlTextWriter.WriteEndElement();
  2438. }
  2439. //blend_mode
  2440. xmlTextWriter.WriteElementString( "blend_mode", blendMode );
  2441. xmlTextWriter.WriteEndElement();//technique
  2442. }
  2443. xmlTextWriter.WriteEndElement();//extra
  2444. }
  2445. xmlTextWriter.WriteEndElement();//texture
  2446. }
  2447. }
  2448. bool WriteEffectAttribute( XmlTextWriter xmlTextWriter, ShaderBaseMaterial.MapItem map,
  2449. ColorValue color, string sid, Dictionary<string, string> generatedImages )
  2450. {
  2451. xmlTextWriter.WriteStartElement( sid );
  2452. if( !string.IsNullOrEmpty( map.Texture ) )
  2453. {
  2454. string imageName;
  2455. if( !generatedImages.TryGetValue( map.Texture, out imageName ) )
  2456. {
  2457. Error( "Image name wasn't generated for texture \"{0}\"", map.Texture );
  2458. return false;
  2459. }
  2460. //texture
  2461. WriteTextureAttribute( xmlTextWriter, imageName, GetTexCoordByIndex( map.TexCoord ),
  2462. GetTexCoordNumberByIndex( map.TexCoord ), "ADD" );
  2463. }
  2464. else
  2465. {
  2466. WriteColorNode( xmlTextWriter, color, sid );
  2467. }
  2468. xmlTextWriter.WriteEndElement();
  2469. return true;
  2470. }
  2471. bool WriteDiffuseEffectAttribute( XmlTextWriter xmlTextWriter, ShaderBaseMaterial.MapItem mapItem0,
  2472. ShaderBaseMaterial.DiffuseMapItem mapItem1, ShaderBaseMaterial.DiffuseMapItem mapItem2,
  2473. ShaderBaseMaterial.DiffuseMapItem mapItem3, ColorValue color, string sid,
  2474. Dictionary<string, string> generatedImages )
  2475. {
  2476. bool isTextureUsed = false;
  2477. xmlTextWriter.WriteStartElement( sid );
  2478. //Diffuse1Map
  2479. if( !string.IsNullOrEmpty( mapItem0.Texture ) )
  2480. {
  2481. string imageName;
  2482. if( !generatedImages.TryGetValue( mapItem0.Texture, out imageName ) )
  2483. {
  2484. Error( "Image name wasn't generated for texture \"{0}\"", mapItem0.Texture );
  2485. return false;
  2486. }
  2487. //texture
  2488. WriteTextureAttribute( xmlTextWriter, imageName, GetTexCoordByIndex( mapItem0.TexCoord ),
  2489. GetTexCoordNumberByIndex( mapItem0.TexCoord ), "ADD" );
  2490. isTextureUsed = true;
  2491. }
  2492. //Diffuse2Map
  2493. if( !string.IsNullOrEmpty( mapItem1.Texture ) )
  2494. {
  2495. string imageName;
  2496. if( !generatedImages.TryGetValue( mapItem1.Texture, out imageName ) )
  2497. {
  2498. Error( "Image name wasn't generated for texture \"{0}\"", mapItem1.Texture );
  2499. return false;
  2500. }
  2501. //texture
  2502. WriteTextureAttribute( xmlTextWriter, imageName, GetTexCoordByIndex( mapItem1.TexCoord ),
  2503. GetTexCoordNumberByIndex( mapItem1.TexCoord ), GetMapBlendingType( mapItem1.Blending ) );
  2504. isTextureUsed = true;
  2505. }
  2506. //Diffuse3Map
  2507. if( !string.IsNullOrEmpty( mapItem2.Texture ) )
  2508. {
  2509. string imageName;
  2510. if( !generatedImages.TryGetValue( mapItem2.Texture, out imageName ) )
  2511. {
  2512. Error( "Image name wasn't generated for texture \"{0}\"", mapItem2.Texture );
  2513. return false;
  2514. }
  2515. //texture
  2516. WriteTextureAttribute( xmlTextWriter, imageName, GetTexCoordByIndex( mapItem2.TexCoord ),
  2517. GetTexCoordNumberByIndex( mapItem2.TexCoord ), GetMapBlendingType( mapItem2.Blending ) );
  2518. isTextureUsed = true;
  2519. }
  2520. //Diffuse4Map
  2521. if( !string.IsNullOrEmpty( mapItem3.Texture ) )
  2522. {
  2523. string imageName;
  2524. if( !generatedImages.TryGetValue( mapItem3.Texture, out imageName ) )
  2525. {
  2526. Error( "Image name wasn't generated for texture \"{0}\"", mapItem3.Texture );
  2527. return false;
  2528. }
  2529. //texture
  2530. WriteTextureAttribute( xmlTextWriter, imageName, GetTexCoordByIndex( mapItem3.TexCoord ),
  2531. GetTexCoordNumberByIndex( mapItem3.TexCoord ), GetMapBlendingType( mapItem3.Blending ) );
  2532. isTextureUsed = true;
  2533. }
  2534. if( !isTextureUsed )
  2535. WriteColorNode( xmlTextWriter, color, sid );
  2536. xmlTextWriter.WriteEndElement();
  2537. return true;
  2538. }
  2539. bool WriteEffectInfo( XmlTextWriter xmlTextWriter, string materialName,
  2540. Dictionary<string, string> generatedImages )
  2541. {
  2542. ShaderBaseMaterial material = null;
  2543. HighLevelMaterial highLevelMaterial =
  2544. HighLevelMaterialManager.Instance.GetMaterialByName( materialName );
  2545. if( highLevelMaterial != null )
  2546. material = highLevelMaterial as ShaderBaseMaterial;
  2547. //phong
  2548. {
  2549. xmlTextWriter.WriteStartElement( "phong" );
  2550. if( material != null )
  2551. {
  2552. //emission
  2553. if( !WriteEffectAttribute( xmlTextWriter, material.EmissionMap, material.EmissionColor,
  2554. "emission", generatedImages ) )
  2555. {
  2556. return false;
  2557. }
  2558. //ambient
  2559. xmlTextWriter.WriteStartElement( "ambient" );
  2560. WriteColorNode( xmlTextWriter, new ColorValue( 0, 0, 0, 1 ), "ambient" );
  2561. xmlTextWriter.WriteEndElement();
  2562. //diffuse
  2563. if( !WriteDiffuseEffectAttribute( xmlTextWriter, material.Diffuse1Map,
  2564. material.Diffuse2Map, material.Diffuse3Map, material.Diffuse3Map,
  2565. material.DiffuseColor, "diffuse", generatedImages ) )
  2566. {
  2567. return false;
  2568. }
  2569. //specular
  2570. if( !WriteEffectAttribute( xmlTextWriter, material.SpecularMap, material.SpecularColor,
  2571. "specular", generatedImages ) )
  2572. {
  2573. return false;
  2574. }
  2575. //shininess
  2576. xmlTextWriter.WriteStartElement( "shininess" );
  2577. WriteFloatNode( xmlTextWriter, material.SpecularShininess / 3, "shininess" );
  2578. xmlTextWriter.WriteEndElement();
  2579. //reflective
  2580. xmlTextWriter.WriteStartElement( "reflective" );
  2581. WriteColorNode( xmlTextWriter, new ColorValue( 0, 0, 0, 1 ), "reflective" );
  2582. xmlTextWriter.WriteEndElement();
  2583. //reflectivity
  2584. xmlTextWriter.WriteStartElement( "reflectivity" );
  2585. WriteFloatNode( xmlTextWriter, 1, "reflectivity" );
  2586. xmlTextWriter.WriteEndElement();
  2587. //transparent
  2588. xmlTextWriter.WriteStartElement( "transparent" );
  2589. WriteColorNode( xmlTextWriter, new ColorValue( 1, 1, 1, 1 ), "transparent" );
  2590. xmlTextWriter.WriteEndElement();
  2591. //transparency
  2592. xmlTextWriter.WriteStartElement( "transparency" );
  2593. WriteFloatNode( xmlTextWriter, 1 - material.DiffuseColor.Alpha, "transparency" );
  2594. xmlTextWriter.WriteEndElement();
  2595. }
  2596. xmlTextWriter.WriteEndElement();//phong
  2597. }
  2598. return true;
  2599. }
  2600. bool WriteLibraryEffects( XmlTextWriter xmlTextWriter, List<string> meshMaterialNamesList,
  2601. Dictionary<string, string> generatedImages )
  2602. {
  2603. //library_effects
  2604. {
  2605. xmlTextWriter.WriteStartElement( "library_effects" );
  2606. foreach( string materialName in meshMaterialNamesList )
  2607. {
  2608. //effect
  2609. {
  2610. xmlTextWriter.WriteStartElement( "effect" );
  2611. xmlTextWriter.WriteAttributeString( "id", materialName + "-fx" );
  2612. xmlTextWriter.WriteAttributeString( "name", materialName );
  2613. //profile_COMMON
  2614. {
  2615. xmlTextWriter.WriteStartElement( "profile_COMMON" );
  2616. //technique
  2617. {
  2618. xmlTextWriter.WriteStartElement( "technique" );
  2619. xmlTextWriter.WriteAttributeString( "sid", "standard" );
  2620. //phong
  2621. if( !WriteEffectInfo( xmlTextWriter, materialName, generatedImages ) )
  2622. return false;
  2623. xmlTextWriter.WriteEndElement();//technique
  2624. }
  2625. xmlTextWriter.WriteEndElement();//profile_COMMON
  2626. }
  2627. xmlTextWriter.WriteEndElement();//effect
  2628. }
  2629. }
  2630. xmlTextWriter.WriteEndElement();//library_effects
  2631. }
  2632. return true;
  2633. }
  2634. bool WriteLibraryGeometries( XmlTextWriter xmlTextWriter, Mesh mesh )
  2635. {
  2636. //library_geometries
  2637. {
  2638. xmlTextWriter.WriteStartElement( "library_geometries" );
  2639. //geometry
  2640. {
  2641. string meshName = Path.GetFileNameWithoutExtension( mesh.Name );
  2642. xmlTextWriter.WriteStartElement( "geometry" );
  2643. xmlTextWriter.WriteAttributeString( "id", meshName + "-lib" );
  2644. xmlTextWriter.WriteAttributeString( "name", meshName + "Mesh" );
  2645. //mesh
  2646. {
  2647. xmlTextWriter.WriteStartElement( "mesh" );
  2648. float[] floatPositionsArray;
  2649. float[] floatNormalsArray;
  2650. float[] floatUV0Array;
  2651. float[] floatUV1Array;
  2652. float[] floatUV2Array;
  2653. float[] floatUV3Array;
  2654. int trianglesCount;
  2655. ConvertMeshVerticesInfoToFloatArrays( mesh, out floatPositionsArray,
  2656. out floatNormalsArray, out floatUV0Array, out floatUV1Array, out floatUV2Array,
  2657. out floatUV3Array, out trianglesCount );
  2658. float[] compressedPositionsArray;
  2659. float[] compressedNormalsArray;
  2660. float[] compressedUV0Array = null;
  2661. float[] compressedUV1Array = null;
  2662. float[] compressedUV2Array = null;
  2663. float[] compressedUV3Array = null;
  2664. int[] positionsArrayToCompressedPositionsArrayIndices;
  2665. int[] normalsArrayToCompressedNormalsArrayIndices;
  2666. int[] UV0ArrayToCompressedUV0ArrayIndices = null;
  2667. int[] UV1ArrayToCompressedUV1ArrayIndices = null;
  2668. int[] UV2ArrayToCompressedUV2ArrayIndices = null;
  2669. int[] UV3ArrayToCompressedUV3ArrayIndices = null;
  2670. CompressFloatArray( floatPositionsArray, 3, out compressedPositionsArray,
  2671. out positionsArrayToCompressedPositionsArrayIndices );
  2672. CompressFloatArray( floatNormalsArray, 3, out compressedNormalsArray,
  2673. out normalsArrayToCompressedNormalsArrayIndices );
  2674. //source (positions)
  2675. WriteFloatSource( xmlTextWriter, compressedPositionsArray, meshName + "-lib-Position",
  2676. compressedPositionsArray.Length / 3, "3", new string[ 3 ] { "X", "Y", "Z" } );
  2677. //source (normals)
  2678. WriteFloatSource( xmlTextWriter, compressedNormalsArray, meshName + "-lib-Normal0",
  2679. compressedNormalsArray.Length / 3, "3", new string[ 3 ] { "X", "Y", "Z" } );
  2680. if( floatUV0Array != null )
  2681. {
  2682. CompressFloatArray( floatUV0Array, 2, out compressedUV0Array,
  2683. out UV0ArrayToCompressedUV0ArrayIndices );
  2684. //source (UV0)
  2685. WriteFloatSource( xmlTextWriter, compressedUV0Array,
  2686. meshName + "-lib-UV0", compressedUV0Array.Length / 2,
  2687. "2", new string[ 2 ] { "S", "T" } );
  2688. }
  2689. if( floatUV1Array != null )
  2690. {
  2691. CompressFloatArray( floatUV1Array, 2, out compressedUV1Array,
  2692. out UV1ArrayToCompressedUV1ArrayIndices );
  2693. //source (UV1)
  2694. WriteFloatSource( xmlTextWriter, compressedUV1Array,
  2695. meshName + "-lib-UV1", compressedUV1Array.Length / 2,
  2696. "2", new string[ 2 ] { "S", "T" } );
  2697. }
  2698. if( floatUV2Array != null )
  2699. {
  2700. CompressFloatArray( floatUV2Array, 2, out compressedUV2Array,
  2701. out UV2ArrayToCompressedUV2ArrayIndices );
  2702. //source (UV2)
  2703. WriteFloatSource( xmlTextWriter, compressedUV2Array,
  2704. meshName + "-lib-UV2", compressedUV2Array.Length / 2,
  2705. "2", new string[ 2 ] { "S", "T" } );
  2706. }
  2707. if( floatUV3Array != null )
  2708. {
  2709. CompressFloatArray( floatUV3Array, 2, out compressedUV3Array,
  2710. out UV3ArrayToCompressedUV3ArrayIndices );
  2711. //source (UV3)
  2712. WriteFloatSource( xmlTextWriter, compressedUV3Array,
  2713. meshName + "-lib-UV3", compressedUV3Array.Length / 2,
  2714. "2", new string[ 2 ] { "S", "T" } );
  2715. }
  2716. //vertices
  2717. {
  2718. xmlTextWriter.WriteStartElement( "vertices" );
  2719. xmlTextWriter.WriteAttributeString( "id", meshName + "-lib-Vertex" );
  2720. //input
  2721. WriteInput( xmlTextWriter, "POSITION", null, "#" + meshName + "-lib-Position" );
  2722. xmlTextWriter.WriteEndElement();
  2723. }
  2724. int vertexStartIndex = 0;
  2725. foreach( SubMesh subMesh in mesh.SubMeshes )
  2726. {
  2727. int subMeshTrianglesCount = subMesh.IndexData.IndexCount / 3;
  2728. int[] indices = subMesh.IndexData.GetIndices();
  2729. //polygons
  2730. {
  2731. xmlTextWriter.WriteStartElement( "polygons" );
  2732. if( !string.IsNullOrEmpty( subMesh.MaterialName ) )
  2733. xmlTextWriter.WriteAttributeString( "material", subMesh.MaterialName );
  2734. xmlTextWriter.WriteAttributeString( "count",
  2735. subMeshTrianglesCount.ToString() );
  2736. //input (VERTEX)
  2737. WriteInput( xmlTextWriter, "VERTEX", "0", "#" + meshName + "-lib-Vertex" );
  2738. //input (NORMAL)
  2739. WriteInput( xmlTextWriter, "NORMAL", "1", "#" + meshName + "-lib-Normal0" );
  2740. int uvLayersCount = 0;
  2741. if( compressedUV0Array != null )
  2742. {
  2743. int offset = 2 + uvLayersCount;
  2744. uvLayersCount++;
  2745. //input (UV0)
  2746. WriteInput( xmlTextWriter, "TEXCOORD", offset.ToString(), "#" + meshName + "-lib-UV0" );
  2747. }
  2748. if( compressedUV1Array != null )
  2749. {
  2750. int offset = 2 + uvLayersCount;
  2751. uvLayersCount++;
  2752. //input (UV1)
  2753. WriteInput( xmlTextWriter, "TEXCOORD", offset.ToString(), "#" + meshName + "-lib-UV1" );
  2754. }
  2755. if( compressedUV2Array != null )
  2756. {
  2757. int offset = 2 + uvLayersCount;
  2758. uvLayersCount++;
  2759. //input (UV2)
  2760. WriteInput( xmlTextWriter, "TEXCOORD", offset.ToString(), "#" + meshName + "-lib-UV2" );
  2761. }
  2762. if( compressedUV3Array != null )
  2763. {
  2764. int offset = 2 + uvLayersCount;
  2765. uvLayersCount++;
  2766. //input (UV3)
  2767. WriteInput( xmlTextWriter, "TEXCOORD", offset.ToString(), "#" + meshName + "-lib-UV3" );
  2768. }
  2769. for( int triangleIndex = 0; triangleIndex < subMeshTrianglesCount;
  2770. triangleIndex++ )
  2771. {
  2772. int indicesPerVertexCount = uvLayersCount + 2;
  2773. int[] polygonIndices = new int[ indicesPerVertexCount * 3 ];
  2774. for( int triangleVertexIndex = 0; triangleVertexIndex < 3;
  2775. triangleVertexIndex++ )
  2776. {
  2777. int vertexIndex = vertexStartIndex + indices[ triangleIndex * 3 +
  2778. triangleVertexIndex ];
  2779. int positionIndex = positionsArrayToCompressedPositionsArrayIndices[
  2780. vertexIndex ];
  2781. int normalIndex = normalsArrayToCompressedNormalsArrayIndices[
  2782. vertexIndex ];
  2783. polygonIndices[ indicesPerVertexCount * triangleVertexIndex + 0 ] =
  2784. positionIndex;
  2785. polygonIndices[ indicesPerVertexCount * triangleVertexIndex + 1 ] =
  2786. normalIndex;
  2787. int uvIndex = 0;
  2788. if( compressedUV0Array != null )
  2789. {
  2790. polygonIndices[ indicesPerVertexCount * triangleVertexIndex +
  2791. uvIndex + 2 ] =
  2792. UV0ArrayToCompressedUV0ArrayIndices[ vertexIndex ];
  2793. uvIndex++;
  2794. }
  2795. if( compressedUV1Array != null )
  2796. {
  2797. polygonIndices[ indicesPerVertexCount * triangleVertexIndex +
  2798. uvIndex + 2 ] =
  2799. UV1ArrayToCompressedUV1ArrayIndices[ vertexIndex ];
  2800. uvIndex++;
  2801. }
  2802. if( compressedUV2Array != null )
  2803. {
  2804. polygonIndices[ indicesPerVertexCount * triangleVertexIndex +
  2805. uvIndex + 2 ] =
  2806. UV2ArrayToCompressedUV2ArrayIndices[ vertexIndex ];
  2807. uvIndex++;
  2808. }
  2809. if( compressedUV3Array != null )
  2810. {
  2811. polygonIndices[ indicesPerVertexCount * triangleVertexIndex +
  2812. uvIndex + 2 ] =
  2813. UV3ArrayToCompressedUV3ArrayIndices[ vertexIndex ];
  2814. uvIndex++;
  2815. }
  2816. }
  2817. string polygonString = ConvertIntArrayToString( polygonIndices );
  2818. //p
  2819. {
  2820. xmlTextWriter.WriteStartElement( "p" );
  2821. xmlTextWriter.WriteString( polygonString );
  2822. xmlTextWriter.WriteEndElement();
  2823. }
  2824. }
  2825. xmlTextWriter.WriteEndElement();//polygons
  2826. }
  2827. vertexStartIndex += subMesh.VertexData.VertexCount;
  2828. }
  2829. xmlTextWriter.WriteEndElement();//mesh
  2830. }
  2831. xmlTextWriter.WriteEndElement();//geometry
  2832. }
  2833. xmlTextWriter.WriteEndElement();//library_geometries
  2834. }
  2835. return true;
  2836. }
  2837. bool WriteLibraryVisualScenes( XmlTextWriter xmlTextWriter, Mesh mesh,
  2838. List<string> meshMaterialNamesList )
  2839. {
  2840. //library_visual_scenes
  2841. {
  2842. xmlTextWriter.WriteStartElement( "library_visual_scenes" );
  2843. //visual_scene
  2844. {
  2845. xmlTextWriter.WriteStartElement( "visual_scene" );
  2846. xmlTextWriter.WriteAttributeString( "id", "RootNode" );
  2847. xmlTextWriter.WriteAttributeString( "name", "RootNode" );
  2848. //node
  2849. {
  2850. xmlTextWriter.WriteStartElement( "node" );
  2851. string meshName = Path.GetFileNameWithoutExtension( mesh.Name );
  2852. xmlTextWriter.WriteAttributeString( "id", meshName );
  2853. xmlTextWriter.WriteAttributeString( "name", meshName );
  2854. //matrix
  2855. WriteMatrix( xmlTextWriter, "matrix", Mat4.Identity );
  2856. //instance_geometry
  2857. {
  2858. xmlTextWriter.WriteStartElement( "instance_geometry" );
  2859. xmlTextWriter.WriteAttributeString( "url", "#" + meshName + "-lib" );
  2860. if( meshMaterialNamesList.Count > 0 )
  2861. {
  2862. //bind_material
  2863. {
  2864. xmlTextWriter.WriteStartElement( "bind_material" );
  2865. //technique_common
  2866. {
  2867. xmlTextWriter.WriteStartElement( "technique_common" );
  2868. foreach( string materialName in meshMaterialNamesList )
  2869. {
  2870. //instance_material
  2871. {
  2872. xmlTextWriter.WriteStartElement( "instance_material" );
  2873. xmlTextWriter.WriteAttributeString( "symbol", materialName );
  2874. xmlTextWriter.WriteAttributeString( "target",
  2875. "#" + materialName );
  2876. xmlTextWriter.WriteEndElement();
  2877. }
  2878. }
  2879. xmlTextWriter.WriteEndElement(); //technique_common
  2880. }
  2881. xmlTextWriter.WriteEndElement();//bind_material
  2882. }
  2883. }
  2884. xmlTextWriter.WriteEndElement();//instance_geometry
  2885. }
  2886. xmlTextWriter.WriteEndElement();//node
  2887. }
  2888. xmlTextWriter.WriteEndElement();//visual_scene
  2889. }
  2890. xmlTextWriter.WriteEndElement();//library_visual_scenes
  2891. }
  2892. return true;
  2893. }
  2894. protected override bool Save( Mesh mesh, string realFileName )
  2895. {
  2896. Dictionary<string, string> generatedImages = GetGeneratedImages( mesh );
  2897. List<string> meshMaterialNamesList = GetMeshMaterialNamesList( mesh );
  2898. XmlTextWriter xmlTextWriter = new XmlTextWriter( realFileName, System.Text.Encoding.UTF8 );
  2899. {
  2900. xmlTextWriter.Formatting = Formatting.Indented;
  2901. xmlTextWriter.Indentation = 1;
  2902. xmlTextWriter.IndentChar = '\t';
  2903. xmlTextWriter.WriteStartDocument();
  2904. xmlTextWriter.WriteStartElement( "COLLADA" );
  2905. xmlTextWriter.WriteAttributeString( "xmlns", "http://www.collada.org/2005/11/COLLADASchema" );
  2906. xmlTextWriter.WriteAttributeString( "version", "1.4.1" );
  2907. if( !WriteAsset( xmlTextWriter ) )
  2908. return false;
  2909. if( !WriteLibraryImages( xmlTextWriter, generatedImages ) )
  2910. return false;
  2911. if( !WriteLibraryMaterials( xmlTextWriter, meshMaterialNamesList ) )
  2912. return false;
  2913. if( !WriteLibraryEffects( xmlTextWriter, meshMaterialNamesList, generatedImages ) )
  2914. return false;
  2915. if( !WriteLibraryGeometries( xmlTextWriter, mesh ) )
  2916. return false;
  2917. if( !WriteLibraryVisualScenes( xmlTextWriter, mesh, meshMaterialNamesList ) )
  2918. return false;
  2919. //scene
  2920. {
  2921. xmlTextWriter.WriteStartElement( "scene" );
  2922. //instance_visual_scene
  2923. xmlTextWriter.WriteStartElement( "instance_visual_scene" );
  2924. xmlTextWriter.WriteAttributeString( "url", "#RootNode" );
  2925. xmlTextWriter.WriteEndElement();
  2926. xmlTextWriter.WriteEndElement();
  2927. }
  2928. xmlTextWriter.WriteEndElement();
  2929. xmlTextWriter.WriteEndDocument();
  2930. try
  2931. {
  2932. xmlTextWriter.Flush();
  2933. }
  2934. catch( Exception ex )
  2935. {
  2936. Error( ex.Message );
  2937. return false;
  2938. }
  2939. xmlTextWriter.Close();
  2940. }
  2941. return true;
  2942. }
  2943. }
  2944. }