/home/lindsay/xeolabs/xeogl-next/xeogl/src/objects/mesh.js
API Docs for:

File: /home/lindsay/xeolabs/xeogl-next/xeogl/src/objects/mesh.js

  1. /**
  2. A **Mesh** is an {{#crossLink "Object"}}{{/crossLink}} that represents a drawable 3D primitive.
  3.  
  4. ## Overview
  5.  
  6. * A Mesh represents a WebGL draw call.
  7. * Each Mesh has six components: {{#crossLink "Geometry"}}{{/crossLink}} for shape, {{#crossLink "Material"}}{{/crossLink}}
  8. for normal rendered appearance, three {{#crossLink "EmphasisMaterial"}}EmphasisMaterials{{/crossLink}} for ghosted, highlighted and selected effects,
  9. and {{#crossLink "EdgeMaterial"}}{{/crossLink}} for rendering emphasised edges.
  10. * By default, Meshes in the same Scene share the same global scene flyweight instances of those components among themselves. The default
  11. component instances are provided by the {{#crossLink "Scene"}}{{/crossLink}}'s {{#crossLink "Scene/geometry:property"}}{{/crossLink}},
  12. {{#crossLink "Scene/material:property"}}{{/crossLink}}, {{#crossLink "Scene/ghostMaterial:property"}}{{/crossLink}}, {{#crossLink "Scene/highlightMaterial:property"}}{{/crossLink}},
  13. {{#crossLink "Scene/selectedMaterial:property"}}{{/crossLink}} and {{#crossLink "Scene/edgeMaterial:property"}}{{/crossLink}} properties.
  14. * A Mesh with all defaults is a white unit-sized box centered at the World-space origin.
  15. * Customize your Meshes by attaching your own instances of those component types, to override the defaults as needed.
  16. * For best performance, reuse as many of the same component instances among your Meshes as possible.
  17. * Use {{#crossLink "Group"}}Group{{/crossLink}} components to organize Meshes into hierarchies, if required.
  18.  
  19. This page covers functionality specific to the Mesh component, while {{#crossLink "Object"}}{{/crossLink}} covers generic
  20. functionality inherited from the base class.
  21.  
  22. ## Usage
  23.  
  24. * [Creating a Mesh](#creating-a-mesh)
  25. * [Creating hierarchies](#creating-hierarchies)
  26. * [Controlling visibility](#controlling-visibility)
  27. * [Controlling clipping](#controlling-clipping)
  28. * [Controlling rendering order](#controlling-rendering-order)
  29. * [Geometry](#geometry)
  30. * [Material](#material)
  31. * [Transforming](#transforming)
  32. * [Ghosting](#ghosting)
  33. * [Highlighting](#highlighting)
  34. * [Outlining](#outlining)
  35. * [Local-space boundary](#local-space-boundary)
  36. * [World-space boundary](#world-space-boundary)
  37. * [Skyboxing](#skyboxing)
  38. * [Billboarding](#billboarding)
  39. * [Shadows](#shadows) TODO
  40.  
  41. ### Creating a Mesh
  42.  
  43. Creating a minimal Mesh that has all the default components:
  44.  
  45. <img src="../../assets/images/screenshots/Scene/defaultMesh.png"></img>
  46.  
  47. ````javascript
  48. var mesh = new xeogl.Mesh(); // A white unit-sized box centered at the World-space origin
  49. ````
  50.  
  51. Since our Mesh has all the default components, we can get those off either the Mesh or its Scene:
  52.  
  53. ````javascript
  54. mesh.material.diffuse = [1.0, 0.0, 0.0]; // This is the same Material component...
  55. mesh.scene.material.diffuse = [1.0, 0.0, 0.0]; // ...as this one.
  56. ````
  57.  
  58. In practice, we would provide (at least) our own Geometry and Material for the Mesh:
  59.  
  60. <a href="../../examples/#geometry_primitives_teapot"><img src="../../assets/images/screenshots/Scene/teapot.png"></img></a>
  61.  
  62. ````javascript
  63. var mesh = new xeogl.Mesh({
  64. geometry: new xeogl.TeapotGeometry(),
  65. material: new xeogl.MetallicMaterial({
  66. baseColor: [1.0, 1.0, 1.0]
  67. })
  68. });
  69. ````
  70.  
  71. ### Creating hierarchies
  72.  
  73. In xeogl we represent an object hierarchy as a tree of {{#crossLink "Object"}}Objects{{/crossLink}} in which
  74. the leaf Objects are Meshes. In an Object tree, an operation on an Object is recursively applied to sub-Objects, down
  75. to the Meshes at the leaves.
  76.  
  77. See {{#crossLink "Object"}}{{/crossLink}} for information on organizing Meshes hierarchically.
  78.  
  79. ### Controlling visibility
  80.  
  81. Show or hide a Mesh by setting its {{#crossLink "Mesh/visible:property"}}{{/crossLink}} property:
  82.  
  83. ````javascript
  84. mesh.visible = false; // Hide
  85. mesh.visible = true; // Show (default)
  86. ````
  87.  
  88. This property is inherited from {{#crossLink "Object/visible:property"}}Object{{/crossLink}}.
  89.  
  90. ### Controlling clipping
  91.  
  92. By default, a Mesh will be clipped by the
  93. Scene's {{#crossLink "Scene/clips:property"}}clipping planes{{/crossLink}}.
  94.  
  95. Make a Mesh unclippable by setting its {{#crossLink "Mesh/clippable:property"}}{{/crossLink}} property false:
  96.  
  97. ````javascript
  98. mesh.clippable = false; // Default is true
  99. ````
  100.  
  101. ### Controlling rendering order
  102.  
  103. Control the order in which a Mesh is rendered relative to others by setting its {{#crossLink "Mesh/layer:property"}}{{/crossLink}}
  104. property. You would normally do this when you need to ensure that transparent Meshes are rendered in back-to-front order for correct alpha blending.
  105.  
  106. Assigning our Mesh to layer 0 (all Meshes are in layer 0 by default):
  107.  
  108. ````javascript
  109. mesh.layer = 0;
  110. ````
  111.  
  112. Create another Mesh in a higher layer, that will get rendered after layer 0:
  113.  
  114. ````javascript
  115. var mesh2 = new xeogl.Mesh({
  116. geometry: new xeogl.Sphere(),
  117. layer: 1
  118. });
  119. ````
  120.  
  121. ### Geometry
  122.  
  123. A Mesh has a {{#crossLink "Geometry"}}{{/crossLink}} which describes its shape. When we don't provide a Geometry,
  124. a Mesh will automatically get its {{#crossLink "Scene"}}{{/crossLink}}'s {{#crossLink "Scene/geometry:property"}}{{/crossLink}} by default.
  125.  
  126. Creating a Mesh with its own Geometry:
  127.  
  128. ````javascript
  129. var mesh = new xeogl.Mesh({
  130. geometry: new xeogl.TeapotGeometry()
  131. });
  132. ````
  133.  
  134. Getting geometry arrays:
  135.  
  136. ````javascript
  137. ver geometry = mesh.geometry;
  138.  
  139. var primitive = geometry.primitive; // Default is "triangles"
  140. var positions = geometry.positions; // Local-space vertex positions
  141. var normals = geometry.normals; // Local-space vertex Normals
  142. var uv = geometry.uv; // UV coordinates
  143. var indices = mesh.geometry.indices; // Vertex indices for pimitives
  144. ````
  145.  
  146. The Mesh also has a convenience property which provides the vertex positions in World-space, ie. after they have been
  147. transformed by the Mesh's {{#crossLink "Object/worldMatrix:property"}}{{/crossLink}}:
  148.  
  149. ````javascript
  150. // These are internally generated on-demand and cached. To free the cached
  151. // vertex World positions when you're done with them, set this property to null or undefined
  152. var worldPositions = mesh.worldPositions;
  153. ````
  154.  
  155. ### Material
  156.  
  157. A Mesh has a {{#crossLink "Material"}}{{/crossLink}}, which describes its appearance. When we don't provide it with
  158. a Material, it will automatically get its {{#crossLink "Scene"}}{{/crossLink}}'s {{#crossLink "Scene/material:property"}}{{/crossLink}} by default.
  159.  
  160. Creating a Mesh with its own custom {{#crossLink "Geometry"}}{{/crossLink}} and {{#crossLink "MetallicMaterial"}}{{/crossLink}}:
  161.  
  162. ````javascript
  163. var mesh = new xeogl.Mesh({
  164. geometry: new xeogl.TeapotGeometry(),
  165. material: new xeogl.MetallicMaterial({
  166. baseColor: [0.0, 0.0, 1.0],
  167. metallic: 1.0,
  168. roughness: 1.0,
  169. emissive: [0.0, 0.0, 0.0],
  170. alpha: 1.0
  171. })
  172. });
  173. ````
  174.  
  175. Animating the {{#crossLink "MetallicMaterial"}}{{/crossLink}}'s diffuse color - making the Mesh rapidly pulse red:
  176.  
  177. ````javascript
  178. mesh.scene.on("tick", function(e) {
  179. var t = e.time - e.startTime; // Millisecs
  180. mesh.material.baseColor = [0.5 + Math.sin(t * 0.01), 0.0, 0.0]; // RGB
  181. });
  182. ````
  183.  
  184. ### Transforming
  185.  
  186. A Mesh can be positioned within the World-space coordinate system.
  187.  
  188. See {{#crossLink "Object"}}{{/crossLink}}.
  189.  
  190. ### Ghosting
  191.  
  192. Ghost a Mesh by setting its {{#crossLink "Mesh/ghosted:property"}}{{/crossLink}} property true. The Mesh's
  193. {{#crossLink "Mesh/ghostMaterial:property"}}{{/crossLink}} property holds the {{#crossLink "EmphasisMaterial"}}{{/crossLink}}
  194. that controls its appearance while ghosted.
  195.  
  196. When we don't provide it with a EmphasisMaterial, the Mesh will automatically get its Scene's {{#crossLink "Scene/ghostMaterial:property"}}{{/crossLink}}
  197. by default.
  198.  
  199. In the example below, we'll create a ghosted Mesh with its own EmphasisMaterial for ghosted appearance:
  200.  
  201. <a href="../../examples/#effects_ghost"><img src="../../assets/images/screenshots/EmphasisMaterial/teapot.png"></img></a>
  202.  
  203. ````javascript
  204. var mesh = new xeogl.Mesh({
  205. geometry: new xeogl.TeapotGeometry(),
  206. material: new xeogl.PhongMaterial({
  207. diffuse: [0.2, 0.2, 1.0]
  208. }),
  209. ghostMaterial: new xeogl.EmphasisMaterial({
  210. edges: true,
  211. edgeColor: [0.2, 1.0, 0.2],
  212. edgeAlpha: 1.0,
  213. edgeWidth: 2,
  214. vertices: true,
  215. vertexColor: [0.6, 1.0, 0.6],
  216. vertexAlpha: 1.0,
  217. vertexSize: 8,
  218. fill: true,
  219. fillColor: [0, 0, 0],
  220. fillAlpha: 0.7
  221. }),
  222. ghosted: true
  223. });
  224. ````
  225.  
  226. #### Examples
  227.  
  228. * [Ghosted teapot](../../examples/#effects_demo_hoverToGhost)
  229.  
  230. ### Highlighting
  231.  
  232. Highlight a Mesh by setting its {{#crossLink "Mesh/highlighted:property"}}{{/crossLink}} property true. The Mesh's
  233. {{#crossLink "Mesh/highlightMaterial:property"}}{{/crossLink}} property holds the {{#crossLink "EmphasisMaterial"}}{{/crossLink}}
  234. that controls its appearance while highlighted.
  235.  
  236. When we don't provide it with a EmphasisMaterial for highlighting, it will automatically get its Scene's {{#crossLink "Scene/highlightMaterial:property"}}{{/crossLink}}
  237. by default.
  238.  
  239. In the example below, we'll create a highlighted Mesh with its own EmphasisMaterial for highlighted appearance:
  240.  
  241. <a href="../../examples/#effects_highlight"><img src="../../assets/images/screenshots/EmphasisMaterial/teapotHighlighted.png"></img></a>
  242.  
  243. ````javascript
  244. var mesh = new xeogl.Mesh({
  245. geometry: new xeogl.TeapotGeometry(),
  246. material: new xeogl.PhongMaterial({
  247. diffuse: [0.2, 0.2, 1.0]
  248. }),
  249. highlightMaterial: new xeogl.EmphasisMaterial({
  250. color: [1.0, 1.0, 0.0],
  251. alpha: 0.6
  252. }),
  253. highlighted: true
  254. });
  255. ````
  256.  
  257. #### Examples
  258.  
  259. * [Ghost and highlight effects](../../examples/#effects_demo_hoverToHighlight)
  260.  
  261. ### Selecting
  262.  
  263. Make a Mesh appear selected by setting its {{#crossLink "Mesh/selected:property"}}{{/crossLink}} property true. The Mesh's
  264. {{#crossLink "Mesh/selectedMaterial:property"}}{{/crossLink}} property holds the {{#crossLink "EmphasisMaterial"}}{{/crossLink}}
  265. that controls its appearance while selected.
  266.  
  267. When we don't provide it with a EmphasisMaterial for selecting, it will automatically get its Scene's {{#crossLink "Scene/selectMaterial:property"}}{{/crossLink}}
  268. by default.
  269.  
  270. In the example below, we'll create a selected Mesh with its own EmphasisMaterial for selection appearance:
  271.  
  272. <a href="../../examples/#effects_select"><img src="../../assets/images/screenshots/EmphasisMaterial/teapotSelected.png"></img></a>
  273.  
  274. ````javascript
  275. var mesh = new xeogl.Mesh({
  276. geometry: new xeogl.TeapotGeometry(),
  277. material: new xeogl.PhongMaterial({
  278. diffuse: [0.2, 0.2, 1.0]
  279. }),
  280. selectMaterial: new xeogl.EmphasisMaterial({
  281. color: [1.0, 1.0, 0.0],
  282. alpha: 0.6
  283. }),
  284. selected: true
  285. });
  286. ````
  287.  
  288. #### Examples
  289.  
  290. * [Ghost and select effects](../../examples/#effects_demo_gearbox)
  291.  
  292.  
  293. ### Edges
  294.  
  295. Emphasise a Mesh's edges by setting its {{#crossLink "Mesh/edges:property"}}{{/crossLink}} property true. The Mesh's
  296. {{#crossLink "Mesh/edgeMaterial:property"}}{{/crossLink}} property holds the {{#crossLink "EdgeMaterial"}}{{/crossLink}}
  297. that controls the appearance of the edges while they are emphasized.
  298.  
  299. When we don't provide it with an EdgeMaterial, the Mesh will automatically get its Scene's {{#crossLink "Scene/edgeMaterial:property"}}{{/crossLink}}
  300. by default.
  301.  
  302. In the example below, we'll create a edges Mesh with its own EdgeMaterial for edges appearance:
  303.  
  304. <a href="../../examples/#effects_ghost"><img src="../../assets/images/screenshots/EdgeMaterial/teapot.png"></img></a>
  305.  
  306. ````javascript
  307. var mesh = new xeogl.Mesh({
  308. geometry: new xeogl.TeapotGeometry(),
  309. material: new xeogl.PhongMaterial({
  310. diffuse: [0.2, 0.2, 1.0]
  311. }),
  312. edgeMaterial: new xeogl.EdgeMaterial({
  313. edgeColor: [0.2, 1.0, 0.2],
  314. edgeAlpha: 1.0,
  315. edgeWidth: 2
  316. }),
  317. edges: true
  318. });
  319. ````
  320.  
  321. ### Outlining
  322.  
  323. Outline a Mesh by setting its {{#crossLink "Mesh/outlined:property"}}{{/crossLink}} property true. The Mesh's
  324. {{#crossLink "Mesh/outlineMaterial:property"}}{{/crossLink}} property holds the {{#crossLink "OutlineMaterial"}}{{/crossLink}}
  325. that controls its appearance while outlined.
  326.  
  327. When we don't provide it with an {{#crossLink "OutlineMaterial"}}{{/crossLink}}, it will automatically get its Scene's
  328. {{#crossLink "Scene/outlineMaterial:property"}}{{/crossLink}} by default.
  329.  
  330. In the example below, we'll create a outlined Mesh with its own {{#crossLink "OutlineMaterial"}}{{/crossLink}}:
  331.  
  332. <a href="../../examples/#effects_outline"><img src="../../assets/images/screenshots/OutlineMaterial/teapot.png"></img></a>
  333.  
  334. ````javascript
  335. var mesh = new xeogl.Mesh({
  336. geometry: new xeogl.TeapotGeometry(),
  337. material: new xeogl.PhongMaterial({
  338. diffuse: [0.2, 0.2, 1.0]
  339. }),
  340. outlineMaterial: new xeogl.OutlineMaterial({
  341. color: [1.0, 1.0, 0.0],
  342. alpha: 0.6,
  343. width: 5
  344. }),
  345. outlined: true
  346. });
  347. ````
  348.  
  349. ### Local-space boundary
  350.  
  351. We can query a Mesh's Local-space boundary at any time, getting it as either an axis-aligned bounding box (AABB) or
  352. an object-aligned bounding box (OBB).
  353.  
  354. The Local-space AABB and OBB belong to the Mesh's {{#crossLink "Geometry"}}{{/crossLink}}.
  355.  
  356. Getting the Local-space AABB:
  357.  
  358. ````
  359. var aabb = mesh.geometry.aabb; // [xmin, ymin, zmin, xmax, ymax, zmax]
  360. ````
  361.  
  362. Getting the Local-space OBB:
  363.  
  364. ```` javascript
  365. var obb = mesh.geometry.obb; // Flat array containing eight 3D corner vertices of a box
  366. ````
  367.  
  368. #### Examples
  369.  
  370. * [Local-space Geometry AABB](../../examples/#boundaries_geometry_aabb)
  371. * [Local-space Geometry OBB](../../examples/#boundaries_geometry_obb)
  372.  
  373. ### World-space boundary
  374.  
  375. We can query a Mesh's World-space boundary at any time, getting it as an axis-aligned bounding box (AABB).
  376.  
  377. The World-space AABB is the boundary of the Mesh's {{#crossLink "Geometry"}}{{/crossLink}} after transformation by the
  378. Mesh's {{#crossLink "Object/worldMatrix:property"}}{{/crossLink}} and the {{#crossLink "Camera"}}{{/crossLink}}'s
  379. {{#crossLink "Camera/matrix:property"}}{{/crossLink}}.
  380.  
  381. Getting the World-space boundary AABB:
  382.  
  383. ````javascript
  384. var aabb = mesh.aabb; // [xmin, ymin, zmin, xmax, ymax, zmax]
  385. ````
  386.  
  387. Subscribing to updates of the World-space boundary, which occur after each update to the
  388. Mesh's {{#crossLink "Object/worldMatrix:property"}}{{/crossLink}} or the {{#crossLink "Camera"}}{{/crossLink}}:
  389.  
  390. ````javascript
  391. mesh.on("boundary", function() {
  392. var aabb = mesh.aabb;
  393. var obb = mesh.obb;
  394. });
  395. ````
  396.  
  397. The {{#crossLink "Scene"}}{{/crossLink}} also has a {{#crossLink "Scene/getAABB:method"}}Scene#getAABB(){{/crossLink}}, which returns
  398. the collective World-space AABBs of the {{#crossLink "Object"}}Objects{{/crossLink}} with the given IDs:
  399.  
  400. ````JavaScript
  401. var scene = mesh.scene;
  402.  
  403. scene.getAABB(); // Gets collective boundary of all meshes in the scene
  404. scene.getAABB("saw"); // Gets collective boundary of all meshes in a model
  405. scene.getAABB(["saw", "gearbox"]); // Gets collective boundary of all meshes in two models
  406. scene.getAABB("saw#0.1"); // Get boundary of a mesh
  407. scene.getAABB(["saw#0.1", "saw#0.2"]); // Get collective boundary of two meshes
  408. ````
  409.  
  410. #### Excluding from boundary calculations
  411.  
  412. The {{#crossLink "Scene/aabb:property"}}Scene aabb{{/crossLink}}
  413. and parent {{#crossLink "Object/aabb:property"}}Object{{/crossLink}}'s {{#crossLink "Object/aabb:property"}}aabb{{/crossLink}}
  414. properties provide AABBs that dynamically include the AABB of all contained Meshes, except those Meshes that have
  415. their {{#crossLink "Mesh/collidable:property"}}collidable{{/crossLink}} properties set ````false````.
  416.  
  417. Toggle that inclusion like so:
  418.  
  419. ````javascript
  420. mesh.collidable = false; // Exclude mesh from calculation of its Scene/Model boundary
  421. mesh.collidable = true; // Include mesh in calculation of its Scene/Model boundary
  422. ````
  423. Setting this false is useful when a Mesh represents some element, such as a control gizmo, that you don't want to
  424. contribute to the {{#crossLink "Scene"}}Scene{{/crossLink}} or parent {{#crossLink "Object"}}{{/crossLink}}'s AABB. It
  425. also helps performance, since boundaries will not need dynamically re-calculated whenever the Mesh's boundary changes after
  426. a {{#crossLink "Object/worldMatrix:property"}}{{/crossLink}} or {{#crossLink "Camera"}}{{/crossLink}} update.
  427.  
  428. #### Examples
  429.  
  430. * [World-space Mesh AABB](../../examples/#boundaries_mesh_aabb)
  431. * [World-space Mesh OBB](../../examples/#boundaries_mesh_obb)
  432.  
  433. ### Skyboxing
  434.  
  435. A Mesh has a {{#crossLink "Mesh/stationary:property"}}{{/crossLink}} property
  436. that will cause it to never translate with respect to the viewpoint.
  437.  
  438. This is useful for using Meshes as skyboxes, like this:
  439.  
  440. ````javascript
  441. new xeogl.Mesh({
  442.  
  443. geometry: new xeogl.BoxGeometry({
  444. xSize: 1000,
  445. ySize: 1000,
  446. zSize: 1000
  447. }),
  448.  
  449. material: new xeogl.PhongMaterial({
  450. diffuseMap: new xeogl.Texture({
  451. src: "textures/diffuse/uvGrid2.jpg"
  452. })
  453. }),
  454.  
  455. stationary: true // Locks position with respect to viewpoint
  456. });
  457. ````
  458.  
  459. #### Examples
  460.  
  461. * [Skybox component](../../examples/#skyboxes_skybox)
  462. * [Custom skybox](../../examples/#skyboxes_skybox_custom)
  463.  
  464. ### Billboarding
  465.  
  466. A Mesh has a {{#crossLink "Mesh/billboard:property"}}{{/crossLink}} property
  467. that can make it behave as a billboard.
  468.  
  469. Two billboard types are supported:
  470.  
  471. * **Spherical** billboards are free to rotate their Meshes in any direction and always face the {{#crossLink "Camera"}}{{/crossLink}} perfectly.
  472. * **Cylindrical** billboards rotate their Meshes towards the {{#crossLink "Camera"}}{{/crossLink}}, but only about the Y-axis.
  473.  
  474. Note that scaling transformations to have no effect on billboarded Meshes.
  475.  
  476. The example below shows a box that remains rotated directly towards the viewpoint, using spherical billboarding:
  477.  
  478. ````javascript
  479. new xeogl.Mesh({
  480.  
  481. geometry: new xeogl.BoxGeometry(),
  482.  
  483. material: new xeogl.PhongMaterial({
  484. diffuseMap: new xeogl.Texture({
  485. src: "textures/diffuse/uvGrid2.jpg"
  486. })
  487. }),
  488.  
  489. billboard: "spherical" // Or "cylindrical"
  490. });
  491. ````
  492.  
  493. #### Examples
  494.  
  495. * [Spherical billboards](../../examples/#billboards_spherical)
  496. * [Cylindrical billboards](../../examples/#billboards_cylindrical)
  497. * [Clouds using billboards](../../examples/#billboards_spherical_clouds)
  498.  
  499.  
  500. ### Shadows
  501.  
  502. [Work-in-progress]
  503.  
  504. @class Mesh
  505. @module xeogl
  506. @submodule objects
  507. @constructor
  508. @param [owner] {Component} Owner component. When destroyed, the owner will destroy this component as well. Creates this component within the default {{#crossLink "Scene"}}{{/crossLink}} when omitted.
  509. @param [cfg] {*} Configs
  510. @param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}}, generated automatically when omitted.
  511. @param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this Mesh.
  512. @param [cfg.entityType] {String} Optional entity classification when using within a semantic data model. See the {{#crossLink "Object"}}{{/crossLink}} documentation for usage.
  513. @param [cfg.parent] {Object} The parent.
  514. @param [cfg.position=[0,0,0]] {Float32Array} The Mesh's local 3D position.
  515. @param [cfg.scale=[1,1,1]] {Float32Array} The Mesh's local scale.
  516. @param [cfg.rotation=[0,0,0]] {Float32Array} The Mesh's local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.
  517. @param [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] {Float32Array} The Mesh's local modelling transform matrix. Overrides the position, scale and rotation parameters.
  518.  
  519. @param [cfg.geometry] {Geometry} Defines shape. Must be within the same {{#crossLink "Scene"}}Scene{{/crossLink}} as this Mesh. Defaults to the
  520. parent {{#crossLink "Scene"}}Scene{{/crossLink}}'s default instance, {{#crossLink "Scene/geometry:property"}}geometry{{/crossLink}}, which is a 2x2x2 box.
  521. @param [cfg.material] {Material} Defines normal rendered appearance. Must be within the same {{#crossLink "Scene"}}Scene{{/crossLink}} as this Mesh. Defaults to the
  522. parent {{#crossLink "Scene"}}Scene{{/crossLink}}'s default instance, {{#crossLink "Scene/material:property"}}material{{/crossLink}}.
  523. @param [cfg.outlineMaterial] {OutlineMaterial} Defines appearance when outlined. Must be within the same {{#crossLink "Scene"}}Scene{{/crossLink}} as this Mesh. Defaults to the
  524. parent {{#crossLink "Scene"}}Scene{{/crossLink}}'s default instance, {{#crossLink "Scene/outlineMaterial:property"}}outlineMaterial{{/crossLink}}.
  525. @param [cfg.ghostMaterial] Defines appearance when ghosted. Must be within the same {{#crossLink "Scene"}}Scene{{/crossLink}} as this Mesh. Defaults to the
  526. parent {{#crossLink "Scene"}}Scene{{/crossLink}}'s default instance, {{#crossLink "Scene/ghostMaterial:property"}}ghostMaterial{{/crossLink}}.
  527. @param [cfg.highlightMaterial] Defines appearance when highlighted. Must be within the same {{#crossLink "Scene"}}Scene{{/crossLink}} as this Mesh. Defaults to the
  528. parent {{#crossLink "Scene"}}Scene{{/crossLink}}'s default instance, {{#crossLink "Scene/highlightMaterial:property"}}highlightMaterial{{/crossLink}}.
  529. @param [cfg.selectedMaterial] Defines appearance when selected. Must be within the same {{#crossLink "Scene"}}Scene{{/crossLink}} as this Mesh. Defaults to the
  530. parent {{#crossLink "Scene"}}Scene{{/crossLink}}'s default instance, {{#crossLink "Scene/selectedMaterial:property"}}selectedMaterial{{/crossLink}}.
  531. @param [cfg.colorize=[1.0,1.0,1.0]] {Float32Array} RGB colorize color, multiplies by the rendered fragment colors.
  532. @param [cfg.opacity=1.0] {Number} Opacity factor, multiplies by the rendered fragment alpha.
  533. @param [cfg.layer=0] {Number} Indicates this Mesh's rendering priority, relative to other Meshes. Typically used for transparency sorting,
  534. @param [cfg.stationary=false] {Boolean} Disables the effect of {{#crossLink "Camera"}}{{/crossLink}} translations for this Mesh. This is useful for making skyboxes.
  535. @param [cfg.billboard="none"] {String} Specifies the billboarding behaviour for this Mesh. Options are "none", "spherical" and "cylindrical".
  536.  
  537. @param [cfg.visible=true] {Boolean} Indicates if this Mesh is visible. Mesh is only rendered when visible and not culled.
  538. @param [cfg.culled=false] {Boolean} Indicates if this Mesh is culled from view. Mesh is only rendered when visible and not culled.
  539. @param [cfg.pickable=true] {Boolean} Indicates if this Mesh is pickable. When false, the Mesh will never be picked by calls to the {{#crossLink "Scene/pick:method"}}Scene pick(){{/crossLink}} method, and picking will happen as "through" the Mesh, to attempt to pick whatever lies on the other side of it.
  540. @param [cfg.clippable=true] {Boolean} Indicates if this Mesh is clippable by {{#crossLink "Clips"}}{{/crossLink}}. When false, Mesh will not be affected by the {{#crossLink "Scene"}}Scene{{/crossLink}}'s {{#crossLink "Clips"}}{{/crossLink}}.
  541. @param [cfg.collidable=true] {Boolean} Whether this Mesh is included in boundary calculations. When false, the bounding boxes of the containing {{#crossLink "Scene"}}{{/crossLink}} and parent {{#crossLink "Object"}}{{/crossLink}}, {{#crossLink "Group"}}{{/crossLink}} or {{#crossLink "Model"}}{{/crossLink}} will not be calculated to enclose this Mesh.
  542. @param [cfg.castShadow=true] {Boolean} Whether this Mesh casts shadows.
  543. @param [cfg.receiveShadow=true] {Boolean} Whether this Mesh receives shadows.
  544. @param [cfg.outlined=false] {Boolean} Whether an outline is rendered around this mesh.
  545. @param [cfg.ghosted=false] {Boolean} Whether this Mesh is rendered with a ghosted appearance.
  546. @param [cfg.highlighted=false] {Boolean} Whether this Mesh is rendered with a highlighted appearance.
  547. @param [cfg.selected=false] {Boolean} Whether this Mesh is rendered with a selected appearance.
  548. @param [cfg.aabbVisible=false] {Boolean} Whether this Mesh's World-space axis-aligned bounding box (AABB) is visible.
  549. @param [cfg.obbVisible=false] {Boolean} Whether this Mesh's World-space oriented bounding box (OBB) is visible.
  550.  
  551. @param [cfg.colorize=[1.0,1.0,1.0]] {Float32Array} RGB colorize color, multiplies by the rendered fragment colors.
  552. @param [cfg.opacity=1.0] {Number} Opacity factor, multiplies by the rendered fragment alpha.
  553.  
  554. @param [cfg.loading=false] {Boolean} Flag which indicates that this Mesh is freshly loaded.
  555.  
  556. @extends Object
  557. */
  558.  
  559. /**
  560. Fired when this Mesh is picked via a call to {{#crossLink "Scene/pick:method"}}Scene#pick(){{/crossLink}}.
  561.  
  562. The event parameters will be the hit result returned by the {{#crossLink "Scene/pick:method"}}Scene#pick(){{/crossLink}} method.
  563. @event picked
  564. */
  565. import {math} from '../math/math.js';
  566. import {xeoglObject} from './object.js';
  567. import {State} from '../renderer/state.js';
  568. import {DrawRenderer} from "../renderer/draw/drawRenderer.js";
  569. import {EmphasisFillRenderer} from "../renderer/emphasis/emphasisFillRenderer.js";
  570. import {EmphasisEdgesRenderer} from "../renderer/emphasis/emphasisEdgesRenderer.js";
  571. import {EmphasisVerticesRenderer} from "../renderer/emphasis/emphasisVerticesRenderer.js";
  572. import {ShadowRenderer} from "../renderer/shadow/shadowRenderer.js";
  573. import {OutlineRenderer} from "../renderer/outline/outlineRenderer.js";
  574. import {PickMeshRenderer} from "../renderer/pick/pickMeshRenderer.js";
  575. import {PickVertexRenderer} from "../renderer/pick/pickVertexRenderer.js";
  576. import {PickTriangleRenderer} from "../renderer/pick/pickTriangleRenderer.js";
  577. import {componentClasses} from "./../componentClasses.js";
  578.  
  579. const obb = math.OBB3();
  580.  
  581. const type = "xeogl.Mesh";
  582.  
  583. class Mesh extends xeoglObject {
  584.  
  585. /**
  586. JavaScript class name for this Component.
  587.  
  588. For example: "xeogl.AmbientLight", "xeogl.MetallicMaterial" etc.
  589.  
  590. @property type
  591. @type String
  592. @final
  593. */
  594. get type() {
  595. return type;
  596. }
  597.  
  598. static _compareState(a, b) {
  599. return (a._state.layer - b._state.layer)
  600. || (a._drawRenderer.id - b._drawRenderer.id) // Program state
  601. || (a._material._state.id - b._material._state.id) // Material state
  602. || (a._vertexBufs.id - b._vertexBufs.id) // SHared vertex bufs
  603. || (a._geometry._state.id - b._geometry._state.id); // Geometry state
  604. }
  605.  
  606. init(cfg) {
  607.  
  608. this._state = new State({ // NOTE: Renderer gets modeling and normal matrices from xeogl.Object#matrix and xeogl.Object.#normalMatrix
  609. visible: true,
  610. culled: false,
  611. pickable: null,
  612. clippable: null,
  613. colorize: null,
  614. collidable: null,
  615. castShadow: null,
  616. receiveShadow: null,
  617. outlined: null,
  618. ghosted: false,
  619. highlighted: false,
  620. selected: false,
  621. edges: false,
  622. layer: null,
  623. billboard: this._checkBillboard(cfg.billboard),
  624. stationary: !!cfg.stationary,
  625. hash: ""
  626. });
  627.  
  628. this._drawRenderer = null;
  629. this._shadowRenderer = null;
  630. this._emphasisFillRenderer = null;
  631. this._emphasisEdgesRenderer = null;
  632. this._emphasisVerticesRenderer = null;
  633. this._pickMeshRenderer = null;
  634. this._pickTriangleRenderer = null;
  635.  
  636. this._worldPositions = null;
  637. this._worldPositionsDirty = true;
  638. this._geometry = cfg.geometry ? this._checkComponent("xeogl.Geometry", cfg.geometry) : this.scene.geometry;
  639. this._vertexBufs = this._geometry._getVertexBufs();
  640. this._material = cfg.material ? this._checkComponent("xeogl.Material", cfg.material) : this.scene.material;
  641. this._ghostMaterial = cfg.ghostMaterial ? this._checkComponent("xeogl.EmphasisMaterial", cfg.ghostMaterial) : this.scene.ghostMaterial;
  642. this._outlineMaterial = cfg.outlineMaterial ? this._checkComponent("xeogl.EmphasisMaterial", cfg.outlineMaterial) : this.scene.outlineMaterial;
  643. this._highlightMaterial = cfg.highlightMaterial ? this._checkComponent("xeogl.EmphasisMaterial", cfg.highlightMaterial) : this.scene.highlightMaterial;
  644. this._selectedMaterial = cfg.selectedMaterial ? this._checkComponent("xeogl.EmphasisMaterial", cfg.selectedMaterial) : this.scene.selectedMaterial;
  645. this._edgeMaterial = cfg.edgeMaterial ? this._checkComponent("xeogl.EdgeMaterial", cfg.edgeMaterial) : this.scene.edgeMaterial;
  646.  
  647. this._compile();
  648.  
  649. super.init(cfg); // Call xeogl.Object._init()
  650.  
  651. this.scene._meshCreated(this);
  652. }
  653.  
  654. _checkBillboard(value) {
  655. value = value || "none";
  656. if (value !== "spherical" && value !== "cylindrical" && value !== "none") {
  657. this.error("Unsupported value for 'billboard': " + value + " - accepted values are " +
  658. "'spherical', 'cylindrical' and 'none' - defaulting to 'none'.");
  659. value = "none";
  660. }
  661. return value;
  662. }
  663.  
  664. _compile() {
  665. this._putRenderers();
  666. this._makeHash();
  667. this._drawRenderer = DrawRenderer.get(this);
  668. this._shadowRenderer = ShadowRenderer.get(this);
  669. this._emphasisFillRenderer = EmphasisFillRenderer.get(this);
  670. this._emphasisEdgesRenderer = EmphasisEdgesRenderer.get(this);
  671. this._emphasisVerticesRenderer = EmphasisVerticesRenderer.get(this);
  672. this._pickMeshRenderer = PickMeshRenderer.get(this);
  673.  
  674. this._renderer.meshListDirty();
  675. }
  676.  
  677. _webglContextRestored() {
  678. if (this._drawRenderer) {
  679. this._drawRenderer.webglContextRestored();
  680. }
  681. if (this._shadowRenderer) {
  682. this._shadowRenderer.webglContextRestored();
  683. }
  684. if (this._emphasisFillRenderer) {
  685. this._emphasisFillRenderer.webglContextRestored();
  686. }
  687. if (this._emphasisEdgesRenderer) {
  688. this._emphasisEdgesRenderer.webglContextRestored();
  689. }
  690. if (this._emphasisVerticesRenderer) {
  691. this._emphasisVerticesRenderer.webglContextRestored();
  692. }
  693. if (this._pickMeshRenderer) {
  694. this._pickMeshRenderer.webglContextRestored();
  695. }
  696. if (this._pickTriangleRenderer) {
  697. this._pickMeshRenderer.webglContextRestored();
  698. }
  699. }
  700.  
  701. _makeHash() {
  702. const hash = [];
  703. const state = this._state;
  704. if (state.stationary) {
  705. hash.push("/s");
  706. }
  707. if (state.billboard === "none") {
  708. hash.push("/n");
  709. } else if (state.billboard === "spherical") {
  710. hash.push("/s");
  711. } else if (state.billboard === "cylindrical") {
  712. hash.push("/c");
  713. }
  714. if (state.receiveShadow) {
  715. hash.push("/rs");
  716. }
  717. hash.push(";");
  718. this._state.hash = hash.join("");
  719. }
  720.  
  721. _buildMeshAABB(worldMatrix, aabb) { // TODO: factor out into class member
  722. math.transformOBB3(worldMatrix, this._geometry.obb, obb);
  723. math.OBB3ToAABB3(obb, aabb);
  724. }
  725.  
  726. _getSceneHash() {
  727. return (this.scene.gammaInput ? "gi;" : ";") + (this.scene.gammaOutput ? "go" : "");
  728. }
  729.  
  730. //--------------------- Rendering ------------------------------------------------------------------------------
  731.  
  732. _draw(frame) {
  733. if (this._drawRenderer || (this._drawRenderer = DrawRenderer.get(this))) {
  734. this._drawRenderer.drawMesh(frame, this);
  735. }
  736. }
  737.  
  738. _drawGhostFill(frame) {
  739. if (this._emphasisFillRenderer || (this._emphasisFillRenderer = EmphasisFillRenderer.get(this))) {
  740. this._emphasisFillRenderer.drawMesh(frame, this, 0); // 0 == ghost
  741. }
  742. }
  743.  
  744. _drawGhostEdges(frame) {
  745. if (this._emphasisEdgesRenderer || (this._emphasisEdgesRenderer = EmphasisEdgesRenderer.get(this))) {
  746. this._emphasisEdgesRenderer.drawMesh(frame, this, 0); // 0 == ghost
  747. }
  748. }
  749.  
  750. _drawGhostVertices(frame) {
  751. if (this._emphasisVerticesRenderer || (this._emphasisVerticesRenderer = EmphasisVerticesRenderer.get(this))) {
  752. this._emphasisVerticesRenderer.drawMesh(frame, this, 0); // 0 == ghost
  753. }
  754. }
  755.  
  756. _drawHighlightFill(frame) {
  757. if (this._emphasisFillRenderer || (this._emphasisFillRenderer = EmphasisFillRenderer.get(this))) {
  758. this._emphasisFillRenderer.drawMesh(frame, this, 1); // 1 == highlight
  759. }
  760. }
  761.  
  762. _drawHighlightEdges(frame) {
  763. if (this._emphasisEdgesRenderer || (this._emphasisEdgesRenderer = EmphasisEdgesRenderer.get(this))) {
  764. this._emphasisEdgesRenderer.drawMesh(frame, this, 1); // 1 == highlight
  765. }
  766. }
  767.  
  768. _drawHighlightVertices(frame) {
  769. if (this._emphasisVerticesRenderer || (this._emphasisVerticesRenderer = EmphasisVerticesRenderer.get(this))) {
  770. this._emphasisVerticesRenderer.drawMesh(frame, this, 1); // 1 == highlight
  771. }
  772. }
  773.  
  774. _drawSelectedFill(frame) {
  775. if (this._emphasisFillRenderer || (this._emphasisFillRenderer = EmphasisFillRenderer.get(this))) {
  776. this._emphasisFillRenderer.drawMesh(frame, this, 2); // 2 == selected
  777. }
  778. }
  779.  
  780. _drawSelectedEdges(frame) {
  781. if (this._emphasisEdgesRenderer || (this._emphasisEdgesRenderer = EmphasisEdgesRenderer.get(this))) {
  782. this._emphasisEdgesRenderer.drawMesh(frame, this, 2); // 2 == selected
  783. }
  784. }
  785.  
  786. _drawSelectedVertices(frame) {
  787. if (this._emphasisVerticesRenderer || (this._emphasisVerticesRenderer = EmphasisVerticesRenderer.get(this))) {
  788. this._emphasisVerticesRenderer.drawMesh(frame, this, 2); // 2 == selected
  789. }
  790. }
  791.  
  792. _drawEdges(frame) {
  793. if (this._emphasisEdgesRenderer || (this._emphasisEdgesRenderer = EmphasisEdgesRenderer.get(this))) {
  794. this._emphasisEdgesRenderer.drawMesh(frame, this, 3); // 3 == edges
  795. }
  796. }
  797.  
  798. _drawShadow(frame, light) {
  799. if (this._shadowRenderer || (this._shadowRenderer = ShadowRenderer.get(this))) {
  800. this._shadowRenderer.drawMesh(frame, this, light);
  801. }
  802. }
  803.  
  804. _drawOutline(frame) {
  805. if (this._shadowRenderer || (this._outlineRenderer = OutlineRenderer.get(this))) {
  806. this._outlineRenderer.drawMesh(frame, this);
  807. }
  808. }
  809.  
  810. _pickMesh(frame) {
  811. if (this._pickMeshRenderer || (this._pickMeshRenderer = PickMeshRenderer.get(this))) {
  812. this._pickMeshRenderer.drawMesh(frame, this);
  813. }
  814. }
  815.  
  816. _pickTriangle(frame) {
  817. if (this._pickTriangleRenderer || (this._pickTriangleRenderer = PickTriangleRenderer.get(this))) {
  818. this._pickTriangleRenderer.drawMesh(frame, this);
  819. }
  820. }
  821.  
  822. _pickVertex(frame) {
  823. if (this._pickVertexRenderer || (this._pickVertexRenderer = PickVertexRenderer.get(this))) {
  824. this._pickVertexRenderer.drawMesh(frame, this);
  825. }
  826. }
  827.  
  828. _getOutlineRenderer() {
  829. this._outlineRenderer = OutlineRenderer.get(this);
  830. if (this._outlineRenderer.errors) {
  831. this.errors = (this.errors || []).concat(this._outlineRenderer.errors);
  832. this.error(this._outlineRenderer.errors.join("\n"));
  833. return false;
  834. }
  835. return true;
  836. }
  837.  
  838. _putRenderers() {
  839. if (this._drawRenderer) {
  840. this._drawRenderer.put();
  841. this._drawRenderer = null;
  842. }
  843. if (this._shadowRenderer) {
  844. this._shadowRenderer.put();
  845. this._shadowRenderer = null;
  846. }
  847. if (this._emphasisFillRenderer) {
  848. this._emphasisFillRenderer.put();
  849. this._emphasisFillRenderer = null;
  850. }
  851. if (this._emphasisEdgesRenderer) {
  852. this._emphasisEdgesRenderer.put();
  853. this._emphasisEdgesRenderer = null;
  854. }
  855. if (this._emphasisVerticesRenderer) {
  856. this._emphasisVerticesRenderer.put();
  857. this._emphasisVerticesRenderer = null;
  858. }
  859. if (this._outlineRenderer) {
  860. this._outlineRenderer.put();
  861. this._outlineRenderer = null;
  862. }
  863. if (this._pickMeshRenderer) {
  864. this._pickMeshRenderer.put();
  865. this._pickMeshRenderer = null;
  866. }
  867. if (this._pickTriangleRenderer) {
  868. this._pickTriangleRenderer.put();
  869. this._pickTriangleRenderer = null;
  870. }
  871. if (this._pickVertexRenderer) {
  872. this._pickVertexRenderer.put();
  873. this._pickVertexRenderer = null;
  874. }
  875. }
  876.  
  877. /**
  878. World-space 3D vertex positions.
  879.  
  880. These are internally generated on-demand and cached. To free the cached
  881. vertex World positions when you're done with them, set this property to null or undefined.
  882.  
  883. @property worldPositions
  884. @type Float32Array
  885. @final
  886. */
  887. get worldPositions() {
  888. if (this._worldPositionsDirty) {
  889. const positions = this._geometry.positions;
  890. if (!this._worldPositions) {
  891. this._worldPositions = new Float32Array(positions.length);
  892. }
  893. math.transformPositions3(this.worldMatrix, positions, this._worldPositions);
  894. this._worldPositionsDirty = false;
  895. }
  896. return this._worldPositions;
  897. }
  898.  
  899. set worldPositions(value) {
  900. if (value = undefined || value === null) {
  901. this._worldPositions = null; // Release memory
  902. this._worldPositionsDirty = true;
  903. }
  904. }
  905.  
  906. /**
  907. Defines the shape of this Mesh.
  908.  
  909. @property geometry
  910. @type Geometry
  911. @final
  912. */
  913. get geometry() {
  914. return this._geometry;
  915. }
  916.  
  917. /**
  918. Defines appearance when rendering normally, ie. when not ghosted, highlighted or selected.
  919.  
  920. @property material
  921. @type Material
  922. @final
  923. */
  924. get material() {
  925. return this._material;
  926. }
  927.  
  928. /**
  929. Defines surface appearance when ghosted.
  930.  
  931. @property ghostMaterial
  932. @type EmphasisMaterial
  933. @final
  934. */
  935. get ghostMaterial() {
  936. return this._ghostMaterial;
  937. }
  938.  
  939. /**
  940. Defines surface appearance when highlighted.
  941.  
  942. @property highlightMaterial
  943. @type EmphasisMaterial
  944. @final
  945. */
  946. get highlightMaterial() {
  947. return this._highlightMaterial;
  948. }
  949.  
  950. /**
  951. Defines surface appearance when selected.
  952.  
  953. @property selectedMaterial
  954. @type EmphasisMaterial
  955. */
  956. get selectedMaterial() {
  957. return this._selectedMaterial;
  958. }
  959.  
  960. /**
  961. Defines surface appearance when edges are shown.
  962.  
  963. @property edgeMaterial
  964. @type EdgeMaterial
  965. */
  966. get edgeMaterial() {
  967. return this._edgeMaterial;
  968. }
  969.  
  970. /**
  971. Defines surface appearance when outlined.
  972.  
  973. @property outlineMaterial
  974. @type OutlineMaterial
  975. */
  976. get outlineMaterial() {
  977. return this._outlineMaterial;
  978. }
  979.  
  980. /**
  981. Indicates if visible.
  982.  
  983. The Mesh is only rendered when {{#crossLink "Mesh/visible:property"}}{{/crossLink}} is true and
  984. {{#crossLink "Mesh/culled:property"}}{{/crossLink}} is false.
  985.  
  986. Each visible Mesh is registered in the {{#crossLink "Scene"}}{{/crossLink}}'s
  987. {{#crossLink "Scene/visibleEntities:property"}}{{/crossLink}} map when its {{#crossLink "Object/entityType:property"}}{{/crossLink}}
  988. is set to a value.
  989.  
  990. @property visible
  991. @default true
  992. @type Boolean
  993. */
  994. set visible(visible) {
  995. visible = visible !== false;
  996. this._state.visible = visible;
  997. if (this._entityType) {
  998. this.scene._entityVisibilityUpdated(this, visible);
  999. }
  1000. this._renderer.imageDirty();
  1001. if (this._state.castShadow) {
  1002. this._renderer.shadowsDirty();
  1003. }
  1004. }
  1005.  
  1006. get visible() {
  1007. return this._state.visible;
  1008. }
  1009.  
  1010. /**
  1011. Indicates if ghosted.
  1012.  
  1013. The ghosted appearance is configured by {{#crossLink "Mesh/ghostMaterial:property"}}ghostMaterial{{/crossLink}}.
  1014.  
  1015. Each ghosted Mesh is registered in its {{#crossLink "Scene"}}{{/crossLink}}'s
  1016. {{#crossLink "Scene/ghostedEntities:property"}}{{/crossLink}} map when its {{#crossLink "Object/entityType:property"}}{{/crossLink}}
  1017. is set to a value.
  1018.  
  1019. @property ghosted
  1020. @default false
  1021. @type Boolean
  1022. */
  1023. set ghosted(ghosted) {
  1024. ghosted = !!ghosted;
  1025. if (this._state.ghosted === ghosted) {
  1026. return;
  1027. }
  1028. this._state.ghosted = ghosted;
  1029. if (this._entityType) {
  1030. this.scene._entityGhostedUpdated(this, ghosted);
  1031. }
  1032. this._renderer.imageDirty();
  1033. }
  1034.  
  1035. get ghosted() {
  1036. return this._state.ghosted;
  1037. }
  1038.  
  1039. /**
  1040. Indicates if highlighted.
  1041.  
  1042. The highlight appearance is configured by {{#crossLink "Mesh/highlightMaterial:property"}}highlightMaterial{{/crossLink}}.
  1043.  
  1044. Each highlighted Mesh is registered in its {{#crossLink "Scene"}}{{/crossLink}}'s
  1045. {{#crossLink "Scene/highlightedEntities:property"}}{{/crossLink}} map when its {{#crossLink "Object/entityType:property"}}{{/crossLink}}
  1046. is set to a value.
  1047.  
  1048. @property highlighted
  1049. @default false
  1050. @type Boolean
  1051. */
  1052. set highlighted(highlighted) {
  1053. highlighted = !!highlighted;
  1054. if (highlighted === this._state.highlighted) {
  1055. return;
  1056. }
  1057. this._state.highlighted = highlighted;
  1058. if (this._entityType) {
  1059. this.scene._entityHighlightedUpdated(this, highlighted);
  1060. }
  1061. this._renderer.imageDirty();
  1062. }
  1063.  
  1064. get highlighted() {
  1065. return this._state.highlighted;
  1066. }
  1067.  
  1068. /**
  1069. Indicates if selected.
  1070.  
  1071. The selected appearance is configured by {{#crossLink "Mesh/selectedMaterial:property"}}selectedMaterial{{/crossLink}}.
  1072.  
  1073. Each selected Mesh is registered in its {{#crossLink "Scene"}}{{/crossLink}}'s
  1074. {{#crossLink "Scene/selectedEntities:property"}}{{/crossLink}} map when its {{#crossLink "Object/entityType:property"}}{{/crossLink}}
  1075. is set to a value.
  1076.  
  1077. @property selected
  1078. @default false
  1079. @type Boolean
  1080. */
  1081. set selected(selected) {
  1082. selected = !!selected;
  1083. if (selected === this._state.selected) {
  1084. return;
  1085. }
  1086. this._state.selected = selected;
  1087. if (this._entityType) {
  1088. this.scene._entitySelectedUpdated(this, selected);
  1089. }
  1090. this._renderer.imageDirty();
  1091. }
  1092.  
  1093. get selected() {
  1094. return this._state.selected;
  1095. }
  1096.  
  1097. /**
  1098. Indicates if edges are shown.
  1099.  
  1100. The edges appearance is configured by {{#crossLink "Mesh/edgeMaterial:property"}}edgeMaterial{{/crossLink}}.
  1101.  
  1102. @property edges
  1103. @default false
  1104. @type Boolean
  1105. */
  1106. set edges(edges) {
  1107. edges = !!edges;
  1108. if (edges === this._state.edges) {
  1109. return;
  1110. }
  1111. this._state.edges = edges;
  1112. this._renderer.imageDirty();
  1113. }
  1114.  
  1115. get edges() {
  1116. return this._state.edges;
  1117. }
  1118.  
  1119. /**
  1120. Indicates if culled from view.
  1121.  
  1122. The MEsh is only rendered when {{#crossLink "Mesh/visible:property"}}{{/crossLink}} is true and
  1123. {{#crossLink "Mesh/culled:property"}}{{/crossLink}} is false.
  1124.  
  1125. @property culled
  1126. @default false
  1127. @type Boolean
  1128. */
  1129. set culled(value) {
  1130. this._state.culled = !!value;
  1131. this._renderer.imageDirty();
  1132. }
  1133.  
  1134. get culled() {
  1135. return this._state.culled;
  1136. }
  1137.  
  1138. /**
  1139. Indicates if pickable.
  1140.  
  1141. When false, the Mesh will never be picked by calls to the {{#crossLink "Scene/pick:method"}}Scene pick(){{/crossLink}} method, and picking will happen as "through" the Mesh, to attempt to pick whatever lies on the other side of it.
  1142.  
  1143. @property pickable
  1144. @default true
  1145. @type Boolean
  1146. */
  1147. set pickable(value) {
  1148. value = value !== false;
  1149. if (this._state.pickable === value) {
  1150. return;
  1151. }
  1152. this._state.pickable = value;
  1153. // No need to trigger a render;
  1154. // state is only used when picking
  1155. }
  1156.  
  1157. get pickable() {
  1158. return this._state.pickable;
  1159. }
  1160.  
  1161. /**
  1162. Indicates if clippable.
  1163.  
  1164. When false, the {{#crossLink "Scene"}}Scene{{/crossLink}}'s {{#crossLink "Clips"}}{{/crossLink}} will have no effect on the Mesh.
  1165.  
  1166. @property clippable
  1167. @default true
  1168. @type Boolean
  1169. */
  1170. set clippable(value) {
  1171. value = value !== false;
  1172. if (this._state.clippable === value) {
  1173. return;
  1174. }
  1175. this._state.clippable = value;
  1176. this._renderer.imageDirty();
  1177. if (this._state.castShadow) {
  1178. this._renderer.shadowsDirty();
  1179. }
  1180. }
  1181.  
  1182. get clippable() {
  1183. return this._state.clippable;
  1184. }
  1185.  
  1186. /**
  1187. Indicates if included in boundary calculations.
  1188.  
  1189. When false, this Mesh will not be included in the bounding boxes provided by parent components (
  1190.  
  1191. @property collidable
  1192. @default true
  1193. @type Boolean
  1194. */
  1195. set collidable(value) {
  1196. value = value !== false;
  1197. if (value === this._state.collidable) {
  1198. return;
  1199. }
  1200. this._state.collidable = value;
  1201. }
  1202.  
  1203. get collidable() {
  1204. return this._state.collidable;
  1205. }
  1206.  
  1207. /**
  1208. Indicates if casting shadows.
  1209.  
  1210. @property castShadow
  1211. @default true
  1212. @type Boolean
  1213. */
  1214. set castShadow(value) {
  1215. value = value !== false;
  1216. if (value === this._state.castShadow) {
  1217. return;
  1218. }
  1219. this._state.castShadow = value;
  1220. this._renderer.shadowsDirty();
  1221. }
  1222.  
  1223. get castShadow() {
  1224. return this._state.castShadow;
  1225. }
  1226.  
  1227. /**
  1228. Indicates if receiving shadows.
  1229.  
  1230. @property receiveShadow
  1231. @default true
  1232. @type Boolean
  1233. */
  1234. set receiveShadow(value) {
  1235. this._state.receiveShadow = false; // Disables shadows for now
  1236. // value = value !== false;
  1237. // if (value === this._state.receiveShadow) {
  1238. // return;
  1239. // }
  1240. // this._state.receiveShadow = value;
  1241. // this._state.hash = value ? "/mod/rs;" : "/mod;";
  1242. // this.fire("dirty", this); // Now need to (re)compile objectRenderers to include/exclude shadow mapping
  1243. }
  1244.  
  1245. get receiveShadow() {
  1246. return this._state.receiveShadow;
  1247. }
  1248.  
  1249. /**
  1250. Indicates if rendered with an outline.
  1251.  
  1252. The outline appearance is configured by {{#crossLink "Mesh/outlineMaterial:property"}}outlineMaterial{{/crossLink}}.
  1253.  
  1254. @property outlined
  1255. @default false
  1256. @type Boolean
  1257. */
  1258. set outlined(value) {
  1259. value = !!value;
  1260. if (value === this._state.outlined) {
  1261. return;
  1262. }
  1263. this._state.outlined = value;
  1264. this._renderer.imageDirty();
  1265. }
  1266.  
  1267. get outlined() {
  1268. return this._state.outlined;
  1269. }
  1270.  
  1271. /**
  1272. RGB colorize color, multiplies by the rendered fragment colors.
  1273.  
  1274. @property colorize
  1275. @default [1.0, 1.0, 1.0]
  1276. @type Float32Array
  1277. */
  1278. set colorize(value) {
  1279. let colorize = this._state.colorize;
  1280. if (!colorize) {
  1281. colorize = this._state.colorize = new Float32Array(4);
  1282. colorize[3] = 1;
  1283. }
  1284. if (value) {
  1285. colorize[0] = value[0];
  1286. colorize[1] = value[1];
  1287. colorize[2] = value[2];
  1288. } else {
  1289. colorize[0] = 1;
  1290. colorize[1] = 1;
  1291. colorize[2] = 1;
  1292. }
  1293. this._renderer.imageDirty();
  1294. }
  1295.  
  1296. get colorize() {
  1297. return this._state.colorize;
  1298. }
  1299.  
  1300. /**
  1301. Opacity factor, multiplies by the rendered fragment alpha.
  1302.  
  1303. This is a factor in range ````[0..1]````.
  1304.  
  1305. @property opacity
  1306. @default 1.0
  1307. @type Number
  1308. */
  1309. set opacity(opacity) {
  1310. let colorize = this._state.colorize;
  1311. if (!colorize) {
  1312. colorize = this._state.colorize = new Float32Array(4);
  1313. colorize[0] = 1;
  1314. colorize[1] = 1;
  1315. colorize[2] = 1;
  1316. }
  1317. colorize[3] = opacity !== null && opacity !== undefined ? opacity : 1.0;
  1318. this._renderer.imageDirty();
  1319. }
  1320.  
  1321. get opacity() {
  1322. return this._state.colorize[3];
  1323. }
  1324.  
  1325. /**
  1326. The rendering order.
  1327.  
  1328. This can be set on multiple transparent Meshes, to make them render in a specific order
  1329. for correct alpha blending.
  1330.  
  1331. @property layer
  1332. @default 0
  1333. @type Number
  1334. */
  1335. set layer(value) {
  1336. // TODO: Only accept rendering layer in range [0...MAX_layer]
  1337. value = value || 0;
  1338. value = Math.round(value);
  1339. if (value === this._state.layer) {
  1340. return;
  1341. }
  1342. this._state.layer = value;
  1343. this._renderer.needStateSort();
  1344. }
  1345.  
  1346. get layer() {
  1347. return this._state.layer;
  1348. }
  1349.  
  1350. /**
  1351. Indicates if the position is stationary.
  1352.  
  1353. When true, will disable the effect of {{#crossLink "Lookat"}}view transform{{/crossLink}}
  1354. translations for this Mesh, while still allowing it to rotate. This is useful for skybox Meshes.
  1355.  
  1356. @property stationary
  1357. @default false
  1358. @type Boolean
  1359. @final
  1360. */
  1361. get stationary() {
  1362. return this._state.stationary;
  1363. }
  1364.  
  1365. /**
  1366. Indicates the billboarding behaviour.
  1367.  
  1368. Options are:
  1369.  
  1370. * **"none"** - **(default)** - No billboarding.
  1371. * **"spherical"** - Mesh is billboarded to face the viewpoint, rotating both vertically and horizontally.
  1372. * **"cylindrical"** - Mesh is billboarded to face the viewpoint, rotating only about its vertically
  1373. axis. Use this mode for things like trees on a landscape.
  1374.  
  1375. @property billboard
  1376. @default "none"
  1377. @type String
  1378. @final
  1379. */
  1380. get billboard() {
  1381. return this._state.billboard;
  1382. }
  1383.  
  1384. destroy() {
  1385. super.destroy(); // xeogl.Object
  1386. this._putRenderers();
  1387. this._renderer.meshListDirty();
  1388. this.scene._meshDestroyed(this);
  1389. if (this._state.castShadow) {
  1390. this._renderer.shadowsDirty();
  1391. }
  1392. }
  1393. }
  1394.  
  1395. componentClasses[type] = Mesh;
  1396.  
  1397. export {Mesh};