/home/lindsay/xeolabs/xeogl-next/xeogl/src/materials/edgeMaterial.js
API Docs for:

File: /home/lindsay/xeolabs/xeogl-next/xeogl/src/materials/edgeMaterial.js

  1. /**
  2. An **EdgeMaterial** is a {{#crossLink "Material"}}{{/crossLink}} that defines the appearance of attached
  3. {{#crossLink "Mesh"}}Meshes{{/crossLink}} when they are highlighted, selected or ghosted.
  4.  
  5. ## Examples
  6.  
  7. | <a href="../../examples/#effects_ghost"><img src="../../assets/images/screenshots/HighlightMaterial/teapot.png"></img></a> | <a href="../../examples/#effects_demo_housePlan"><img src="../../assets/images/screenshots/HighlightMaterial/house.png"></img></a> | <a href="../../examples/#effects_demo_gearbox"><img src="../../assets/images/screenshots/HighlightMaterial/gearbox.png"></img></a> | <a href="../../examples/#effects_demo_adam"><img src="../../assets/images/screenshots/HighlightMaterial/adam.png"></img></a>|
  8. |:------:|:------:|:----:|:-----:|:-----:|
  9. |[Example 1: Ghost effect](../../examples/#effects_ghost)|[Example 2: Ghost and highlight effects for architecture](../../examples/#effects_demo_housePlan)|[Example 3: Ghost and highlight effects for CAD](../../examples/#effects_demo_gearbox)| [Example 4: Ghost effect for CAD ](../../examples//#effects_demo_adam)|
  10.  
  11. ## Overview
  12.  
  13. * Ghost an {{#crossLink "Mesh"}}{{/crossLink}} by setting its {{#crossLink "Mesh/ghost:property"}}{{/crossLink}} property ````true````.
  14. * When ghosted, a Mesh's appearance is controlled by its EdgeMaterial.
  15. * An EdgeMaterial provides several preset configurations that you can set it to. Select a preset by setting {{#crossLink "EdgeMaterial/preset:property"}}{{/crossLink}} to the preset's ID. A map of available presets is provided in {{#crossLink "EdgeMaterial/presets:property"}}xeogl.EdgeMaterial.presets{{/crossLink}}.
  16. * By default, a Mesh uses the {{#crossLink "Scene"}}{{/crossLink}}'s global EdgeMaterials, but you can give each Mesh its own EdgeMaterial when you want to customize the effect per-Mesh.
  17. * Ghost all Meshes in a {{#crossLink "Model"}}{{/crossLink}} by setting the Model's {{#crossLink "Model/ghost:property"}}{{/crossLink}} property ````true````. Note that all Meshes in a Model have the Scene's global EdgeMaterial by default.
  18. * Modify the Scene's global EdgeMaterial to customize it.
  19.  
  20. ## Usage
  21.  
  22. * [Ghosting](#ghosting)
  23. * [Highlighting](#highlighting)
  24.  
  25. ### Ghosting
  26.  
  27. In the usage example below, we'll create a Mesh with a ghost effect applied to it. The Mesh gets its own EdgeMaterial for ghosting, and
  28. has its {{#crossLink "Mesh/ghost:property"}}{{/crossLink}} property set ````true```` to activate the effect.
  29.  
  30. <a href="../../examples/#effects_ghost"><img src="../../assets/images/screenshots/HighlightMaterial/teapot.png"></img></a>
  31.  
  32. ````javascript
  33. var mesh = new xeogl.Mesh({
  34. geometry: new xeogl.TeapotGeometry({
  35. edgeThreshold: 1
  36. }),
  37. material: new xeogl.PhongMaterial({
  38. diffuse: [0.2, 0.2, 1.0]
  39. }),
  40. edgeMaterial: new xeogl.EdgeMaterial({
  41. edges: true,
  42. edgeColor: [0.2, 1.0, 0.2],
  43. edgeAlpha: 1.0,
  44. edgeWidth: 2,
  45. vertices: true,
  46. vertexColor: [0.6, 1.0, 0.6],
  47. vertexAlpha: 1.0,
  48. vertexSize: 8,
  49. fill: true,
  50. fillColor: [0, 0, 0],
  51. fillAlpha: 0.7
  52. }),
  53. ghost: true
  54. });
  55. ````
  56.  
  57. Note the **edgeThreshold** configuration on the {{#crossLink "Geometry"}}{{/crossLink}} we've created for our
  58. Mesh. Our EdgeMaterial is configured to draw a wireframe representation of the Geometry, which will have inner edges (ie. edges between
  59. adjacent co-planar triangles) removed for visual clarity. The ````edgeThreshold```` configuration indicates
  60. that, for this particular Geometry, an inner edge is one where the angle between the surface normals of adjacent triangles is not
  61. greater than ````5```` degrees. That's set to ````2```` by default, but we can override it to tweak the effect as needed for particular Geometries.
  62.  
  63. Here's the example again, this time using the Scene's global EdgeMaterial by default. We'll also modify that EdgeMaterial
  64. to customize the effect.
  65.  
  66. ````javascript
  67. var mesh = new xeogl.Mesh({
  68. geometry: new xeogl.TeapotGeometry({
  69. edgeThreshold: 5
  70. }),
  71. material: new xeogl.PhongMaterial({
  72. diffuse: [0.2, 0.2, 1.0]
  73. }),
  74. ghost: true
  75. });
  76.  
  77. var edgeMaterial = mesh.scene.edgeMaterial;
  78.  
  79. edgeMaterial.edges = true;
  80. edgeMaterial.edgeColor = [0.2, 1.0, 0.2];
  81. edgeMaterial.edgeAlpha = 1.0;
  82. edgeMaterial.edgeWidth = 2;
  83. ````
  84.  
  85. ### Highlighting
  86.  
  87. In the next example, we'll use a ghosting in conjunction with highlighting, to emphasise a couple of objects within
  88. a gearbox {{#crossLink "Model"}}{{/crossLink}}. We'll load the Model from glTF, then ghost all of its Meshes except for two gears, which we'll highlight instead. The ghosted
  89. Meshes have the Scene's global ghosting EdgeMaterial, which we'll modify. The highlighted Meshes also have the Scene's global highlighting EdgeMaterial, which we'll modify as well.
  90.  
  91. <a href="../../examples/#effects_demo_gearbox"><img src="../../assets/images/screenshots/HighlightMaterial/gearbox.png"></img></a>
  92.  
  93. ````javascript
  94. var model = new xeogl.GLTFModel({
  95. src: "models/gltf/gearbox_conical/scene.gltf",
  96. edgeThreshold: 10
  97. });
  98.  
  99. model.on("loaded", function() {
  100.  
  101. model.meshes["gearbox#77.0"].highlight = true;
  102. model.meshes["gearbox#79.0"].highlight = true;
  103.  
  104. var edgeMaterial = model.scene.edgeMaterial;
  105.  
  106. edgeMaterial.edgeColor = [0.4, 0.4, 1.6];
  107. edgeMaterial.edgeAlpha = 0.8;
  108. edgeMaterial.edgeWidth = 3;
  109.  
  110. var highlightMaterial = model.scene.highlightMaterial;
  111.  
  112. highlightMaterial.color = [1.0, 1.0, 1.0];
  113. highlightMaterial.alpha = 1.0;
  114. });
  115. ````
  116.  
  117. ## Presets
  118.  
  119. For convenience, an EdgeMaterial provides several preset configurations that you can set it to, which are provided in
  120. {{#crossLink "EdgeMaterial/presets:property"}}xeogl.EdgeMaterial.presets{{/crossLink}}:
  121.  
  122. ````javascript
  123. var presets = xeogl.EdgeMaterial.presets;
  124. ````
  125.  
  126. The presets look something like this:
  127.  
  128. ````json
  129. {
  130. "default": {
  131. edgeColor: [0.2, 0.2, 0.2],
  132. edgeAlpha: 1.0,
  133. edgeWidth: 1
  134. },
  135.  
  136. "sepia": {
  137. edgeColor: [0.45, 0.45, 0.41],
  138. edgeAlpha: 1.0,
  139. edgeWidth: 1
  140. },
  141.  
  142. //...
  143. }
  144. ````
  145.  
  146. Let's switch the Scene's global default EdgeMaterial over to the "sepia" preset used in <a href="/examples/#effects_demo_adam">Example 4: Ghost effect for CAD</a>.
  147.  
  148. ````javascript
  149. scene.edgeMaterial.preset = "sepia";
  150. ````
  151.  
  152. You can also just create an EdgeMaterial from a preset:
  153.  
  154. ````javascript
  155. var mesh = new xeogl.Mesh({
  156. geometry: new xeogl.TeapotGeometry({
  157. edgeThreshold: 5
  158. }),
  159. material: new xeogl.PhongMaterial({
  160. diffuse: [0.2, 0.2, 1.0]
  161. }),
  162. edgeMaterial: new xeogl.EdgeMaterial({
  163. preset: "sepia"
  164. });
  165. ghost: true
  166. });
  167. ````
  168.  
  169. Note that applying a preset just sets the EdgeMaterial's property values, which you are then free to modify afterwards.
  170.  
  171. @class EdgeMaterial
  172. @module xeogl
  173. @submodule materials
  174. @constructor
  175. @extends Material
  176. @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.
  177. @param [cfg] {*} The EdgeMaterial configuration
  178. @param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}}, generated automatically when omitted.
  179. @param [cfg.meta=null] {String:Object} Metadata to attach to this EdgeMaterial.
  180.  
  181. @param [cfg.edgeColor=[0.2,0.2,0.2]] {Array of Number} RGB color of ghost edges.
  182. @param [cfg.edgeAlpha=1.0] {Number} Transparency of ghost edges. A value of 0.0 indicates fully transparent, 1.0 is fully opaque.
  183. @param [cfg.edgeWidth=1] {Number} Width of ghost edges, in pixels.
  184.  
  185. @param [cfg.preset] {String} Selects a preset EdgeMaterial configuration - see {{#crossLink "EdgeMaterial/preset:method"}}EdgeMaterial#preset(){{/crossLink}}.
  186. */
  187.  
  188. import {Material} from './material.js';
  189. import {State} from '../renderer/state.js';
  190. import {componentClasses} from "./../componentClasses.js";
  191.  
  192. const PRESETS = {
  193. "default": {
  194. edgeColor: [0.0, 0.0, 0.0],
  195. edgeAlpha: 1.0,
  196. edgeWidth: 1
  197. },
  198. "defaultWhiteBG": {
  199. edgeColor: [0.2, 0.2, 0.2],
  200. edgeAlpha: 1.0,
  201. edgeWidth: 1
  202. },
  203. "defaultLightBG": {
  204. edgeColor: [0.2, 0.2, 0.2],
  205. edgeAlpha: 1.0,
  206. edgeWidth: 1
  207. },
  208. "defaultDarkBG": {
  209. edgeColor: [0.5, 0.5, 0.5],
  210. edgeAlpha: 1.0,
  211. edgeWidth: 1
  212. }
  213. };
  214.  
  215.  
  216. const type = "xeogl.EdgeMaterial";
  217.  
  218. class EdgeMaterial extends Material {
  219.  
  220. /**
  221. Available EdgeMaterial presets.
  222.  
  223. @property presets
  224. @type {Object}
  225. @static
  226. */
  227. static get presets() {
  228. return PRESETS;
  229. };
  230.  
  231. /**
  232. JavaScript class name for this Component.
  233.  
  234. For example: "xeogl.AmbientLight", "xeogl.MetallicMaterial" etc.
  235.  
  236. @property type
  237. @type String
  238. @final
  239. */
  240. get type() {
  241. return type;
  242. }
  243.  
  244. init(cfg) {
  245.  
  246. super.init(cfg);
  247.  
  248. this._state = new State({
  249. type: "EdgeMaterial",
  250. edgeColor: null,
  251. edgeAlpha: null,
  252. edgeWidth: null
  253. });
  254.  
  255. this._preset = "default";
  256.  
  257. if (cfg.preset) { // Apply preset then override with configs where provided
  258. this.preset = cfg.preset;
  259. if (cfg.edgeColor) {
  260. this.edgeColor = cfg.edgeColor;
  261. }
  262. if (cfg.edgeAlpha !== undefined) {
  263. this.edgeAlpha = cfg.edgeAlpha;
  264. }
  265. if (cfg.edgeWidth !== undefined) {
  266. this.edgeWidth = cfg.edgeWidth;
  267. }
  268. } else {
  269. this.edgeColor = cfg.edgeColor;
  270. this.edgeAlpha = cfg.edgeAlpha;
  271. this.edgeWidth = cfg.edgeWidth;
  272. }
  273. }
  274.  
  275.  
  276. /**
  277. RGB color of ghost edges.
  278.  
  279. @property edgeColor
  280. @default [0.2, 0.2, 0.2]
  281. @type Float32Array
  282. */
  283. set edgeColor(value) {
  284. let edgeColor = this._state.edgeColor;
  285. if (!edgeColor) {
  286. edgeColor = this._state.edgeColor = new Float32Array(3);
  287. } else if (value && edgeColor[0] === value[0] && edgeColor[1] === value[1] && edgeColor[2] === value[2]) {
  288. return;
  289. }
  290. if (value) {
  291. edgeColor[0] = value[0];
  292. edgeColor[1] = value[1];
  293. edgeColor[2] = value[2];
  294. } else {
  295. edgeColor[0] = 0.2;
  296. edgeColor[1] = 0.2;
  297. edgeColor[2] = 0.2;
  298. }
  299. this._renderer.imageDirty();
  300. }
  301.  
  302. get edgeColor() {
  303. return this._state.edgeColor;
  304. }
  305.  
  306. /**
  307. Transparency of ghost edges.
  308.  
  309. A value of 0.0 indicates fully transparent, 1.0 is fully opaque.
  310.  
  311. @property edgeAlpha
  312. @default 1.0
  313. @type Number
  314. */
  315. set edgeAlpha(value) {
  316. value = (value !== undefined && value !== null) ? value : 1.0;
  317. if (this._state.edgeAlpha === value) {
  318. return;
  319. }
  320. this._state.edgeAlpha = value;
  321. this._renderer.imageDirty();
  322. }
  323.  
  324. get edgeAlpha() {
  325. return this._state.edgeAlpha;
  326. }
  327.  
  328. /**
  329. Width of ghost edges, in pixels.
  330.  
  331. @property edgeWidth
  332. @default 1.0
  333. @type Number
  334. */
  335. set edgeWidth(value) {
  336. this._state.edgeWidth = value || 1.0;
  337. this._renderer.imageDirty();
  338. }
  339.  
  340. get edgeWidth() {
  341. return this._state.edgeWidth;
  342. }
  343.  
  344. /**
  345. Selects a preset EdgeMaterial configuration.
  346.  
  347. Available presets are:
  348.  
  349. * "default" - grey wireframe with translucent fill, for light backgrounds.
  350. * "defaultLightBG" - grey wireframe with grey translucent fill, for light backgrounds.
  351. * "defaultDarkBG" - grey wireframe with grey translucent fill, for dark backgrounds.
  352. * "vectorscope" - green wireframe with glowing vertices and black translucent fill.
  353. * "battlezone" - green wireframe with black opaque fill, giving a solid hidden-lines-removed effect.
  354. * "sepia" - light red-grey wireframe with light sepia translucent fill - easy on the eyes.
  355. * "gamegrid" - light blue wireframe with dark blue translucent fill - reminiscent of Tron.
  356. * "yellowHighlight" - light yellow translucent fill - highlights while allowing underlying detail to show through.
  357.  
  358. @property preset
  359. @default "default"
  360. @type String
  361. */
  362. set preset(value) {
  363. value = value || "default";
  364. if (this._preset === value) {
  365. return;
  366. }
  367. const preset = PRESETS[value];
  368. if (!preset) {
  369. this.error("unsupported preset: '" + value + "' - supported values are " + Object.keys(PRESETS).join(", "));
  370. return;
  371. }
  372. this.edgeColor = preset.edgeColor;
  373. this.edgeAlpha = preset.edgeAlpha;
  374. this.edgeWidth = preset.edgeWidth;
  375. this._preset = value;
  376. }
  377.  
  378. get preset() {
  379. return this._preset;
  380. }
  381.  
  382. destroy() {
  383. super.destroy();
  384. this._state.destroy();
  385. }
  386. }
  387.  
  388. componentClasses[type] = EdgeMaterial;
  389.  
  390. export {EdgeMaterial};