transformBlock.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import { NodeMaterialBlock } from '../nodeMaterialBlock';
  2. import { NodeMaterialBlockConnectionPointTypes } from '../Enums/nodeMaterialBlockConnectionPointTypes';
  3. import { NodeMaterialBuildState } from '../nodeMaterialBuildState';
  4. import { NodeMaterialBlockTargets } from '../Enums/nodeMaterialBlockTargets';
  5. import { NodeMaterialConnectionPoint } from '../nodeMaterialBlockConnectionPoint';
  6. import { _TypeStore } from '../../../Misc/typeStore';
  7. import { Scene } from '../../../scene';
  8. import { InputBlock } from './Input/inputBlock';
  9. import { AbstractMesh } from '../../../Meshes/abstractMesh';
  10. import { NodeMaterial, NodeMaterialDefines } from '../nodeMaterial';
  11. import { SubMesh } from '../../../Meshes/subMesh';
  12. /**
  13. * Block used to transform a vector (2, 3 or 4) with a matrix. It will generate a Vector4
  14. */
  15. export class TransformBlock extends NodeMaterialBlock {
  16. /**
  17. * Defines the value to use to complement W value to transform it to a Vector4
  18. */
  19. public complementW = 1;
  20. /**
  21. * Defines the value to use to complement z value to transform it to a Vector4
  22. */
  23. public complementZ = 0;
  24. /**
  25. * Creates a new TransformBlock
  26. * @param name defines the block name
  27. */
  28. public constructor(name: string) {
  29. super(name, NodeMaterialBlockTargets.Vertex);
  30. this.registerInput("vector", NodeMaterialBlockConnectionPointTypes.AutoDetect);
  31. this.registerInput("transform", NodeMaterialBlockConnectionPointTypes.Matrix);
  32. this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Vector4);
  33. this.registerOutput("xyz", NodeMaterialBlockConnectionPointTypes.Vector3);
  34. this._inputs[0].onConnectionObservable.add((other) => {
  35. if (other.ownerBlock.isInput) {
  36. let otherAsInput = other.ownerBlock as InputBlock;
  37. if (otherAsInput.name === "normal" || otherAsInput.name === "tangent") {
  38. this.complementW = 0;
  39. }
  40. }
  41. });
  42. }
  43. /**
  44. * Gets the current class name
  45. * @returns the class name
  46. */
  47. public getClassName() {
  48. return "TransformBlock";
  49. }
  50. /**
  51. * Gets the vector input
  52. */
  53. public get vector(): NodeMaterialConnectionPoint {
  54. return this._inputs[0];
  55. }
  56. /**
  57. * Gets the output component
  58. */
  59. public get output(): NodeMaterialConnectionPoint {
  60. return this._outputs[0];
  61. }
  62. /**
  63. * Gets the xyz output component
  64. */
  65. public get xyz(): NodeMaterialConnectionPoint {
  66. return this._outputs[1];
  67. }
  68. /**
  69. * Gets the matrix transform input
  70. */
  71. public get transform(): NodeMaterialConnectionPoint {
  72. return this._inputs[1];
  73. }
  74. protected _buildBlock(state: NodeMaterialBuildState) {
  75. super._buildBlock(state);
  76. let vector = this.vector;
  77. let transform = this.transform;
  78. if (vector.connectedPoint) {
  79. // None uniform scaling case.
  80. if (this.complementW === 0) {
  81. let comments = `//${this.name}`;
  82. state._emitFunctionFromInclude("helperFunctions", comments);
  83. state.sharedData.blocksWithDefines.push(this);
  84. const transformName = state._getFreeVariableName(`${transform.associatedVariableName}_NUS`);
  85. state.compilationString += `mat3 ${transformName} = mat3(${transform.associatedVariableName});\r\n`;
  86. state.compilationString += `#ifdef NONUNIFORMSCALING\r\n`;
  87. state.compilationString += `${transformName} = transposeMat3(inverseMat3(${transformName}));\r\n`;
  88. state.compilationString += `#endif\r\n`;
  89. switch (vector.connectedPoint.type) {
  90. case NodeMaterialBlockConnectionPointTypes.Vector2:
  91. state.compilationString += this._declareOutput(this.output, state) + ` = vec4(${transformName} * vec3(${vector.associatedVariableName}, ${this._writeFloat(this.complementZ)}), ${this._writeFloat(this.complementW)});\r\n`;
  92. break;
  93. case NodeMaterialBlockConnectionPointTypes.Vector3:
  94. case NodeMaterialBlockConnectionPointTypes.Color3:
  95. state.compilationString += this._declareOutput(this.output, state) + ` = vec4(${transformName} * ${vector.associatedVariableName}, ${this._writeFloat(this.complementW)});\r\n`;
  96. break;
  97. default:
  98. state.compilationString += this._declareOutput(this.output, state) + ` = vec4(${transformName} * ${vector.associatedVariableName}.xyz, ${this._writeFloat(this.complementW)});\r\n`;
  99. break;
  100. }
  101. }
  102. else {
  103. const transformName = transform.associatedVariableName;
  104. switch (vector.connectedPoint.type) {
  105. case NodeMaterialBlockConnectionPointTypes.Vector2:
  106. state.compilationString += this._declareOutput(this.output, state) + ` = ${transformName} * vec4(${vector.associatedVariableName}, ${this._writeFloat(this.complementZ)}, ${this._writeFloat(this.complementW)});\r\n`;
  107. break;
  108. case NodeMaterialBlockConnectionPointTypes.Vector3:
  109. case NodeMaterialBlockConnectionPointTypes.Color3:
  110. state.compilationString += this._declareOutput(this.output, state) + ` = ${transformName} * vec4(${vector.associatedVariableName}, ${this._writeFloat(this.complementW)});\r\n`;
  111. break;
  112. default:
  113. state.compilationString += this._declareOutput(this.output, state) + ` = ${transformName} * ${vector.associatedVariableName};\r\n`;
  114. break;
  115. }
  116. }
  117. if (this.xyz.hasEndpoints) {
  118. state.compilationString += this._declareOutput(this.xyz, state) + ` = ${this.output.associatedVariableName}.xyz;\r\n`;
  119. }
  120. }
  121. return this;
  122. }
  123. /**
  124. * Update defines for shader compilation
  125. * @param mesh defines the mesh to be rendered
  126. * @param nodeMaterial defines the node material requesting the update
  127. * @param defines defines the material defines to update
  128. * @param useInstances specifies that instances should be used
  129. * @param subMesh defines which submesh to render
  130. */
  131. public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances: boolean = false, subMesh?: SubMesh) {
  132. // Do nothing
  133. if (mesh.nonUniformScaling) {
  134. defines.setValue("NONUNIFORMSCALING", true);
  135. }
  136. }
  137. public serialize(): any {
  138. let serializationObject = super.serialize();
  139. serializationObject.complementZ = this.complementZ;
  140. serializationObject.complementW = this.complementW;
  141. return serializationObject;
  142. }
  143. public _deserialize(serializationObject: any, scene: Scene, rootUrl: string) {
  144. super._deserialize(serializationObject, scene, rootUrl);
  145. this.complementZ = serializationObject.complementZ !== undefined ? serializationObject.complementZ : 0.0;
  146. this.complementW = serializationObject.complementW !== undefined ? serializationObject.complementW : 1.0;
  147. }
  148. protected _dumpPropertiesCode() {
  149. var codeString = `${this._codeVariableName}.complementZ = ${this.complementZ};\r\n`;
  150. codeString += `${this._codeVariableName}.complementW = ${this.complementW};\r\n`;
  151. return codeString;
  152. }
  153. }
  154. _TypeStore.RegisteredTypes["BABYLON.TransformBlock"] = TransformBlock;