mirror of
https://github.com/photonstorm/phaser
synced 2024-11-25 14:10:42 +00:00
Merged the Layer3D Game Object and pipeline back in for now
This commit is contained in:
parent
c3fe480905
commit
dda4431366
19 changed files with 3395 additions and 1 deletions
214
src/display/RGB.js
Normal file
214
src/display/RGB.js
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Class = require('../utils/Class');
|
||||||
|
var NOOP = require('../utils/NOOP');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* The RGB class holds a single color value and allows for easy modification and reading of it,
|
||||||
|
* with optional on-change callback notification and a dirty flag.
|
||||||
|
*
|
||||||
|
* @class RGB
|
||||||
|
* @memberof Phaser.Display
|
||||||
|
* @constructor
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} [red=0] - The red color value. A number between 0 and 1.
|
||||||
|
* @param {number} [green=0] - The green color value. A number between 0 and 1.
|
||||||
|
* @param {number} [blue=0] - The blue color value. A number between 0 and 1.
|
||||||
|
*/
|
||||||
|
var RGB = new Class({
|
||||||
|
|
||||||
|
initialize:
|
||||||
|
|
||||||
|
function RGB (red, green, blue)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Cached RGB values.
|
||||||
|
*
|
||||||
|
* @name Phaser.Display.RGB#_rgb
|
||||||
|
* @type {number[]}
|
||||||
|
* @private
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this._rgb = [ 0, 0, 0 ];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This callback will be invoked each time one of the RGB color values change.
|
||||||
|
*
|
||||||
|
* The callback is sent the new color values as the parameters.
|
||||||
|
*
|
||||||
|
* @name Phaser.Display.RGB#onChangeCallback
|
||||||
|
* @type {function}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.onChangeCallback = NOOP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this color dirty?
|
||||||
|
*
|
||||||
|
* @name Phaser.Display.RGB#dirty
|
||||||
|
* @type {boolean}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.dirty = false;
|
||||||
|
|
||||||
|
this.set(red, green, blue);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the red, green and blue values of this RGB object, flags it as being
|
||||||
|
* dirty and then invokes the `onChangeCallback`, if set.
|
||||||
|
*
|
||||||
|
* @method Phaser.Display.RGB#set
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} [red=0] - The red color value. A number between 0 and 1.
|
||||||
|
* @param {number} [green=0] - The green color value. A number between 0 and 1.
|
||||||
|
* @param {number} [blue=0] - The blue color value. A number between 0 and 1.
|
||||||
|
*
|
||||||
|
* @return {this} This RGB instance.
|
||||||
|
*/
|
||||||
|
set: function (red, green, blue)
|
||||||
|
{
|
||||||
|
if (red === undefined) { red = 0; }
|
||||||
|
if (green === undefined) { green = 0; }
|
||||||
|
if (blue === undefined) { blue = 0; }
|
||||||
|
|
||||||
|
this._rgb = [ red, green, blue ];
|
||||||
|
|
||||||
|
this.onChange();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the given rgb parameters with those in this object and returns
|
||||||
|
* a boolean `true` value if they are equal, otherwise it returns `false`.
|
||||||
|
*
|
||||||
|
* @method Phaser.Display.RGB#equals
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} red - The red value to compare with this object.
|
||||||
|
* @param {number} green - The green value to compare with this object.
|
||||||
|
* @param {number} blue - The blue value to compare with this object.
|
||||||
|
*
|
||||||
|
* @return {boolean} `true` if the given values match those in this object, otherwise `false`.
|
||||||
|
*/
|
||||||
|
equals: function (red, green, blue)
|
||||||
|
{
|
||||||
|
var rgb = this._rgb;
|
||||||
|
|
||||||
|
return (rgb.r === red && rgb.g === green && rgb.b === blue);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal on change handler. Sets this object as being dirty and
|
||||||
|
* then invokes the `onChangeCallback`, if set, passing in the
|
||||||
|
* new RGB values.
|
||||||
|
*
|
||||||
|
* @method Phaser.Display.RGB#onChange
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
onChange: function ()
|
||||||
|
{
|
||||||
|
this.dirty = true;
|
||||||
|
|
||||||
|
var rgb = this._rgb;
|
||||||
|
|
||||||
|
this.onChangeCallback.call(this, rgb[0], rgb[1], rgb[2]);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The red color value. Between 0 and 1.
|
||||||
|
*
|
||||||
|
* Changing this property will flag this RGB object as being dirty
|
||||||
|
* and invoke the `onChangeCallback` , if set.
|
||||||
|
*
|
||||||
|
* @name Phaser.Display.RGB#r
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
r: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this._rgb[0];
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this._rgb[0] = value;
|
||||||
|
this.onChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The green color value. Between 0 and 1.
|
||||||
|
*
|
||||||
|
* Changing this property will flag this RGB object as being dirty
|
||||||
|
* and invoke the `onChangeCallback` , if set.
|
||||||
|
*
|
||||||
|
* @name Phaser.Display.RGB#g
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
g: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this._rgb[1];
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this._rgb[1] = value;
|
||||||
|
this.onChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The blue color value. Between 0 and 1.
|
||||||
|
*
|
||||||
|
* Changing this property will flag this RGB object as being dirty
|
||||||
|
* and invoke the `onChangeCallback` , if set.
|
||||||
|
*
|
||||||
|
* @name Phaser.Display.RGB#b
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
b: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this._rgb[2];
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this._rgb[2] = value;
|
||||||
|
this.onChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nulls any external references this object contains.
|
||||||
|
*
|
||||||
|
* @method Phaser.Display.RGB#destroy
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
destroy: function ()
|
||||||
|
{
|
||||||
|
this.onChangeCallback = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = RGB;
|
|
@ -124,12 +124,15 @@ if (typeof WEBGL_RENDERER)
|
||||||
// WebGL only Game Objects
|
// WebGL only Game Objects
|
||||||
GameObjects.Shader = require('./shader/Shader');
|
GameObjects.Shader = require('./shader/Shader');
|
||||||
GameObjects.Mesh = require('./mesh/Mesh');
|
GameObjects.Mesh = require('./mesh/Mesh');
|
||||||
|
GameObjects.Layer3D = require('./layer3d/Layer3D');
|
||||||
|
|
||||||
GameObjects.Factories.Shader = require('./shader/ShaderFactory');
|
GameObjects.Factories.Shader = require('./shader/ShaderFactory');
|
||||||
GameObjects.Factories.Mesh = require('./mesh/MeshFactory');
|
GameObjects.Factories.Mesh = require('./mesh/MeshFactory');
|
||||||
|
GameObjects.Factories.Layer3D = require('./layer3d/Layer3DFactory');
|
||||||
|
|
||||||
GameObjects.Creators.Shader = require('./shader/ShaderCreator');
|
GameObjects.Creators.Shader = require('./shader/ShaderCreator');
|
||||||
GameObjects.Creators.Mesh = require('./mesh/MeshCreator');
|
GameObjects.Creators.Mesh = require('./mesh/MeshCreator');
|
||||||
|
GameObjects.Creators.Layer3D = require('./layer3d/Layer3DCreator');
|
||||||
|
|
||||||
GameObjects.Light = require('./lights/Light');
|
GameObjects.Light = require('./lights/Light');
|
||||||
GameObjects.LightsManager = require('./lights/LightsManager');
|
GameObjects.LightsManager = require('./lights/LightsManager');
|
||||||
|
|
575
src/gameobjects/layer3d/Layer3D.js
Normal file
575
src/gameobjects/layer3d/Layer3D.js
Normal file
|
@ -0,0 +1,575 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Class = require('../../utils/Class');
|
||||||
|
var Components = require('../components');
|
||||||
|
var CONST = require('../../renderer/webgl/pipelines/const');
|
||||||
|
var GameObject = require('../GameObject');
|
||||||
|
var GameObjectEvents = require('../events');
|
||||||
|
var Layer3DCamera = require('./Layer3DCamera');
|
||||||
|
var Layer3DLight = require('./Layer3DLight');
|
||||||
|
var Layer3DRender = require('./Layer3DRender');
|
||||||
|
var Model = require('../../geom/mesh/Model');
|
||||||
|
var RGB = require('../../display/RGB');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* A Layer3D Game Object.
|
||||||
|
*
|
||||||
|
* The Mesh object is WebGL only and does not have a Canvas counterpart.
|
||||||
|
*
|
||||||
|
* TODO - Finish this.
|
||||||
|
*
|
||||||
|
* @class Layer3D
|
||||||
|
* @extends Phaser.GameObjects.GameObject
|
||||||
|
* @memberof Phaser.GameObjects
|
||||||
|
* @constructor
|
||||||
|
* @webglOnly
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @extends Phaser.GameObjects.Components.AlphaSingle
|
||||||
|
* @extends Phaser.GameObjects.Components.BlendMode
|
||||||
|
* @extends Phaser.GameObjects.Components.Depth
|
||||||
|
* @extends Phaser.GameObjects.Components.Mask
|
||||||
|
* @extends Phaser.GameObjects.Components.Pipeline
|
||||||
|
* @extends Phaser.GameObjects.Components.Transform
|
||||||
|
* @extends Phaser.GameObjects.Components.Visible
|
||||||
|
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||||
|
* @extends Phaser.GameObjects.Components.Size
|
||||||
|
*
|
||||||
|
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
|
||||||
|
* @param {number} [x] - The horizontal position of this Game Object in the world.
|
||||||
|
* @param {number} [y] - The vertical position of this Game Object in the world.
|
||||||
|
*/
|
||||||
|
var Layer3D = new Class({
|
||||||
|
|
||||||
|
Extends: GameObject,
|
||||||
|
|
||||||
|
Mixins: [
|
||||||
|
Components.AlphaSingle,
|
||||||
|
Components.BlendMode,
|
||||||
|
Components.Depth,
|
||||||
|
Components.Mask,
|
||||||
|
Components.Pipeline,
|
||||||
|
Components.Transform,
|
||||||
|
Components.Visible,
|
||||||
|
Components.ScrollFactor,
|
||||||
|
Components.Size,
|
||||||
|
Layer3DRender
|
||||||
|
],
|
||||||
|
|
||||||
|
initialize:
|
||||||
|
|
||||||
|
function Layer3D (scene, x, y)
|
||||||
|
{
|
||||||
|
GameObject.call(this, scene, 'Layer3D');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Camera which can be used to control the view of the models being managed
|
||||||
|
* by this Layer3D. It will default to have an fov of 45 and be positioned at 0, 0, -10,
|
||||||
|
* with a near of 0.01 and far of 1000. You can change all of these by using the
|
||||||
|
* methods and properties available on the `Layer3DCamera` class.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3D#camera
|
||||||
|
* @type {Phaser.GameObjects.Layer3DCamera}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.camera = new Layer3DCamera(this, 45, 0, 0, -10, 0.01, 1000);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An ambient light source for the entire Layer3D scene and all models it is rendering.
|
||||||
|
*
|
||||||
|
* It is created at a position of 0, -100, 0 with full ambient, diffuse and specular
|
||||||
|
* values. You can change all of these by using the methods and properties
|
||||||
|
* available on the `Layer3DLight` class.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3D#light
|
||||||
|
* @type {Phaser.GameObjects.Layer3DLight}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.light = new Layer3DLight(this, 0, 100, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color of the fog.
|
||||||
|
*
|
||||||
|
* By default it is 0,0,0, which is black.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3D#fogColor
|
||||||
|
* @type {Phaser.Display.RGB}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.fogColor = new RGB();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum distance from which fog starts to affect objects closer than it.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3D#fogNear
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.fogNear = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum distance from which fog starts to affect objects further than it.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3D#fogFar
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.fogFar = Infinity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of model instances that have been created in this Layer3D.
|
||||||
|
*
|
||||||
|
* This array can be sorted, by your own functions, to control model rendering order.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3D#models
|
||||||
|
* @type {Phaser.Geom.Mesh.Model[]}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.models = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal cached value.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3D#_prevWidth
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this._prevWidth = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal cached value.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3D#_prevHeight
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this._prevHeight = 0;
|
||||||
|
|
||||||
|
var renderer = scene.sys.renderer;
|
||||||
|
|
||||||
|
this.setPosition(x, y);
|
||||||
|
this.setSize(renderer.width, renderer.height);
|
||||||
|
this.initPipeline(CONST.MESH_PIPELINE);
|
||||||
|
|
||||||
|
this.on(GameObjectEvents.ADDED_TO_SCENE, this.addedToScene, this);
|
||||||
|
this.on(GameObjectEvents.REMOVED_FROM_SCENE, this.removedFromScene, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Overrides Game Object method
|
||||||
|
addedToScene: function ()
|
||||||
|
{
|
||||||
|
this.scene.sys.updateList.add(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Overrides Game Object method
|
||||||
|
removedFromScene: function ()
|
||||||
|
{
|
||||||
|
this.scene.sys.updateList.remove(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all models from this Layer3D, calling `destroy` on each one of them.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#clearModels
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
clearModels: function ()
|
||||||
|
{
|
||||||
|
var models = this.models;
|
||||||
|
|
||||||
|
for (var i = 0; i < models.length; i++)
|
||||||
|
{
|
||||||
|
models[i].destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.models = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates a new blank Model instance and adds it to this Layer3D.
|
||||||
|
*
|
||||||
|
* You still need to tell it how many vertices it's going to contain in total, but you can
|
||||||
|
* populate the vertex data at a later stage after calling this. It won't try to render
|
||||||
|
* while it has no vertices.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#addModel
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} verticesCount - The total number of vertices this model can contain.
|
||||||
|
* @param {string|Phaser.Textures.Texture} [texture] - The key, or instance of the Texture this model will use to render with, as stored in the Texture Manager.
|
||||||
|
* @param {string|integer} [frame] - An optional frame from the Texture this model is rendering with. Ensure your UV data also matches this frame.
|
||||||
|
* @param {number} [x=0] - The x position of the Model.
|
||||||
|
* @param {number} [y=0] - The y position of the Model.
|
||||||
|
* @param {number} [z=0] - The z position of the Model.
|
||||||
|
*
|
||||||
|
* @return {Phaser.Geom.Mesh.Model} The model instance that was created.
|
||||||
|
*/
|
||||||
|
addModel: function (verticesCount, texture, frame, x, y, z)
|
||||||
|
{
|
||||||
|
var model = new Model(this, verticesCount, texture, frame, x, y, z);
|
||||||
|
|
||||||
|
this.models.push(model);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates a new Model based on a loaded triangulated Wavefront OBJ.
|
||||||
|
*
|
||||||
|
* The obj file should have been loaded via OBJFile:
|
||||||
|
*
|
||||||
|
* ```javascript
|
||||||
|
* this.load.obj(key, url, [ flipUV ]);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Then use the key it was loaded under in this method.
|
||||||
|
*
|
||||||
|
* If the model has a texture, you must provide it as the second parameter.
|
||||||
|
*
|
||||||
|
* The model is then added to this Layer3D. A single Layer3D can contain multiple models
|
||||||
|
* without impacting each other. Equally, multiple models can all share the same base OBJ
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* Make sure your 3D package has triangulated the model data prior to exporting it.
|
||||||
|
*
|
||||||
|
* You can scale the model data during import, which will set the new 'base' scale for the model.
|
||||||
|
*
|
||||||
|
* You can also offset the models generated vertex positions via the `originX`, `originY` and `originZ`
|
||||||
|
* parameters, which will change the rotation origin of the model. The model itself can be positioned,
|
||||||
|
* rotated and scaled independantly of these settings, so don't use them to position the model, just
|
||||||
|
* use them to offset the base values.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#addModelFromOBJ
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {string} key - The key of the data in the OBJ Cache to create the model from.
|
||||||
|
* @param {string|Phaser.Textures.Texture} [texture] - The key, or instance of the Texture this model will use to render with, as stored in the Texture Manager.
|
||||||
|
* @param {string|integer} [frame] - An optional frame from the Texture this model is rendering with. Ensure your UV data also matches this frame.
|
||||||
|
* @param {number} [scale=1] - An amount to scale the model data by during creation.
|
||||||
|
* @param {number} [originX=0] - The x origin of the model vertices during creation.
|
||||||
|
* @param {number} [originY=0] - The y origin of the model vertices during creation.
|
||||||
|
* @param {number} [originZ=0] - The z origin of the model vertices during creation.
|
||||||
|
*
|
||||||
|
* @return {Phaser.Geom.Mesh.Model|Phaser.Geom.Mesh.Model[]} The Model instance that was created. If the OBJ contained multiple models then an array of Model instances is returned.
|
||||||
|
*/
|
||||||
|
addModelFromOBJ: function (key, texture, frame, scale, originX, originY, originZ)
|
||||||
|
{
|
||||||
|
var model = [];
|
||||||
|
var data = this.scene.sys.cache.obj.get(key);
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
model = this.addModelFromData(data, texture, frame, scale, originX, originY, originZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (model.length === 1) ? model[0] : model;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates a new Model based on the parsed triangulated model data.
|
||||||
|
*
|
||||||
|
* The data should have been parsed in advance via a function such as `ParseObj`:
|
||||||
|
*
|
||||||
|
* ```javascript
|
||||||
|
* const data = Phaser.Geom.Mesh.ParseObj(rawData, flipUV);
|
||||||
|
*
|
||||||
|
* Layer3D.addModelFromData(data, texture, frame);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If the model has a texture, you must provide it as the second parameter.
|
||||||
|
*
|
||||||
|
* The model is then added to this Layer3D. A single Layer3D can contain multiple models
|
||||||
|
* without impacting each other. Equally, multiple models can all share the same base OBJ
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* Make sure your 3D package has triangulated the model data prior to exporting it.
|
||||||
|
*
|
||||||
|
* You can scale the model data during import, which will set the new 'base' scale for the model.
|
||||||
|
*
|
||||||
|
* You can also offset the models generated vertex positions via the `originX`, `originY` and `originZ`
|
||||||
|
* parameters, which will change the rotation origin of the model. The model itself can be positioned,
|
||||||
|
* rotated and scaled independantly of these settings, so don't use them to position the model, just
|
||||||
|
* use them to offset the base values.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#addModelFromData
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {array} data - The parsed model data.
|
||||||
|
* @param {string|Phaser.Textures.Texture} [texture] - The key, or instance of the Texture this model will use to render with, as stored in the Texture Manager.
|
||||||
|
* @param {string|integer} [frame] - An optional frame from the Texture this model is rendering with. Ensure your UV data also matches this frame.
|
||||||
|
* @param {number} [scale=1] - An amount to scale the model data by during creation.
|
||||||
|
* @param {number} [originX=0] - The x origin of the model vertices during creation.
|
||||||
|
* @param {number} [originY=0] - The y origin of the model vertices during creation.
|
||||||
|
* @param {number} [originZ=0] - The z origin of the model vertices during creation.
|
||||||
|
*
|
||||||
|
* @return {Phaser.Geom.Mesh.Model|Phaser.Geom.Mesh.Model[]} The Model instance that was created. If the data contained multiple models then an array of Model instances is returned.
|
||||||
|
*/
|
||||||
|
addModelFromData: function (data, texture, frame, scale, originX, originY, originZ)
|
||||||
|
{
|
||||||
|
if (scale === undefined) { scale = 1; }
|
||||||
|
if (originX === undefined) { originX = 0; }
|
||||||
|
if (originY === undefined) { originY = 0; }
|
||||||
|
if (originZ === undefined) { originZ = 0; }
|
||||||
|
|
||||||
|
var results = [];
|
||||||
|
|
||||||
|
for (var m = 0; m < data.models.length; m++)
|
||||||
|
{
|
||||||
|
var modelData = data.models[m];
|
||||||
|
|
||||||
|
var vertices = modelData.vertices;
|
||||||
|
var textureCoords = modelData.textureCoords;
|
||||||
|
var normals = modelData.vertexNormals;
|
||||||
|
var faces = modelData.faces;
|
||||||
|
|
||||||
|
var model = this.addModel(faces.length * 3, texture, frame);
|
||||||
|
|
||||||
|
var defaultUV1 = { u: 0, v: 1 };
|
||||||
|
var defaultUV2 = { u: 0, v: 0 };
|
||||||
|
var defaultUV3 = { u: 1, v: 1 };
|
||||||
|
|
||||||
|
for (var i = 0; i < faces.length; i++)
|
||||||
|
{
|
||||||
|
var face = faces[i];
|
||||||
|
|
||||||
|
// {textureCoordsIndex: 0, vertexIndex: 16, vertexNormalIndex: 16}
|
||||||
|
var v1 = face.vertices[0];
|
||||||
|
var v2 = face.vertices[1];
|
||||||
|
var v3 = face.vertices[2];
|
||||||
|
|
||||||
|
// {x: 0.19509, y: 0.980785, z: 0}
|
||||||
|
var m1 = vertices[v1.vertexIndex];
|
||||||
|
var m2 = vertices[v2.vertexIndex];
|
||||||
|
var m3 = vertices[v3.vertexIndex];
|
||||||
|
|
||||||
|
var n1 = normals[v1.vertexNormalIndex];
|
||||||
|
var n2 = normals[v2.vertexNormalIndex];
|
||||||
|
var n3 = normals[v3.vertexNormalIndex];
|
||||||
|
|
||||||
|
var t1 = v1.textureCoordsIndex;
|
||||||
|
var t2 = v2.textureCoordsIndex;
|
||||||
|
var t3 = v3.textureCoordsIndex;
|
||||||
|
|
||||||
|
var uv1 = (t1 === -1) ? defaultUV1 : textureCoords[t1];
|
||||||
|
var uv2 = (t2 === -1) ? defaultUV2 : textureCoords[t2];
|
||||||
|
var uv3 = (t3 === -1) ? defaultUV3 : textureCoords[t3];
|
||||||
|
|
||||||
|
model.addVertex(originX + m1.x * scale, originY + m1.y * scale, originZ + m1.z * scale, uv1.u, uv1.v, n1.x, n1.y, n1.z);
|
||||||
|
model.addVertex(originX + m2.x * scale, originY + m2.y * scale, originZ + m2.z * scale, uv2.u, uv2.v, n2.x, n2.y, n2.z);
|
||||||
|
model.addVertex(originX + m3.x * scale, originY + m3.y * scale, originZ + m3.z * scale, uv3.u, uv3.v, n3.x, n3.y, n3.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
results.push(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates a new Model based on the given triangulated vertices arrays.
|
||||||
|
*
|
||||||
|
* Adds vertices to this model by parsing the given arrays.
|
||||||
|
*
|
||||||
|
* This method will take vertex data in one of two formats, based on the `containsZ` parameter.
|
||||||
|
*
|
||||||
|
* If your vertex data are `x`, `y` pairs, then `containsZ` should be `false` (this is the default)
|
||||||
|
*
|
||||||
|
* If your vertex data is groups of `x`, `y` and `z` values, then the `containsZ` parameter must be true.
|
||||||
|
*
|
||||||
|
* The `uvs` parameter is a numeric array consisting of `u` and `v` pairs.
|
||||||
|
* The `normals` parameter is a numeric array consisting of `x`, `y` vertex normal values and, if `containsZ` is true, `z` values as well.
|
||||||
|
* The `indicies` parameter is an optional array that, if given, is an indexed list of vertices to be added.
|
||||||
|
*
|
||||||
|
* The following example will create a 256 x 256 sized quad using an index array:
|
||||||
|
*
|
||||||
|
* ```javascript
|
||||||
|
* const vertices = [
|
||||||
|
* -128, 128,
|
||||||
|
* 128, 128,
|
||||||
|
* -128, -128,
|
||||||
|
* 128, -128
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* const uvs = [
|
||||||
|
* 0, 1,
|
||||||
|
* 1, 1,
|
||||||
|
* 0, 0,
|
||||||
|
* 1, 0
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* const indices = [ 0, 2, 1, 2, 3, 1 ];
|
||||||
|
*
|
||||||
|
* Layer3D.addModelFromVertices(vertices, uvs, indicies);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* You cannot add more vertices to a model than the total specified when the model was created.
|
||||||
|
* If you need to clear all vertices first, call `Model.resetVertices`.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#addModelFromVertices
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number[]} vertices - The vertices array. Either `xy` pairs, or `xyz` if the `containsZ` parameter is `true`.
|
||||||
|
* @param {number[]} uvs - The UVs pairs array.
|
||||||
|
* @param {number[]} [normals] - Optional vertex normals array. If you don't have one, pass `null` or an empty array.
|
||||||
|
* @param {number[]} [indicies] - Optional vertex indicies array. If you don't have one, pass `null` or an empty array.
|
||||||
|
* @param {boolean} [containsZ=false] - Does the vertices data include a `z` component?
|
||||||
|
* @param {string|Phaser.Textures.Texture} [texture] - The key, or instance of the Texture the model will use to render with, as stored in the Texture Manager.
|
||||||
|
* @param {string|integer} [frame] - An optional frame from the Texture the model is rendering with.
|
||||||
|
*
|
||||||
|
* @return {Phaser.Geom.Mesh.Model} The Model instance that was created.
|
||||||
|
*/
|
||||||
|
addModelFromVertices: function (vertices, uvs, normals, indicies, containsZ, texture, frame)
|
||||||
|
{
|
||||||
|
var isIndexed = (Array.isArray(indicies) && indicies.length > 0);
|
||||||
|
|
||||||
|
var verticesCount = (isIndexed) ? indicies.length : vertices.length;
|
||||||
|
|
||||||
|
if (!isIndexed)
|
||||||
|
{
|
||||||
|
verticesCount /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
var model = this.addModel(verticesCount, texture, frame, 0, 0, 0);
|
||||||
|
|
||||||
|
model.addVertices(vertices, uvs, normals, indicies, containsZ);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the fog values for this Layer3D, including the fog color and the near and
|
||||||
|
* far distance values.
|
||||||
|
*
|
||||||
|
* By default, fog effects all models in this layer.
|
||||||
|
*
|
||||||
|
* If you do not wish to have a fog effect, see the `disableFog` method.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#setFog
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} red - The red color component of the fog. A value between 0 and 1.
|
||||||
|
* @param {number} green - The green color component of the fog. A value between 0 and 1.
|
||||||
|
* @param {number} blue - The blue color component of the fog. A value between 0 and 1.
|
||||||
|
* @param {number} [near] - The 'near' value of the fog.
|
||||||
|
* @param {number} [far] - The 'far' value of the fog, beyond which objects are 'fogged' out.
|
||||||
|
*
|
||||||
|
* @return {this} This Layer3D Game Object.
|
||||||
|
*/
|
||||||
|
setFog: function (red, green, blue, near, far)
|
||||||
|
{
|
||||||
|
if (near === undefined) { near = this.fogNear; }
|
||||||
|
if (far === undefined) { far = this.fogFar; }
|
||||||
|
|
||||||
|
this.fogColor.set(red, green, blue);
|
||||||
|
|
||||||
|
this.fogNear = near;
|
||||||
|
this.fogFar = far;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables fog for this Layer3D and all models it renders.
|
||||||
|
*
|
||||||
|
* To re-enable fog, just call `setFog` and provide new color, near and far values.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#disableFog
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @return {this} This Layer3D Game Object.
|
||||||
|
*/
|
||||||
|
disableFog: function ()
|
||||||
|
{
|
||||||
|
this.fogFar = Infinity;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Layer3D update loop.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#preUpdate
|
||||||
|
* @protected
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} time - The current timestamp.
|
||||||
|
* @param {number} delta - The delta time, in ms, elapsed since the last frame.
|
||||||
|
*/
|
||||||
|
preUpdate: function (time, delta)
|
||||||
|
{
|
||||||
|
var width = this.width;
|
||||||
|
var height = this.height;
|
||||||
|
|
||||||
|
var camera = this.camera;
|
||||||
|
|
||||||
|
if (camera.dirtyProjection || width !== this._prevWidth || height !== this._prevHeight)
|
||||||
|
{
|
||||||
|
camera.updateProjectionMatrix(width, height);
|
||||||
|
|
||||||
|
this._prevWidth = width;
|
||||||
|
this._prevHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
var models = this.models;
|
||||||
|
|
||||||
|
for (var i = 0; i < models.length; i++)
|
||||||
|
{
|
||||||
|
var model = models[i];
|
||||||
|
|
||||||
|
if (model.visible)
|
||||||
|
{
|
||||||
|
model.preUpdate(time, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets all of the dirty cache values this Layer3D object uses.
|
||||||
|
*
|
||||||
|
* This is called automatically at the end of the render step.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#resetDirtyFlags
|
||||||
|
* @protected
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
resetDirtyFlags: function ()
|
||||||
|
{
|
||||||
|
this.camera.dirtyView = false;
|
||||||
|
this.camera.dirtyProjection = false;
|
||||||
|
|
||||||
|
this.light.ambient.dirty = false;
|
||||||
|
this.light.diffuse.dirty = false;
|
||||||
|
this.light.specular.dirty = false;
|
||||||
|
|
||||||
|
this.fogColor.dirty = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The destroy step for this Layer3D, which removes all models, destroys the camera and
|
||||||
|
* nulls external references.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#preDestroy
|
||||||
|
* @private
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
preDestroy: function ()
|
||||||
|
{
|
||||||
|
this.clearModels();
|
||||||
|
|
||||||
|
this.camera.destroy();
|
||||||
|
this.light.destroy();
|
||||||
|
|
||||||
|
this.camera = null;
|
||||||
|
this.light = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Layer3D;
|
716
src/gameobjects/layer3d/Layer3DCamera.js
Normal file
716
src/gameobjects/layer3d/Layer3DCamera.js
Normal file
|
@ -0,0 +1,716 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Class = require('../../utils/Class');
|
||||||
|
var DegToRad = require('../../math/DegToRad');
|
||||||
|
var GetFastValue = require('../../utils/object/GetFastValue');
|
||||||
|
var INPUT_EVENTS = require('../../input/events');
|
||||||
|
var Matrix4 = require('../../math/Matrix4');
|
||||||
|
var Vector3 = require('../../math/Vector3');
|
||||||
|
var Vector4 = require('../../math/Vector4');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* The Layer3D Camera.
|
||||||
|
*
|
||||||
|
* @class Layer3DCamera
|
||||||
|
* @memberof Phaser.GameObjects
|
||||||
|
* @constructor
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
var Layer3DCamera = new Class({
|
||||||
|
|
||||||
|
initialize:
|
||||||
|
|
||||||
|
function Layer3DCamera (layer, fov, x, y, z, near, far)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The Layer3D instance this camera belongs to.
|
||||||
|
*
|
||||||
|
* A camera can only belong to a single Layer3D instance.
|
||||||
|
*
|
||||||
|
* You should consider this property as being read-only. You cannot move a
|
||||||
|
* camera to another Layer3D by simply changing it.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#layer
|
||||||
|
* @type {Phaser.GameObjects.Layer3D}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.layer = layer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Scene Input Plugin, as referenced via the Layer3D parent.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#input
|
||||||
|
* @type {Phaser.Input.InputPlugin}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.input = layer.scene.sys.input;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal 'dirty' flag that tells the parent Layer3D if the
|
||||||
|
* view matrix of this camera needs recalculating at the next step.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#dirtyView
|
||||||
|
* @type {boolean}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.dirtyView = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal 'dirty' flag that tells the parent Layer3D if the
|
||||||
|
* projection matrix of this camera needs recalculating at the next step.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#dirtyProjection
|
||||||
|
* @type {boolean}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.dirtyProjection = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal fov value.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#_fov
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this._fov = fov;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal near value.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#_near
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this._near = near;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal far value.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#_far
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this._far = far;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The aspect ratio of the camera.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#aspectRatio
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.aspectRatio = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The position of the camera in 3D space.
|
||||||
|
*
|
||||||
|
* You can modify this vector directly, or use the `x`, `y` and `z`
|
||||||
|
* properties of this class.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#position
|
||||||
|
* @type {Phaser.Math.Vector3}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.position = new Vector3(x, y, z);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rotation of the camera in 3D space.
|
||||||
|
*
|
||||||
|
* You can modify this vector directly, or use the `rotationX`, `rotationY`
|
||||||
|
* and `rotationZ` properties of this class.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#rotation
|
||||||
|
* @type {Phaser.Math.Vector3}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.rotation = new Vector3();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The forward facing vector of the camera.
|
||||||
|
*
|
||||||
|
* Calculated and updated automatically when the view matrix changes.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#forward
|
||||||
|
* @type {Phaser.Math.Vector4}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.forward = new Vector4();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The upward facing vector of the camera.
|
||||||
|
* Invert it to get the bottom vector.
|
||||||
|
*
|
||||||
|
* Calculated and updated automatically when the view matrix changes.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#up
|
||||||
|
* @type {Phaser.Math.Vector4}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.up = new Vector4();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The right facing vector of the camera.
|
||||||
|
* Invert it to get the left vector.
|
||||||
|
*
|
||||||
|
* Calculated and updated automatically when the view matrix changes.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#right
|
||||||
|
* @type {Phaser.Math.Vector4}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.right = new Vector4();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal transform matrix.
|
||||||
|
*
|
||||||
|
* Calculated and updated automatically when the camera is dirty.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#matrix
|
||||||
|
* @type {Phaser.Math.Matrix4}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.matrix = new Matrix4();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The inverse of the transform matrix.
|
||||||
|
*
|
||||||
|
* Calculated and updated automatically when the camera is dirty.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#viewMatrix
|
||||||
|
* @type {Phaser.Math.Matrix4}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.viewMatrix = new Matrix4();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The perspective projection matrix.
|
||||||
|
*
|
||||||
|
* Calculated and updated automatically when the camera is dirty.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#projectionMatrix
|
||||||
|
* @type {Phaser.Math.Matrix4}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.projectionMatrix = new Matrix4();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The perspective projection matrix, multiplied by the view matrix.
|
||||||
|
*
|
||||||
|
* Calculated and updated automatically when the camera is dirty.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#viewProjectionMatrix
|
||||||
|
* @type {Phaser.Math.Matrix4}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.viewProjectionMatrix = new Matrix4();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The movement and rotation mode of this camera.
|
||||||
|
* Either ORBIT, or FREE.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#mode
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.mode = Layer3DCamera.MODE_ORBIT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How fast to rotate the camera, in degrees per delta.
|
||||||
|
*
|
||||||
|
* This value is only used after calling the `enableControls` method,
|
||||||
|
* it does not influence changing the rotation values directly.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#rotateSpeed
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.rotateSpeed = 0.5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How fast to pan the camera, in units per delta.
|
||||||
|
*
|
||||||
|
* This value is only used after calling the `enableControls` method,
|
||||||
|
* it does not influence calling the pan methods directly.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#panSpeed
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.panSpeed = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How fast to zoom the camera.
|
||||||
|
*
|
||||||
|
* This value is only used after calling the `enableControls` method,
|
||||||
|
* it does not influence calling the panZ method directly.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#zoomSpeed
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.zoomSpeed = 3;
|
||||||
|
|
||||||
|
this.allowPan = false;
|
||||||
|
|
||||||
|
this.lockXAxis = false;
|
||||||
|
this.lockYAxis = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
enableOrbitControls: function (config)
|
||||||
|
{
|
||||||
|
this.rotateSpeed = GetFastValue(config, 'rotateSpeed', this.rotateSpeed);
|
||||||
|
this.panSpeed = GetFastValue(config, 'panSpeed', this.panSpeed);
|
||||||
|
this.allowPan = GetFastValue(config, 'allowPan', this.allowPan);
|
||||||
|
this.lockXAxis = GetFastValue(config, 'lockXAxis', this.lockXAxis);
|
||||||
|
this.lockYAxis = GetFastValue(config, 'lockYAxis', this.lockYAxis);
|
||||||
|
|
||||||
|
this.input.on(INPUT_EVENTS.POINTER_MOVE, this.pointerMoveHandler, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
disableOrbitControls: function ()
|
||||||
|
{
|
||||||
|
this.input.off(INPUT_EVENTS.POINTER_MOVE, this.pointerMoveHandler, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
enableZoom: function (zoomSpeed)
|
||||||
|
{
|
||||||
|
if (zoomSpeed === undefined) { zoomSpeed = 3; }
|
||||||
|
|
||||||
|
this.zoomSpeed = zoomSpeed;
|
||||||
|
|
||||||
|
this.input.on(INPUT_EVENTS.POINTER_WHEEL, this.pointerWheelHandler, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
disableZoom: function ()
|
||||||
|
{
|
||||||
|
this.input.off(INPUT_EVENTS.POINTER_WHEEL, this.pointerWheelHandler, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
pointerMoveHandler: function (pointer)
|
||||||
|
{
|
||||||
|
if (pointer.isDown)
|
||||||
|
{
|
||||||
|
var width = this.layer.width;
|
||||||
|
var height = this.layer.height;
|
||||||
|
|
||||||
|
if (pointer.event.shiftKey && this.allowPan)
|
||||||
|
{
|
||||||
|
this.panX(pointer.velocity.x * (this.panSpeed / width));
|
||||||
|
this.panY(pointer.velocity.y * (this.panSpeed / height));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!this.lockXAxis)
|
||||||
|
{
|
||||||
|
this.rotationX -= pointer.velocity.y * (this.rotateSpeed / height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.lockYAxis)
|
||||||
|
{
|
||||||
|
this.rotationY -= pointer.velocity.x * (this.rotateSpeed / width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
pointerWheelHandler: function (pointer, over, deltaX, deltaY)
|
||||||
|
{
|
||||||
|
this.panZ(deltaY * (this.zoomSpeed / this.layer.height));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pans this camera on the x axis by the given amount.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DCamera#panX
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} v - The amount to pan by.
|
||||||
|
*/
|
||||||
|
panX: function (v)
|
||||||
|
{
|
||||||
|
this.updateViewMatrix();
|
||||||
|
|
||||||
|
this.position.addScale(this.right, v);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pans this camera on the y axis by the given amount.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DCamera#panY
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} v - The amount to pan by.
|
||||||
|
*/
|
||||||
|
panY: function (v)
|
||||||
|
{
|
||||||
|
this.updateViewMatrix();
|
||||||
|
|
||||||
|
this.y += this.up.y * v;
|
||||||
|
|
||||||
|
if (this.mode === Layer3DCamera.MODE_ORBIT)
|
||||||
|
{
|
||||||
|
// Can only move up and down the y axis in orbit mode
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.x += this.up.x * v;
|
||||||
|
this.z += this.up.z * v;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pans this camera on the z axis by the given amount.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DCamera#panZ
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} v - The amount to pan by.
|
||||||
|
*/
|
||||||
|
panZ: function (v)
|
||||||
|
{
|
||||||
|
this.updateViewMatrix();
|
||||||
|
|
||||||
|
if (this.mode === Layer3DCamera.MODE_ORBIT)
|
||||||
|
{
|
||||||
|
// Orbit mode translates after rotatation, so only need to set Z. The rotation will handle the rest.
|
||||||
|
this.z += v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// In freemode to move forward, we move based on our forward, which is relative to our current rotation.
|
||||||
|
this.position.addScale(this.forward, v);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal method that is called by the Layer3D instance that owns this camera
|
||||||
|
* during its `render` step. If the view matrix is dirty, it is recalculated
|
||||||
|
* and then applied to the view projection matrix, ready for rendering.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DCamera#update
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
update: function ()
|
||||||
|
{
|
||||||
|
if (this.dirtyView)
|
||||||
|
{
|
||||||
|
this.updateViewMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.dirtyView || this.dirtyProjection)
|
||||||
|
{
|
||||||
|
this.projectionMatrix.multiplyToMat4(this.viewMatrix, this.viewProjectionMatrix);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal method that handles the update of the view transform matrix, based on the rotation
|
||||||
|
* and position of the camera. Called automatically when the camera is updated.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DCamera#updateViewMatrix
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
updateViewMatrix: function ()
|
||||||
|
{
|
||||||
|
var matView = this.matrix;
|
||||||
|
|
||||||
|
if (this.mode === Layer3DCamera.MODE_FREE)
|
||||||
|
{
|
||||||
|
matView.fromRotationXYTranslation(this.rotation, this.position, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matView.fromRotationXYTranslation(this.rotation, this.position, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateDirection();
|
||||||
|
|
||||||
|
this.viewMatrix.copy(matView).invert();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal method that is called by the Layer3D instance that owns this camera
|
||||||
|
* during its `preUpdate` step. If the projection matrix is dirty, or the renderer
|
||||||
|
* width or height has changed, then a new projection matrix is calculated.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DCamera#updateProjectionMatrix
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} width - The width of the renderer.
|
||||||
|
* @param {number} height - The height of the renderer.
|
||||||
|
*/
|
||||||
|
updateProjectionMatrix: function (width, height)
|
||||||
|
{
|
||||||
|
this.aspectRatio = width / height;
|
||||||
|
|
||||||
|
this.projectionMatrix.perspective(DegToRad(this._fov), this.aspectRatio, this._near, this._far);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal method that sets the forward, up and right vectors from
|
||||||
|
* the view matrix. This is called automatically as part of the
|
||||||
|
* `updateViewMatrix` method.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DCamera#updateDirection
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
updateDirection: function ()
|
||||||
|
{
|
||||||
|
var matView = this.matrix;
|
||||||
|
|
||||||
|
this.forward.set(0, 0, 1, 0).transformMat4(matView);
|
||||||
|
this.up.set(0, 1, 0, 0).transformMat4(matView);
|
||||||
|
this.right.set(1, 0, 0, 0).transformMat4(matView);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The field of view, in degrees, of this camera.
|
||||||
|
*
|
||||||
|
* Limited to the range of 0 to 180.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#fov
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
fov: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this._fov;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
if (value > 0 && value < 180)
|
||||||
|
{
|
||||||
|
this._fov = value;
|
||||||
|
this.dirtyProjection = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum distance the camera can see from.
|
||||||
|
*
|
||||||
|
* It's important to consider that depth buffers are not infinite and the closer
|
||||||
|
* a camera starts, the more you may encounter depth fighting issues.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#near
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
near: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this._near;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
if (value > 0)
|
||||||
|
{
|
||||||
|
this._near = value;
|
||||||
|
this.dirtyProjection = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum distance the camera can see to.
|
||||||
|
*
|
||||||
|
* It's important to consider that depth buffers are not infinite and the further
|
||||||
|
* a camera ends, the more you may encounter depth fighting issues.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#far
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
far: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this._far;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
if (value > 0)
|
||||||
|
{
|
||||||
|
this._far = value;
|
||||||
|
this.dirtyProjection = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The x position of the camera.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#x
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
x: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.position.x;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.position.x = value;
|
||||||
|
this.dirtyView = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The y position of the camera.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#y
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
y: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.position.y;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.position.y = value;
|
||||||
|
this.dirtyView = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The z position of the camera.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#z
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
z: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.position.z;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.position.z = value;
|
||||||
|
this.dirtyView = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The x axis rotation, in radians, of the camera.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#rotationX
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
rotationX: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.rotation.x;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.rotation.x = value;
|
||||||
|
this.dirtyView = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The y axis rotation, in radians, of the camera.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#rotationY
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
rotationY: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.rotation.y;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.rotation.y = value;
|
||||||
|
this.dirtyView = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The z axis rotation, in radians, of the camera.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DCamera#rotationZ
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
rotationZ: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.rotation.z;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.rotation.z = value;
|
||||||
|
this.dirtyView = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy handler for this camera.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DCamera#destroy
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
destroy: function ()
|
||||||
|
{
|
||||||
|
this.layer = null;
|
||||||
|
this.position = null;
|
||||||
|
this.rotation = null;
|
||||||
|
this.forward = null;
|
||||||
|
this.up = null;
|
||||||
|
this.right = null;
|
||||||
|
this.matrix = null;
|
||||||
|
this.viewMatrix = null;
|
||||||
|
this.projectionMatrix = null;
|
||||||
|
this.viewProjectionMatrix = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Allows free movement of position and rotation
|
||||||
|
Layer3DCamera.MODE_FREE = 0;
|
||||||
|
|
||||||
|
// Movement is locked to rotate around the origin
|
||||||
|
Layer3DCamera.MODE_ORBIT = 1;
|
||||||
|
|
||||||
|
module.exports = Layer3DCamera;
|
22
src/gameobjects/layer3d/Layer3DCanvasRenderer.js
Normal file
22
src/gameobjects/layer3d/Layer3DCanvasRenderer.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a stub function for Layer3D.Render. There is no Canvas renderer for Layer3D objects.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#renderCanvas
|
||||||
|
* @since 3.50.0
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
|
||||||
|
* @param {Phaser.GameObjects.Layer3D} src - The Game Object being rendered in this call.
|
||||||
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
||||||
|
*/
|
||||||
|
var Layer3DCanvasRenderer = function ()
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Layer3DCanvasRenderer;
|
40
src/gameobjects/layer3d/Layer3DCreator.js
Normal file
40
src/gameobjects/layer3d/Layer3DCreator.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var BuildGameObject = require('../BuildGameObject');
|
||||||
|
var GameObjectCreator = require('../GameObjectCreator');
|
||||||
|
var Layer3D = require('./Layer3D');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Layer3D Game Object and returns it.
|
||||||
|
*
|
||||||
|
* Note: This method will only be available if the Layer3D Game Object and WebGL support have been built into Phaser.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.GameObjectCreator#layer3d
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {object} config - The configuration object this Game Object will use to create itself.
|
||||||
|
* @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object.
|
||||||
|
*
|
||||||
|
* @return {Phaser.GameObjects.Layer3D} The Game Object that was created.
|
||||||
|
*/
|
||||||
|
GameObjectCreator.register('layer3d', function (config, addToScene)
|
||||||
|
{
|
||||||
|
if (config === undefined) { config = {}; }
|
||||||
|
|
||||||
|
var layer = new Layer3D(this.scene, 0, 0);
|
||||||
|
|
||||||
|
if (addToScene !== undefined)
|
||||||
|
{
|
||||||
|
config.add = addToScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildGameObject(this.scene, layer, config);
|
||||||
|
|
||||||
|
return layer;
|
||||||
|
});
|
||||||
|
|
||||||
|
// When registering a factory function 'this' refers to the GameObjectCreator context.
|
38
src/gameobjects/layer3d/Layer3DFactory.js
Normal file
38
src/gameobjects/layer3d/Layer3DFactory.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Layer3D = require('./Layer3D');
|
||||||
|
var GameObjectFactory = require('../GameObjectFactory');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Layer3D Game Object and adds it to the Scene.
|
||||||
|
*
|
||||||
|
* Note: This method will only be available if the Layer3D Game Object and WebGL support have been built into Phaser.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.GameObjectFactory#layer3d
|
||||||
|
* @webglOnly
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} [x] - The horizontal position of this Game Object in the world.
|
||||||
|
* @param {number} [y] - The vertical position of this Game Object in the world.
|
||||||
|
*
|
||||||
|
* @return {Phaser.GameObjects.Layer3D} The Game Object that was created.
|
||||||
|
*/
|
||||||
|
if (typeof WEBGL_RENDERER)
|
||||||
|
{
|
||||||
|
GameObjectFactory.register('layer3d', function (x, y)
|
||||||
|
{
|
||||||
|
return this.displayList.add(new Layer3D(this.scene, x, y));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// When registering a factory function 'this' refers to the GameObjectFactory context.
|
||||||
|
//
|
||||||
|
// There are several properties available to use:
|
||||||
|
//
|
||||||
|
// this.scene - a reference to the Scene that owns the GameObjectFactory
|
||||||
|
// this.displayList - a reference to the Display List the Scene owns
|
||||||
|
// this.updateList - a reference to the Update List the Scene owns
|
295
src/gameobjects/layer3d/Layer3DLight.js
Normal file
295
src/gameobjects/layer3d/Layer3DLight.js
Normal file
|
@ -0,0 +1,295 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Class = require('../../utils/Class');
|
||||||
|
var RGB = require('../../display/RGB');
|
||||||
|
var Vector3 = require('../../math/Vector3');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* A Layer3D Light.
|
||||||
|
*
|
||||||
|
* @class Layer3DLight
|
||||||
|
* @memberof Phaser.GameObjects
|
||||||
|
* @constructor
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
var Layer3DLight = new Class({
|
||||||
|
|
||||||
|
initialize:
|
||||||
|
|
||||||
|
function Layer3DLight (layer, x, y, z)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The Layer3D instance this light belongs to.
|
||||||
|
*
|
||||||
|
* A light can only belong to a single Layer3D instance.
|
||||||
|
*
|
||||||
|
* You should consider this property as being read-only. You cannot move a
|
||||||
|
* light to another Layer3D by simply changing it.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DLight#layer
|
||||||
|
* @type {Phaser.GameObjects.Layer3D}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.layer = layer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The position of the light in 3D space.
|
||||||
|
*
|
||||||
|
* You can modify this vector directly, or use the `x`, `y` and `z`
|
||||||
|
* properties of this class.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DLight#position
|
||||||
|
* @type {Phaser.Math.Vector3}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.position = new Vector3(x, y, z);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ambient color of the light.
|
||||||
|
*
|
||||||
|
* The default ambient color is 1, 1, 1.
|
||||||
|
*
|
||||||
|
* You can modify the properties of this RGB object directly, or call
|
||||||
|
* the `setAmbient` method of this class.
|
||||||
|
*
|
||||||
|
* The values in this object are used by the `uLightAmbient` shader uniform.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DLight#ambient
|
||||||
|
* @type {Phaser.Display.RGB}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.ambient = new RGB(1, 1, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The diffuse color of the light.
|
||||||
|
*
|
||||||
|
* The default diffuse color is 1, 1, 1.
|
||||||
|
*
|
||||||
|
* You can modify the properties of this RGB object directly, or call
|
||||||
|
* the `setDiffuse` method of this class.
|
||||||
|
*
|
||||||
|
* The values in this object are used by the `uLightDiffuse` shader uniform.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DLight#diffuse
|
||||||
|
* @type {Phaser.Display.RGB}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.diffuse = new RGB(1, 1, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The specular color of the light.
|
||||||
|
*
|
||||||
|
* The default specular color is 1, 1, 1.
|
||||||
|
*
|
||||||
|
* You can modify the properties of this RGB object directly, or call
|
||||||
|
* the `setSpecular` method of this class.
|
||||||
|
*
|
||||||
|
* The values in this object are used by the `uLightSpecular` shader uniform.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DLight#specular
|
||||||
|
* @type {Phaser.Display.RGB}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.specular = new RGB(1, 1, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dirty cache array.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DLight#dirtyCache
|
||||||
|
* @type {number[]}
|
||||||
|
* @private
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.dirtyCache = [ 0, 0, 0 ];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the position of this light is dirty.
|
||||||
|
*
|
||||||
|
* Called internally by the Mesh Pipeline `onBind` method and if dirty
|
||||||
|
* is used to set the `uLightPosition` uniform.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DLight#isDirty
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @return {boolean} `true` if this light is dirty, otherwise `false`.
|
||||||
|
*/
|
||||||
|
isDirty: function ()
|
||||||
|
{
|
||||||
|
var position = this.position;
|
||||||
|
var dirtyCache = this.dirtyCache;
|
||||||
|
|
||||||
|
var x = position.x;
|
||||||
|
var y = position.y;
|
||||||
|
var z = position.z;
|
||||||
|
|
||||||
|
var xCached = dirtyCache[0];
|
||||||
|
var yCached = dirtyCache[1];
|
||||||
|
var zCached = dirtyCache[2];
|
||||||
|
|
||||||
|
dirtyCache[0] = x;
|
||||||
|
dirtyCache[1] = y;
|
||||||
|
dirtyCache[2] = z;
|
||||||
|
|
||||||
|
return (xCached !== x || yCached !== y || zCached !== z);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the position of this light.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DLight#setPosition
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} x - The x position of this light.
|
||||||
|
* @param {number} y - The y position of this light.
|
||||||
|
* @param {number} z - The z position of this light.
|
||||||
|
*
|
||||||
|
* @return {this} This Layer3DLight instance.
|
||||||
|
*/
|
||||||
|
setPosition: function (x, y, z)
|
||||||
|
{
|
||||||
|
this.position.set(x, y, z);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ambient color of this light.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DLight#setAmbient
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} r - The red color value. Between 0 and 1.
|
||||||
|
* @param {number} g - The green color value. Between 0 and 1.
|
||||||
|
* @param {number} b - The blue color value. Between 0 and 1.
|
||||||
|
*
|
||||||
|
* @return {this} This Layer3DLight instance.
|
||||||
|
*/
|
||||||
|
setAmbient: function (r, g, b)
|
||||||
|
{
|
||||||
|
this.ambient.set(r, g, b);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the diffuse color of this light.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DLight#setDiffuse
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} r - The red color value. Between 0 and 1.
|
||||||
|
* @param {number} g - The green color value. Between 0 and 1.
|
||||||
|
* @param {number} b - The blue color value. Between 0 and 1.
|
||||||
|
*
|
||||||
|
* @return {this} This Layer3DLight instance.
|
||||||
|
*/
|
||||||
|
setDiffuse: function (r, g, b)
|
||||||
|
{
|
||||||
|
this.diffuse.set(r, g, b);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the specular color of this light.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DLight#setSpecular
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} r - The red color value. Between 0 and 1.
|
||||||
|
* @param {number} g - The green color value. Between 0 and 1.
|
||||||
|
* @param {number} b - The blue color value. Between 0 and 1.
|
||||||
|
*
|
||||||
|
* @return {this} This Layer3DLight instance.
|
||||||
|
*/
|
||||||
|
setSpecular: function (r, g, b)
|
||||||
|
{
|
||||||
|
this.specular.set(r, g, b);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The x position of the light.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DLight#x
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
x: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.position.x;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.position.x = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The y position of the light.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DLight#y
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
y: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.position.y;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.position.y = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The z position of the light.
|
||||||
|
*
|
||||||
|
* @name Phaser.GameObjects.Layer3DLight#z
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
z: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.position.z;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.position.z = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy handler for this light.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3DLight#destroy
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
destroy: function ()
|
||||||
|
{
|
||||||
|
this.layer = null;
|
||||||
|
this.position = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Layer3DLight;
|
25
src/gameobjects/layer3d/Layer3DRender.js
Normal file
25
src/gameobjects/layer3d/Layer3DRender.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var renderWebGL = require('../../utils/NOOP');
|
||||||
|
var renderCanvas = require('../../utils/NOOP');
|
||||||
|
|
||||||
|
if (typeof WEBGL_RENDERER)
|
||||||
|
{
|
||||||
|
renderWebGL = require('./Layer3DWebGLRenderer');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof CANVAS_RENDERER)
|
||||||
|
{
|
||||||
|
renderCanvas = require('./Layer3DCanvasRenderer');
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
renderWebGL: renderWebGL,
|
||||||
|
renderCanvas: renderCanvas
|
||||||
|
|
||||||
|
};
|
52
src/gameobjects/layer3d/Layer3DWebGLRenderer.js
Normal file
52
src/gameobjects/layer3d/Layer3DWebGLRenderer.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders this Game Object with the WebGL Renderer to the given Camera.
|
||||||
|
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
||||||
|
* This method should not be called directly. It is a utility function of the Render module.
|
||||||
|
*
|
||||||
|
* @method Phaser.GameObjects.Layer3D#renderWebGL
|
||||||
|
* @since 3.50.0
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
|
||||||
|
* @param {Phaser.GameObjects.Layer3D} src - The Game Object being rendered in this call.
|
||||||
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
||||||
|
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
||||||
|
*/
|
||||||
|
var Layer3DWebGLRenderer = function (renderer, src)
|
||||||
|
{
|
||||||
|
var models = src.models;
|
||||||
|
var totalModels = models.length;
|
||||||
|
|
||||||
|
if (totalModels === 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.pipelines.clear();
|
||||||
|
|
||||||
|
src.camera.update();
|
||||||
|
|
||||||
|
var pipeline = renderer.pipelines.set(src.pipeline, src);
|
||||||
|
|
||||||
|
for (var m = 0; m < totalModels; m++)
|
||||||
|
{
|
||||||
|
var model = models[m];
|
||||||
|
|
||||||
|
if (model.visible && model.vertexCount > 0)
|
||||||
|
{
|
||||||
|
pipeline.drawModel(src, model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
src.resetDirtyFlags();
|
||||||
|
|
||||||
|
renderer.pipelines.rebind();
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Layer3DWebGLRenderer;
|
918
src/geom/mesh/Model.js
Normal file
918
src/geom/mesh/Model.js
Normal file
|
@ -0,0 +1,918 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var AnimationState = require('../../animations/AnimationState');
|
||||||
|
var Class = require('../../utils/Class');
|
||||||
|
var Components = require('../../gameobjects/components');
|
||||||
|
var Matrix4 = require('../../math/Matrix4');
|
||||||
|
var Quaternion = require('../../math/Quaternion');
|
||||||
|
var RGB = require('../../layer3d/math/RGB');
|
||||||
|
var Vector3 = require('../../math/Vector3');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* A 3D Model.
|
||||||
|
*
|
||||||
|
* @class Model
|
||||||
|
* @memberof Phaser.Geom.Mesh
|
||||||
|
* @constructor
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {Phaser.GameObjects.Layer3D} layer - A reference to the Layer3D instance that this model belongs to.
|
||||||
|
* @param {number} verticesCount - The total number of vertices this model can contain.
|
||||||
|
* @param {string|Phaser.Textures.Texture} [texture] - The key, or instance of the Texture this model will use to render with, as stored in the Texture Manager.
|
||||||
|
* @param {string|integer} [frame] - An optional frame from the Texture this model is rendering with. Ensure your UV data also matches this frame.
|
||||||
|
* @param {number} [x=0] - The x position of the Model.
|
||||||
|
* @param {number} [y=0] - The y position of the Model.
|
||||||
|
* @param {number} [z=0] - The z position of the Model.
|
||||||
|
*/
|
||||||
|
var Model = new Class({
|
||||||
|
|
||||||
|
Mixins: [
|
||||||
|
Components.AlphaSingle,
|
||||||
|
Components.Size,
|
||||||
|
Components.Texture,
|
||||||
|
Components.Visible
|
||||||
|
],
|
||||||
|
|
||||||
|
initialize:
|
||||||
|
|
||||||
|
function Model (layer, verticesCount, texture, frame, x, y, z)
|
||||||
|
{
|
||||||
|
if (x === undefined) { x = 0; }
|
||||||
|
if (y === undefined) { y = 0; }
|
||||||
|
if (z === undefined) { z = 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Layer3D instance this model belongs to.
|
||||||
|
*
|
||||||
|
* A model can only belong to a single Layer3D instance.
|
||||||
|
*
|
||||||
|
* You should consider this property as being read-only. You cannot move a
|
||||||
|
* model to another Layer3D by simply changing it.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#layer
|
||||||
|
* @type {Phaser.GameObjects.Layer3D}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.layer = layer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to the Scene to which this the Layer3D Object which owns this model belongs.
|
||||||
|
*
|
||||||
|
* You should consider this property as being read-only. You cannot move a
|
||||||
|
* Game Object to another Scene by simply changing it.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#scene
|
||||||
|
* @type {Phaser.Scene}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.scene = layer.scene;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Animation State of this Model.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#anims
|
||||||
|
* @type {Phaser.Animation.AnimationState}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.anims = new AnimationState(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of a single vertex, in bytes.
|
||||||
|
*
|
||||||
|
* The total of all 8 attributes * bytes size.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#vertexSize
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.vertexSize = 32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of vertices the ArrayBuffer in this model can hold.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#maxVertexCount
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.maxVertexCount = verticesCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of vertices currently added to this model.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#vertexCount
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.vertexCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An ArrayBuffer that contains the GPU byte data for this model.
|
||||||
|
*
|
||||||
|
* The size of the buffer is set to `verticesCount * vertexSize` when
|
||||||
|
* this model is created and cannot be changed without resetting the vertices.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#vertexData
|
||||||
|
* @type {ArrayBuffer}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.vertexData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Float32 View into the Array Buffer.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#vertexViewF32
|
||||||
|
* @type {Float32Array}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.vertexViewF32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Vector3 containing the position of this model in 3D space.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#position
|
||||||
|
* @type {Phaser.Math.Vector3}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.position = new Vector3(x, y, z);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Vector3 containing the scale of this model in 3D space.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#scale
|
||||||
|
* @type {Phaser.Math.Vector3}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.scale = new Vector3(1, 1, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Quaternion containing the rotation of this model in 3D space.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#position
|
||||||
|
* @type {Phaser.Math.Quaternion}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.rotation = new Quaternion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An RGB object containing the ambient material color of this model.
|
||||||
|
*
|
||||||
|
* You can adjust the ambient material color by calling the methods
|
||||||
|
* on this object and changing its properties.
|
||||||
|
*
|
||||||
|
* Remember that all color values should be specified in the range
|
||||||
|
* of 0 to 1.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#ambient
|
||||||
|
* @type {Phaser.Display.RGB}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.ambient = new RGB(1, 1, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An RGB object containing the diffuse material color of this model.
|
||||||
|
*
|
||||||
|
* You can adjust the diffuse material color by calling the methods
|
||||||
|
* on this object and changing its properties.
|
||||||
|
*
|
||||||
|
* Remember that all color values should be specified in the range
|
||||||
|
* of 0 to 1.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#diffuse
|
||||||
|
* @type {Phaser.Display.RGB}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.diffuse = new RGB(1, 1, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An RGB object containing the specular material color of this model.
|
||||||
|
*
|
||||||
|
* You can adjust the specular material color by calling the methods
|
||||||
|
* on this object and changing its properties.
|
||||||
|
*
|
||||||
|
* Remember that all color values should be specified in the range
|
||||||
|
* of 0 to 1.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#specular
|
||||||
|
* @type {Phaser.Display.RGB}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.specular = new RGB(1, 1, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The material shine value of this model.
|
||||||
|
*
|
||||||
|
* Default to 0.25. Keep this value in the range 0 to 1.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#ambient
|
||||||
|
* @type {number}
|
||||||
|
* @default 0.25
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.shine = 0.25;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Matrix4 containing the transformed normal values for this model.
|
||||||
|
*
|
||||||
|
* You should consider this Matrix as being read-only. Its values are
|
||||||
|
* repopulated during `Model.preUpdate` as required.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#normalMatrix
|
||||||
|
* @type {Phaser.Math.Matrix4}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.normalMatrix = new Matrix4();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Matrix4 containing the transform matrix for this model.
|
||||||
|
*
|
||||||
|
* You should consider this Matrix as being read-only. Its values are
|
||||||
|
* repopulated during `Model.preUpdate` as required.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#transformMatrix
|
||||||
|
* @type {Phaser.Math.Matrix4}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.transformMatrix = new Matrix4();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The culling mode used by this Model during rendering.
|
||||||
|
*
|
||||||
|
* Specifies whether front or back facing polygons are candidates
|
||||||
|
* for culling. The default value is `gl.BACK`. Possible values are:
|
||||||
|
*
|
||||||
|
* `gl.FRONT` (1028)
|
||||||
|
* `gl.BACK` (1029)
|
||||||
|
* `gl.FRONT_AND_BACK` (1032)
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#cullMode
|
||||||
|
* @type {GLenum}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.cullMode = 1029;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An internal cache, used to compare position, rotation, scale and verts data
|
||||||
|
* each frame, to avoid math calculates in `preUpdate`.
|
||||||
|
*
|
||||||
|
* cache structure = position | rotation | scale | verts count
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#dirtyCache
|
||||||
|
* @type {number[]}
|
||||||
|
* @private
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.dirtyCache = [ x, y, z, 0, 0, 0, 1, 1, 1, 1, 0 ];
|
||||||
|
|
||||||
|
if (!texture)
|
||||||
|
{
|
||||||
|
texture = this.scene.sys.textures.get('__WHITE');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setTexture(texture, frame);
|
||||||
|
|
||||||
|
this.setSizeToFrame();
|
||||||
|
|
||||||
|
this.resetVertices(verticesCount);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls each of the listeners registered for a given event.
|
||||||
|
*
|
||||||
|
* This is a proxy for the Layer3D `emit` method.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#emit
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {(string|symbol)} event - The event name.
|
||||||
|
* @param {...*} [args] - Additional arguments that will be passed to the event handler.
|
||||||
|
*
|
||||||
|
* @return {boolean} `true` if the event had listeners, else `false`.
|
||||||
|
*/
|
||||||
|
emit: function ()
|
||||||
|
{
|
||||||
|
return this.layer.emit.call(arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks all of the current model values against the `dirtyCache` to see if the
|
||||||
|
* normal and transform matrices need updating.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#isDirty
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @return {boolean} Returns `true` if any of the model values are dirty, otherwise `false`.
|
||||||
|
*/
|
||||||
|
isDirty: function ()
|
||||||
|
{
|
||||||
|
var position = this.position;
|
||||||
|
var rotation = this.rotation;
|
||||||
|
var scale = this.scale;
|
||||||
|
|
||||||
|
var dirtyCache = this.dirtyCache;
|
||||||
|
|
||||||
|
var px = position.x;
|
||||||
|
var py = position.y;
|
||||||
|
var pz = position.z;
|
||||||
|
|
||||||
|
var rx = rotation.x;
|
||||||
|
var ry = rotation.y;
|
||||||
|
var rz = rotation.z;
|
||||||
|
var rw = rotation.w;
|
||||||
|
|
||||||
|
var sx = scale.x;
|
||||||
|
var sy = scale.y;
|
||||||
|
var sz = scale.z;
|
||||||
|
|
||||||
|
var vertices = this.vertexCount;
|
||||||
|
|
||||||
|
var pxCached = dirtyCache[0];
|
||||||
|
var pyCached = dirtyCache[1];
|
||||||
|
var pzCached = dirtyCache[2];
|
||||||
|
|
||||||
|
var rxCached = dirtyCache[3];
|
||||||
|
var ryCached = dirtyCache[4];
|
||||||
|
var rzCached = dirtyCache[5];
|
||||||
|
var rwCached = dirtyCache[6];
|
||||||
|
|
||||||
|
var sxCached = dirtyCache[7];
|
||||||
|
var syCached = dirtyCache[8];
|
||||||
|
var szCached = dirtyCache[9];
|
||||||
|
|
||||||
|
var vCached = dirtyCache[10];
|
||||||
|
|
||||||
|
dirtyCache[0] = px;
|
||||||
|
dirtyCache[1] = py;
|
||||||
|
dirtyCache[2] = pz;
|
||||||
|
|
||||||
|
dirtyCache[3] = rx;
|
||||||
|
dirtyCache[4] = ry;
|
||||||
|
dirtyCache[5] = rz;
|
||||||
|
dirtyCache[6] = rw;
|
||||||
|
|
||||||
|
dirtyCache[7] = sx;
|
||||||
|
dirtyCache[8] = sy;
|
||||||
|
dirtyCache[9] = sz;
|
||||||
|
|
||||||
|
dirtyCache[10] = vertices;
|
||||||
|
|
||||||
|
return (
|
||||||
|
pxCached !== px || pyCached !== py || pzCached !== pz ||
|
||||||
|
rxCached !== rx || ryCached !== ry || rzCached !== rz || rwCached !== rw ||
|
||||||
|
sxCached !== sx || syCached !== sy || szCached !== sz ||
|
||||||
|
vCached !== vertices
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal update handler. Advances any animations that are set on the model and,
|
||||||
|
* if the model data is dirty, recalculates the transform and normal matrices.
|
||||||
|
*
|
||||||
|
* This method is called automatically by the `Layer3D` to which this model belongs.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#preUpdate
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} time - The current timestamp.
|
||||||
|
* @param {number} delta - The delta time, in ms, elapsed since the last frame.
|
||||||
|
*/
|
||||||
|
preUpdate: function (time, delta)
|
||||||
|
{
|
||||||
|
this.anims.update(time, delta);
|
||||||
|
|
||||||
|
// If the model isn't dirty we can bail out and save lots of math
|
||||||
|
if (this.isDirty())
|
||||||
|
{
|
||||||
|
var normalMatrix = this.normalMatrix;
|
||||||
|
var transformMatrix = this.transformMatrix;
|
||||||
|
|
||||||
|
// TODO - Merge scale into this op
|
||||||
|
transformMatrix.fromRotationTranslation(this.rotation, this.position);
|
||||||
|
transformMatrix.scale(this.scale);
|
||||||
|
|
||||||
|
normalMatrix.copy(transformMatrix);
|
||||||
|
normalMatrix.invert();
|
||||||
|
normalMatrix.transpose();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total number of Faces _currently added_ to this model.
|
||||||
|
*
|
||||||
|
* Models in Phaser 3 must always be triangulated, so this value is the same as
|
||||||
|
* `vertexCount / 3`.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#getFaceCount
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @return {number} The number of Faces in this Model.
|
||||||
|
*/
|
||||||
|
getFaceCount: function ()
|
||||||
|
{
|
||||||
|
return this.vertexCount / 3;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Vertex at the given offset from this models data.
|
||||||
|
*
|
||||||
|
* Be aware that the returned Vertex is untranslated, so will need transforming if you wish
|
||||||
|
* to use its coordinates in world space.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#getVertex
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} index - The index of the vertex to get. Cannot be negative, or exceed `Model.vertexCount`.
|
||||||
|
*
|
||||||
|
* @return {Phaser.Types.GameObjects.Vertex} A Vertex object.
|
||||||
|
*/
|
||||||
|
getVertex: function (index)
|
||||||
|
{
|
||||||
|
var vertexViewF32 = this.vertexViewF32;
|
||||||
|
|
||||||
|
// 8 = attribute count (number of items added into the view below)
|
||||||
|
var vertexOffset = (index * 8) - 1;
|
||||||
|
|
||||||
|
var x = vertexViewF32[++vertexOffset];
|
||||||
|
var y = vertexViewF32[++vertexOffset];
|
||||||
|
var z = vertexViewF32[++vertexOffset];
|
||||||
|
var normalX = vertexViewF32[++vertexOffset];
|
||||||
|
var normalY = vertexViewF32[++vertexOffset];
|
||||||
|
var normalZ = vertexViewF32[++vertexOffset];
|
||||||
|
var u = vertexViewF32[++vertexOffset];
|
||||||
|
var v = vertexViewF32[++vertexOffset];
|
||||||
|
|
||||||
|
return { x: x, y: y, z: z, u: u, v: v, normalX: normalX, normalY: normalY, normalZ: normalZ, alpha: 1 };
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Face at the given index in this model.
|
||||||
|
*
|
||||||
|
* A face comprises of 3 vertices.
|
||||||
|
*
|
||||||
|
* Be aware that the Face vertices are untranslated, so will need transforming if you wish
|
||||||
|
* to use their coordinates in world space.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#getFace
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} index - The index of the Face to get. Make sure the index is in range.
|
||||||
|
*
|
||||||
|
* @return {Phaser.Types.GameObjects.Face} The Face at the given index.
|
||||||
|
*/
|
||||||
|
getFace: function (index)
|
||||||
|
{
|
||||||
|
var offset = index * 3;
|
||||||
|
|
||||||
|
var v1 = this.getVertex(offset);
|
||||||
|
var v2 = this.getVertex(offset + 1);
|
||||||
|
var v3 = this.getVertex(offset + 2);
|
||||||
|
var ccw = (v2.x - v1.x) * (v3.y - v1.y) - (v2.y - v1.y) * (v3.x - v1.x) >= 0;
|
||||||
|
|
||||||
|
return { vertex1: v1, vertex2: v2, vertex3: 3, isCounterClockwise: ccw };
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the data in this model, clearing the `vertexData` ArrayBuffer and
|
||||||
|
* setting it to the new max count given.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#resetVertices
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} verticesCount - The total number of vertices this model can contain.
|
||||||
|
*/
|
||||||
|
resetVertices: function (verticesCount)
|
||||||
|
{
|
||||||
|
this.vertexData = new ArrayBuffer(verticesCount * this.vertexSize);
|
||||||
|
this.vertexViewF32 = new Float32Array(this.vertexData);
|
||||||
|
this.vertexCount = 0;
|
||||||
|
this.maxVertexCount = verticesCount;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates all values of the vertex at the given index.
|
||||||
|
*
|
||||||
|
* Ensure that the index is in range.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#updateVertex
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} index - The index of the vertex to update.
|
||||||
|
* @param {number} x - The x position of the vertex.
|
||||||
|
* @param {number} y - The y position of the vertex.
|
||||||
|
* @param {number} z - The z position of the vertex.
|
||||||
|
* @param {number} u - The UV u coordinate of the vertex.
|
||||||
|
* @param {number} v - The UV v coordinate of the vertex.
|
||||||
|
* @param {number} normalX - The x normal of the vertex.
|
||||||
|
* @param {number} normalY - The y normal of the vertex.
|
||||||
|
* @param {number} normalZ - The z normal of the vertex.
|
||||||
|
*/
|
||||||
|
updateVertex: function (index, x, y, z, u, v, normalX, normalY, normalZ)
|
||||||
|
{
|
||||||
|
var vertexViewF32 = this.vertexViewF32;
|
||||||
|
|
||||||
|
// 8 = attribute count
|
||||||
|
var vertexOffset = (index * 8) - 1;
|
||||||
|
|
||||||
|
vertexViewF32[++vertexOffset] = x;
|
||||||
|
vertexViewF32[++vertexOffset] = y;
|
||||||
|
vertexViewF32[++vertexOffset] = z;
|
||||||
|
vertexViewF32[++vertexOffset] = normalX;
|
||||||
|
vertexViewF32[++vertexOffset] = normalY;
|
||||||
|
vertexViewF32[++vertexOffset] = normalZ;
|
||||||
|
vertexViewF32[++vertexOffset] = u;
|
||||||
|
vertexViewF32[++vertexOffset] = v;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new vertex to this model and increments the `vertexCount` by one.
|
||||||
|
*
|
||||||
|
* You cannot add more vertices to this model than the total specified when the model was created.
|
||||||
|
* If you need to clear all vertices first, call `Model.resetVertices`.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#addVertex
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} x - The x position of the vertex.
|
||||||
|
* @param {number} y - The y position of the vertex.
|
||||||
|
* @param {number} z - The z position of the vertex.
|
||||||
|
* @param {number} u - The UV u coordinate of the vertex.
|
||||||
|
* @param {number} v - The UV v coordinate of the vertex.
|
||||||
|
* @param {number} normalX - The x normal of the vertex.
|
||||||
|
* @param {number} normalY - The y normal of the vertex.
|
||||||
|
* @param {number} normalZ - The z normal of the vertex.
|
||||||
|
*/
|
||||||
|
addVertex: function (x, y, z, u, v, normalX, normalY, normalZ)
|
||||||
|
{
|
||||||
|
if (this.vertexCount < this.maxVertexCount)
|
||||||
|
{
|
||||||
|
this.updateVertex(this.vertexCount, x, y, z, u, v, normalX, normalY, normalZ);
|
||||||
|
|
||||||
|
this.vertexCount++;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds vertices to this model by parsing the given arrays.
|
||||||
|
*
|
||||||
|
* This method will take vertex data in one of two formats, based on the `containsZ` parameter.
|
||||||
|
*
|
||||||
|
* If your vertex data are `x`, `y` pairs, then `containsZ` should be `false` (this is the default)
|
||||||
|
*
|
||||||
|
* If your vertex data is groups of `x`, `y` and `z` values, then the `containsZ` parameter must be true.
|
||||||
|
*
|
||||||
|
* The `uvs` parameter is a numeric array consisting of `u` and `v` pairs.
|
||||||
|
* The `normals` parameter is a numeric array consisting of `x`, `y` vertex normal values and, if `containsZ` is true, `z` values as well.
|
||||||
|
* The `indicies` parameter is an optional array that, if given, is an indexed list of vertices to be added.
|
||||||
|
*
|
||||||
|
* The following example will create a 256 x 256 sized quad using an index array:
|
||||||
|
*
|
||||||
|
* ```javascript
|
||||||
|
* const vertices = [
|
||||||
|
* -128, 128,
|
||||||
|
* 128, 128,
|
||||||
|
* -128, -128,
|
||||||
|
* 128, -128
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* const uvs = [
|
||||||
|
* 0, 1,
|
||||||
|
* 1, 1,
|
||||||
|
* 0, 0,
|
||||||
|
* 1, 0
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* const indices = [ 0, 2, 1, 2, 3, 1 ];
|
||||||
|
*
|
||||||
|
* Model.addVertices(vertices, uvs, indicies);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* You cannot add more vertices to this model than the total specified when the model was created.
|
||||||
|
* If you need to clear all vertices first, call `Model.resetVertices`.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#addVertices
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number[]} vertices - The vertices array. Either `xy` pairs, or `xyz` if the `containsZ` parameter is `true`.
|
||||||
|
* @param {number[]} uvs - The UVs pairs array.
|
||||||
|
* @param {number[]} [normals] - Optional vertex normals array. If you don't have one, pass `null` or an empty array.
|
||||||
|
* @param {number[]} [indicies] - Optional vertex indicies array. If you don't have one, pass `null` or an empty array.
|
||||||
|
* @param {boolean} [containsZ=false] - Does the vertices data include a `z` component?
|
||||||
|
*/
|
||||||
|
addVertices: function (vertices, uvs, normals, indicies, containsZ)
|
||||||
|
{
|
||||||
|
if (containsZ === undefined) { containsZ = false; }
|
||||||
|
|
||||||
|
if (vertices.length !== uvs.length)
|
||||||
|
{
|
||||||
|
throw new Error('Model vertices and uv count not equal');
|
||||||
|
}
|
||||||
|
|
||||||
|
var i;
|
||||||
|
var x;
|
||||||
|
var y;
|
||||||
|
var z;
|
||||||
|
var u;
|
||||||
|
var v;
|
||||||
|
var normalX;
|
||||||
|
var normalY;
|
||||||
|
var normalZ;
|
||||||
|
var iInc = (containsZ) ? 3 : 2;
|
||||||
|
|
||||||
|
if (Array.isArray(indicies) && indicies.length > 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < indicies.length; i++)
|
||||||
|
{
|
||||||
|
var index = indicies[i] * iInc;
|
||||||
|
|
||||||
|
x = vertices[index];
|
||||||
|
y = vertices[index + 1];
|
||||||
|
z = (containsZ) ? vertices[index + 2] : 0;
|
||||||
|
u = uvs[index];
|
||||||
|
v = uvs[index + 1];
|
||||||
|
normalX = 0;
|
||||||
|
normalY = 0;
|
||||||
|
normalZ = 0;
|
||||||
|
|
||||||
|
if (normals)
|
||||||
|
{
|
||||||
|
normalX = normals[index];
|
||||||
|
normalY = normals[index + 1];
|
||||||
|
normalZ = (containsZ) ? normals[index + 2] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addVertex(
|
||||||
|
x, y, z,
|
||||||
|
u, v,
|
||||||
|
normalX, normalY, normalZ
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < vertices.length; i += iInc)
|
||||||
|
{
|
||||||
|
x = vertices[i];
|
||||||
|
y = vertices[i + 1];
|
||||||
|
z = (containsZ) ? vertices[i + 2] : 0;
|
||||||
|
u = uvs[i];
|
||||||
|
v = uvs[i + 1];
|
||||||
|
normalX = 0;
|
||||||
|
normalY = 0;
|
||||||
|
normalZ = 0;
|
||||||
|
|
||||||
|
if (normals)
|
||||||
|
{
|
||||||
|
normalX = normals[i];
|
||||||
|
normalY = normals[i + 1];
|
||||||
|
normalZ = (containsZ) ? normals[i + 2] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addVertex(
|
||||||
|
x, y, z,
|
||||||
|
u, v,
|
||||||
|
normalX, normalY, normalZ
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates this model along the x axis by the given amount.
|
||||||
|
*
|
||||||
|
* This method works by calling the `rotateX` method of the `rotation` quaternion of this model.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#rotateX
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} rad - The amount, in radians, to rotate the model by.
|
||||||
|
*
|
||||||
|
* @return {this} This model instance.
|
||||||
|
*/
|
||||||
|
rotateX: function (rad)
|
||||||
|
{
|
||||||
|
this.rotation.rotateX(rad);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates this model along the y axis by the given amount.
|
||||||
|
*
|
||||||
|
* This method works by calling the `rotateY` method of the `rotation` quaternion of this model.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#rotateY
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} rad - The amount, in radians, to rotate the model by.
|
||||||
|
*
|
||||||
|
* @return {this} This model instance.
|
||||||
|
*/
|
||||||
|
rotateY: function (rad)
|
||||||
|
{
|
||||||
|
this.rotation.rotateY(rad);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates this model along the z axis by the given amount.
|
||||||
|
*
|
||||||
|
* This method works by calling the `rotateZ` method of the `rotation` quaternion of this model.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#rotateZ
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {number} rad - The amount, in radians, to rotate the model by.
|
||||||
|
*
|
||||||
|
* @return {this} This model instance.
|
||||||
|
*/
|
||||||
|
rotateZ: function (rad)
|
||||||
|
{
|
||||||
|
this.rotation.rotateZ(rad);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
setPosition: function (x, y, z)
|
||||||
|
{
|
||||||
|
this.position.set(x, y, z);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
setScale: function (x, y, z)
|
||||||
|
{
|
||||||
|
this.scale.set(x, y, z);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The x position of this model in 3D space.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#x
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
x: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.position.x;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.position.x = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The y position of this model in 3D space.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#y
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
y: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.position.y;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.position.y = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The z position of this model in 3D space.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#z
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
z: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.position.z;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.position.z = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The x scale of this model in 3D space.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#scaleX
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
scaleX: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.scale.x;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.scale.x = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The y scale of this model in 3D space.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#scaleY
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
scaleY: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.scale.y;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.scale.y = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The z scale of this model in 3D space.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Model#scaleZ
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
scaleZ: {
|
||||||
|
|
||||||
|
get: function ()
|
||||||
|
{
|
||||||
|
return this.scale.z;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function (value)
|
||||||
|
{
|
||||||
|
this.scale.z = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys this Model instance, all of its vertex data and references.
|
||||||
|
*
|
||||||
|
* Calling this method will not remove it from any parent Layer3D, so be sure to do that first,
|
||||||
|
* prior to calling `destroy`.
|
||||||
|
*
|
||||||
|
* If a Layer3D object is destroyed, this is the method that is called on all of its models.
|
||||||
|
*
|
||||||
|
* @method Phaser.Geom.Mesh.Model#destroy
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
destroy: function ()
|
||||||
|
{
|
||||||
|
this.anims.destroy();
|
||||||
|
|
||||||
|
this.layer = null;
|
||||||
|
this.scene = null;
|
||||||
|
this.anims = null;
|
||||||
|
|
||||||
|
this.vertexData = null;
|
||||||
|
this.vertexViewF32 = null;
|
||||||
|
|
||||||
|
this.position = null;
|
||||||
|
this.scale = null;
|
||||||
|
this.rotation = null;
|
||||||
|
|
||||||
|
this.ambient = null;
|
||||||
|
this.diffuse = null;
|
||||||
|
this.specular = null;
|
||||||
|
|
||||||
|
this.normalMatrix = null;
|
||||||
|
this.transformMatrix = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Model;
|
|
@ -70,6 +70,33 @@ var Vertex = new Class({
|
||||||
*/
|
*/
|
||||||
this.vz = 0;
|
this.vz = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The projected x coordinate of this vertex.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Vertex#vx
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.nx = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The projected y coordinate of this vertex.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Vertex#vy
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.ny = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The projected z coordinate of this vertex.
|
||||||
|
*
|
||||||
|
* @name Phaser.Geom.Mesh.Vertex#vz
|
||||||
|
* @type {number}
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
this.nz = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UV u coordinate of this vertex.
|
* UV u coordinate of this vertex.
|
||||||
*
|
*
|
||||||
|
@ -107,6 +134,15 @@ var Vertex = new Class({
|
||||||
this.alpha = alpha;
|
this.alpha = alpha;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setNormals: function (nx, ny, nz)
|
||||||
|
{
|
||||||
|
this.nx = nx;
|
||||||
|
this.ny = ny;
|
||||||
|
this.nz = nz;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms this vertex by the given matrix, storing the results in `vx`, `vy` and `vz`.
|
* Transforms this vertex by the given matrix, storing the results in `vx`, `vy` and `vz`.
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,6 +14,7 @@ var LightPipeline = require('./pipelines/LightPipeline');
|
||||||
var MultiPipeline = require('./pipelines/MultiPipeline');
|
var MultiPipeline = require('./pipelines/MultiPipeline');
|
||||||
var RopePipeline = require('./pipelines/RopePipeline');
|
var RopePipeline = require('./pipelines/RopePipeline');
|
||||||
var SinglePipeline = require('./pipelines/SinglePipeline');
|
var SinglePipeline = require('./pipelines/SinglePipeline');
|
||||||
|
var MeshPipeline = require('./pipelines/MeshPipeline');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
|
@ -146,6 +147,7 @@ var PipelineManager = new Class({
|
||||||
this.add(CONST.SINGLE_PIPELINE, new SinglePipeline({ game: game }));
|
this.add(CONST.SINGLE_PIPELINE, new SinglePipeline({ game: game }));
|
||||||
this.add(CONST.ROPE_PIPELINE, new RopePipeline({ game: game }));
|
this.add(CONST.ROPE_PIPELINE, new RopePipeline({ game: game }));
|
||||||
this.add(CONST.LIGHT_PIPELINE, new LightPipeline({ game: game }));
|
this.add(CONST.LIGHT_PIPELINE, new LightPipeline({ game: game }));
|
||||||
|
this.add(CONST.MESH_PIPELINE, new MeshPipeline({ game: game }));
|
||||||
|
|
||||||
this.set(this.MULTI_PIPELINE);
|
this.set(this.MULTI_PIPELINE);
|
||||||
},
|
},
|
||||||
|
|
288
src/renderer/webgl/pipelines/MeshPipeline.js
Normal file
288
src/renderer/webgl/pipelines/MeshPipeline.js
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
/**
|
||||||
|
* @author Richard Davey <rich@photonstorm.com>
|
||||||
|
* @copyright 2020 Photon Storm Ltd.
|
||||||
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Class = require('../../../utils/Class');
|
||||||
|
var GetFastValue = require('../../../utils/object/GetFastValue');
|
||||||
|
var ShaderSourceFS = require('../shaders/Mesh-frag.js');
|
||||||
|
var ShaderSourceVS = require('../shaders/Mesh-vert.js');
|
||||||
|
var WebGLPipeline = require('../WebGLPipeline');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @class MeshPipeline
|
||||||
|
* @extends Phaser.Renderer.WebGL.WebGLPipeline
|
||||||
|
* @memberof Phaser.Renderer.WebGL.Pipelines
|
||||||
|
* @constructor
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {Phaser.Types.Renderer.WebGL.WebGLPipelineConfig} config - The configuration options for this pipeline.
|
||||||
|
*/
|
||||||
|
var MeshPipeline = new Class({
|
||||||
|
|
||||||
|
Extends: WebGLPipeline,
|
||||||
|
|
||||||
|
initialize:
|
||||||
|
|
||||||
|
function MeshPipeline (config)
|
||||||
|
{
|
||||||
|
var gl = config.game.renderer.gl;
|
||||||
|
|
||||||
|
config.fragShader = GetFastValue(config, 'fragShader', ShaderSourceFS),
|
||||||
|
config.vertShader = GetFastValue(config, 'vertShader', ShaderSourceVS),
|
||||||
|
config.vertexCapacity = GetFastValue(config, 'vertexCapacity', 8),
|
||||||
|
config.vertexSize = GetFastValue(config, 'vertexSize', 32),
|
||||||
|
config.attributes = GetFastValue(config, 'attributes', [
|
||||||
|
{
|
||||||
|
name: 'aVertexPosition',
|
||||||
|
size: 3,
|
||||||
|
type: gl.FLOAT,
|
||||||
|
normalized: false,
|
||||||
|
offset: 0,
|
||||||
|
enabled: false,
|
||||||
|
location: -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'aVertexNormal',
|
||||||
|
size: 3,
|
||||||
|
type: gl.FLOAT,
|
||||||
|
normalized: false,
|
||||||
|
offset: 12,
|
||||||
|
enabled: false,
|
||||||
|
location: -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'aTextureCoord',
|
||||||
|
size: 2,
|
||||||
|
type: gl.FLOAT,
|
||||||
|
normalized: false,
|
||||||
|
offset: 24,
|
||||||
|
enabled: false,
|
||||||
|
location: -1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
config.uniforms = GetFastValue(config, 'uniforms', [
|
||||||
|
'uViewProjectionMatrix',
|
||||||
|
'uLightPosition',
|
||||||
|
'uLightAmbient',
|
||||||
|
'uLightDiffuse',
|
||||||
|
'uLightSpecular',
|
||||||
|
'uCameraPosition',
|
||||||
|
'uFogColor',
|
||||||
|
'uFogNear',
|
||||||
|
'uFogFar',
|
||||||
|
'uModelMatrix',
|
||||||
|
'uNormalMatrix',
|
||||||
|
'uMaterialAmbient',
|
||||||
|
'uMaterialDiffuse',
|
||||||
|
'uMaterialSpecular',
|
||||||
|
'uMaterialShine',
|
||||||
|
'uTexture'
|
||||||
|
]);
|
||||||
|
|
||||||
|
WebGLPipeline.call(this, config);
|
||||||
|
|
||||||
|
this.forceZero = true;
|
||||||
|
|
||||||
|
// Cache structure:
|
||||||
|
|
||||||
|
// 0 fog near
|
||||||
|
// 1 fog far
|
||||||
|
// 2, 3, 4 model material ambient
|
||||||
|
// 5, 6, 7 model material diffuse
|
||||||
|
// 8, 9, 10 model material specular
|
||||||
|
// 11 model material shine
|
||||||
|
|
||||||
|
this.dirtyCache = [
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
-1, -1, -1,
|
||||||
|
-1, -1, -1,
|
||||||
|
-1, -1, -1,
|
||||||
|
-1
|
||||||
|
];
|
||||||
|
|
||||||
|
this.cullMode = 1029;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called every time the pipeline is bound by the renderer.
|
||||||
|
* Sets the shader program, vertex buffer and other resources.
|
||||||
|
* Should only be called when changing pipeline.
|
||||||
|
*
|
||||||
|
* @method Phaser.Renderer.WebGL.Pipelines.MeshPipeline#bind
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {boolean} [reset=false] - Should the pipeline be fully re-bound after a renderer pipeline clear?
|
||||||
|
*
|
||||||
|
* @return {this} This WebGLPipeline instance.
|
||||||
|
*/
|
||||||
|
bind: function (reset)
|
||||||
|
{
|
||||||
|
if (reset === undefined) { reset = false; }
|
||||||
|
|
||||||
|
WebGLPipeline.prototype.bind.call(this, reset);
|
||||||
|
|
||||||
|
var gl = this.gl;
|
||||||
|
|
||||||
|
gl.enable(gl.DEPTH_TEST);
|
||||||
|
gl.enable(gl.CULL_FACE);
|
||||||
|
gl.cullFace(gl.BACK);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called every time a Game Object asks the Pipeline Manager to use this pipeline.
|
||||||
|
*
|
||||||
|
* Unlike the `bind` method, which is only called once per frame, this is called for every object
|
||||||
|
* that requests it, allowing you to perform per-object GL set-up.
|
||||||
|
*
|
||||||
|
* @method Phaser.Renderer.WebGL.Pipelines.MeshPipeline#onBind
|
||||||
|
* @since 3.50.0
|
||||||
|
*
|
||||||
|
* @param {Phaser.GameObjects.Mesh} mesh - The Mesh that requested this pipeline.
|
||||||
|
*
|
||||||
|
* @return {this} This WebGLPipeline instance.
|
||||||
|
*/
|
||||||
|
onBind: function (mesh)
|
||||||
|
{
|
||||||
|
var camera = mesh.camera;
|
||||||
|
|
||||||
|
if (camera.dirtyView || camera.dirtyProjection)
|
||||||
|
{
|
||||||
|
this.setMatrix4fv('uViewProjectionMatrix', false, camera.viewProjectionMatrix.val);
|
||||||
|
|
||||||
|
this.set3f('uCameraPosition', camera.x, camera.y, camera.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
var light = mesh.light;
|
||||||
|
|
||||||
|
if (light.isDirty())
|
||||||
|
{
|
||||||
|
this.set3f('uLightPosition', light.x, light.y, light.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ambient = light.ambient;
|
||||||
|
var diffuse = light.diffuse;
|
||||||
|
var specular = light.specular;
|
||||||
|
|
||||||
|
if (ambient.dirty)
|
||||||
|
{
|
||||||
|
this.set3f('uLightAmbient', ambient.r, ambient.g, ambient.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diffuse.dirty)
|
||||||
|
{
|
||||||
|
this.set3f('uLightDiffuse', diffuse.r, diffuse.g, diffuse.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (specular.dirty)
|
||||||
|
{
|
||||||
|
this.set3f('uLightSpecular', specular.r, specular.g, specular.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
var fogColor = mesh.fogColor;
|
||||||
|
|
||||||
|
if (fogColor.dirty)
|
||||||
|
{
|
||||||
|
this.set3f('uFogColor', fogColor.r, fogColor.g, fogColor.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cache = this.dirtyCache;
|
||||||
|
var fogNear = mesh.fogNear;
|
||||||
|
var fogFar = mesh.fogFar;
|
||||||
|
|
||||||
|
if (cache[0] !== fogNear)
|
||||||
|
{
|
||||||
|
this.set1f('uFogNear', fogNear);
|
||||||
|
|
||||||
|
cache[0] = fogNear;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache[1] !== fogFar)
|
||||||
|
{
|
||||||
|
this.set1f('uFogFar', fogFar);
|
||||||
|
|
||||||
|
cache[1] = fogFar;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set1i('uTexture', 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
drawModel: function (mesh, model)
|
||||||
|
{
|
||||||
|
var cache = this.dirtyCache;
|
||||||
|
|
||||||
|
this.setMatrix4fv('uModelMatrix', false, model.transformMatrix.val);
|
||||||
|
this.setMatrix4fv('uNormalMatrix', false, model.normalMatrix.val);
|
||||||
|
|
||||||
|
var ambient = model.ambient;
|
||||||
|
|
||||||
|
if (!ambient.equals(cache[2], cache[3], cache[4]))
|
||||||
|
{
|
||||||
|
this.set3f('uMaterialAmbient', ambient.r, ambient.g, ambient.b);
|
||||||
|
|
||||||
|
cache[2] = ambient.r;
|
||||||
|
cache[3] = ambient.g;
|
||||||
|
cache[4] = ambient.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
var diffuse = model.diffuse;
|
||||||
|
|
||||||
|
if (!diffuse.equals(cache[5], cache[6], cache[7]))
|
||||||
|
{
|
||||||
|
this.set3f('uMaterialDiffuse', diffuse.r, diffuse.g, diffuse.b);
|
||||||
|
|
||||||
|
cache[5] = diffuse.r;
|
||||||
|
cache[6] = diffuse.g;
|
||||||
|
cache[7] = diffuse.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
var specular = model.specular;
|
||||||
|
|
||||||
|
if (!specular.equals(cache[8], cache[9], cache[10]))
|
||||||
|
{
|
||||||
|
this.set3f('uMaterialSpecular', specular.r, specular.g, specular.b);
|
||||||
|
|
||||||
|
cache[8] = specular.r;
|
||||||
|
cache[9] = specular.g;
|
||||||
|
cache[10] = specular.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
var shine = model.shine;
|
||||||
|
|
||||||
|
if (!shine !== cache[11])
|
||||||
|
{
|
||||||
|
this.set1f('uMaterialShine', shine);
|
||||||
|
|
||||||
|
cache[11] = specular.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.renderer.setTextureZero(model.frame.glTexture);
|
||||||
|
|
||||||
|
// All the uniforms are finally bound, so let's buffer our data
|
||||||
|
var gl = this.gl;
|
||||||
|
|
||||||
|
var cullMode = model.cullMode;
|
||||||
|
|
||||||
|
if (cullMode !== this.cullMode)
|
||||||
|
{
|
||||||
|
this.cullMode = cullMode;
|
||||||
|
|
||||||
|
gl.cullFace(cullMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// STATIC because the buffer data doesn't change, the uniforms do
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, model.vertexData, gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
gl.drawArrays(this.topology, 0, model.vertexCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = MeshPipeline;
|
|
@ -54,7 +54,17 @@ var PIPELINE_CONST = {
|
||||||
* @const
|
* @const
|
||||||
* @since 3.50.0
|
* @since 3.50.0
|
||||||
*/
|
*/
|
||||||
ROPE_PIPELINE: 'RopePipeline'
|
ROPE_PIPELINE: 'RopePipeline',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Mesh Pipeline.
|
||||||
|
*
|
||||||
|
* @name Phaser.Renderer.WebGL.Pipelines.MESH_PIPELINE
|
||||||
|
* @type {string}
|
||||||
|
* @const
|
||||||
|
* @since 3.50.0
|
||||||
|
*/
|
||||||
|
MESH_PIPELINE: 'MeshPipeline'
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
54
src/renderer/webgl/shaders/Mesh-frag.js
Normal file
54
src/renderer/webgl/shaders/Mesh-frag.js
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
module.exports = [
|
||||||
|
'#define SHADER_NAME PHASER_MESH_FS',
|
||||||
|
'',
|
||||||
|
'precision mediump float;',
|
||||||
|
'',
|
||||||
|
'uniform vec3 uLightPosition;',
|
||||||
|
'uniform vec3 uLightAmbient;',
|
||||||
|
'uniform vec3 uLightDiffuse;',
|
||||||
|
'uniform vec3 uLightSpecular;',
|
||||||
|
'',
|
||||||
|
'uniform vec3 uFogColor;',
|
||||||
|
'uniform float uFogNear;',
|
||||||
|
'uniform float uFogFar;',
|
||||||
|
'',
|
||||||
|
'uniform vec3 uMaterialAmbient;',
|
||||||
|
'uniform vec3 uMaterialDiffuse;',
|
||||||
|
'uniform vec3 uMaterialSpecular;',
|
||||||
|
'uniform float uMaterialShine;',
|
||||||
|
'',
|
||||||
|
'uniform vec3 uCameraPosition;',
|
||||||
|
'',
|
||||||
|
'uniform sampler2D uTexture;',
|
||||||
|
'',
|
||||||
|
'varying vec2 vTextureCoord;',
|
||||||
|
'varying vec3 vNormal;',
|
||||||
|
'varying vec3 vPosition;',
|
||||||
|
'',
|
||||||
|
'void main (void)',
|
||||||
|
'{',
|
||||||
|
' vec4 color = texture2D(uTexture, vTextureCoord);',
|
||||||
|
'',
|
||||||
|
' vec3 ambient = uLightAmbient * uMaterialAmbient;',
|
||||||
|
'',
|
||||||
|
' vec3 norm = normalize(vNormal);',
|
||||||
|
' vec3 lightDir = normalize(uLightPosition - vPosition);',
|
||||||
|
' float diff = max(dot(norm, lightDir), 0.0);',
|
||||||
|
' vec3 diffuse = uLightDiffuse * (diff * uMaterialDiffuse);',
|
||||||
|
'',
|
||||||
|
' vec3 viewDir = normalize(uCameraPosition - vPosition);',
|
||||||
|
' vec3 reflectDir = reflect(-lightDir, norm);',
|
||||||
|
' float spec = pow(max(dot(viewDir, reflectDir), 0.0), uMaterialShine);',
|
||||||
|
' vec3 specular = uLightSpecular * (spec * uMaterialSpecular);',
|
||||||
|
'',
|
||||||
|
' vec3 result = (ambient + diffuse + specular) * color.rgb;',
|
||||||
|
'',
|
||||||
|
' float depth = gl_FragCoord.z / gl_FragCoord.w;',
|
||||||
|
'',
|
||||||
|
' float fogFactor = smoothstep(uFogNear, uFogFar, depth);',
|
||||||
|
'',
|
||||||
|
' gl_FragColor.rgb = mix(result.rgb, uFogColor, fogFactor);',
|
||||||
|
' gl_FragColor.a = color.a;',
|
||||||
|
'}',
|
||||||
|
''
|
||||||
|
].join('\n');
|
29
src/renderer/webgl/shaders/Mesh-vert.js
Normal file
29
src/renderer/webgl/shaders/Mesh-vert.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
module.exports = [
|
||||||
|
'#define SHADER_NAME PHASER_MESH_VS',
|
||||||
|
'',
|
||||||
|
'precision mediump float;',
|
||||||
|
'',
|
||||||
|
'attribute vec3 aVertexPosition;',
|
||||||
|
'attribute vec3 aVertexNormal;',
|
||||||
|
'attribute vec2 aTextureCoord;',
|
||||||
|
'',
|
||||||
|
'uniform mat4 uViewProjectionMatrix;',
|
||||||
|
'uniform mat4 uModelMatrix;',
|
||||||
|
'uniform mat4 uNormalMatrix;',
|
||||||
|
'',
|
||||||
|
'varying vec2 vTextureCoord;',
|
||||||
|
'varying vec3 vNormal;',
|
||||||
|
'varying vec3 vPosition;',
|
||||||
|
'',
|
||||||
|
'void main ()',
|
||||||
|
'{',
|
||||||
|
' vTextureCoord = aTextureCoord;',
|
||||||
|
'',
|
||||||
|
' vPosition = vec3(uModelMatrix * vec4(aVertexPosition, 1.0));',
|
||||||
|
'',
|
||||||
|
' vNormal = vec3(uNormalMatrix * vec4(aVertexNormal, 1.0));',
|
||||||
|
'',
|
||||||
|
' gl_Position = uViewProjectionMatrix * uModelMatrix * vec4(aVertexPosition, 1.0);',
|
||||||
|
'}',
|
||||||
|
''
|
||||||
|
].join('\n');
|
51
src/renderer/webgl/shaders/src/Mesh.frag
Normal file
51
src/renderer/webgl/shaders/src/Mesh.frag
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#define SHADER_NAME PHASER_MESH_FS
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
uniform vec3 uLightPosition;
|
||||||
|
uniform vec3 uLightAmbient;
|
||||||
|
uniform vec3 uLightDiffuse;
|
||||||
|
uniform vec3 uLightSpecular;
|
||||||
|
|
||||||
|
uniform vec3 uFogColor;
|
||||||
|
uniform float uFogNear;
|
||||||
|
uniform float uFogFar;
|
||||||
|
|
||||||
|
uniform vec3 uMaterialAmbient;
|
||||||
|
uniform vec3 uMaterialDiffuse;
|
||||||
|
uniform vec3 uMaterialSpecular;
|
||||||
|
uniform float uMaterialShine;
|
||||||
|
|
||||||
|
uniform vec3 uCameraPosition;
|
||||||
|
|
||||||
|
uniform sampler2D uTexture;
|
||||||
|
|
||||||
|
varying vec2 vTextureCoord;
|
||||||
|
varying vec3 vNormal;
|
||||||
|
varying vec3 vPosition;
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
vec4 color = texture2D(uTexture, vTextureCoord);
|
||||||
|
|
||||||
|
vec3 ambient = uLightAmbient * uMaterialAmbient;
|
||||||
|
|
||||||
|
vec3 norm = normalize(vNormal);
|
||||||
|
vec3 lightDir = normalize(uLightPosition - vPosition);
|
||||||
|
float diff = max(dot(norm, lightDir), 0.0);
|
||||||
|
vec3 diffuse = uLightDiffuse * (diff * uMaterialDiffuse);
|
||||||
|
|
||||||
|
vec3 viewDir = normalize(uCameraPosition - vPosition);
|
||||||
|
vec3 reflectDir = reflect(-lightDir, norm);
|
||||||
|
float spec = pow(max(dot(viewDir, reflectDir), 0.0), uMaterialShine);
|
||||||
|
vec3 specular = uLightSpecular * (spec * uMaterialSpecular);
|
||||||
|
|
||||||
|
vec3 result = (ambient + diffuse + specular) * color.rgb;
|
||||||
|
|
||||||
|
float depth = gl_FragCoord.z / gl_FragCoord.w;
|
||||||
|
|
||||||
|
float fogFactor = smoothstep(uFogNear, uFogFar, depth);
|
||||||
|
|
||||||
|
gl_FragColor.rgb = mix(result.rgb, uFogColor, fogFactor);
|
||||||
|
gl_FragColor.a = color.a;
|
||||||
|
}
|
26
src/renderer/webgl/shaders/src/Mesh.vert
Normal file
26
src/renderer/webgl/shaders/src/Mesh.vert
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#define SHADER_NAME PHASER_MESH_VS
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
attribute vec3 aVertexPosition;
|
||||||
|
attribute vec3 aVertexNormal;
|
||||||
|
attribute vec2 aTextureCoord;
|
||||||
|
|
||||||
|
uniform mat4 uViewProjectionMatrix;
|
||||||
|
uniform mat4 uModelMatrix;
|
||||||
|
uniform mat4 uNormalMatrix;
|
||||||
|
|
||||||
|
varying vec2 vTextureCoord;
|
||||||
|
varying vec3 vNormal;
|
||||||
|
varying vec3 vPosition;
|
||||||
|
|
||||||
|
void main ()
|
||||||
|
{
|
||||||
|
vTextureCoord = aTextureCoord;
|
||||||
|
|
||||||
|
vPosition = vec3(uModelMatrix * vec4(aVertexPosition, 1.0));
|
||||||
|
|
||||||
|
vNormal = vec3(uNormalMatrix * vec4(aVertexNormal, 1.0));
|
||||||
|
|
||||||
|
gl_Position = uViewProjectionMatrix * uModelMatrix * vec4(aVertexPosition, 1.0);
|
||||||
|
}
|
Loading…
Reference in a new issue