mirror of
https://github.com/photonstorm/phaser
synced 2024-11-22 20:53:39 +00:00
Added basic Geometry
This commit is contained in:
parent
6ab0803469
commit
5313356fb0
5 changed files with 503 additions and 0 deletions
83
src/layer3d/geometry/BufferAttribute.js
Normal file
83
src/layer3d/geometry/BufferAttribute.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* @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 BufferAttribute = new Class({
|
||||
|
||||
initialize:
|
||||
|
||||
function BufferAttribute (array, size, normalized)
|
||||
{
|
||||
/**
|
||||
* The array holding data stored in the buffer.
|
||||
* @type {TypedArray}
|
||||
*/
|
||||
this.array = array;
|
||||
|
||||
/**
|
||||
* The length of vectors that are being stored in the array.
|
||||
* @type {Integer}
|
||||
*/
|
||||
this.size = size;
|
||||
|
||||
/**
|
||||
* Stores the array's length divided by the size.
|
||||
* If the buffer is storing a 3-component vector (such as a position, normal, or color), then this will count the number of such vectors stored.
|
||||
* @type {Integer}
|
||||
*/
|
||||
this.count = array !== undefined ? array.length / size : 0;
|
||||
|
||||
/**
|
||||
* Indicates how the underlying data in the buffer maps to the values in the GLSL shader code.
|
||||
* See the constructor above for details.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.normalized = normalized === true;
|
||||
|
||||
/**
|
||||
* Whether the buffer is dynamic or not.
|
||||
* If false, the GPU is informed that contents of the buffer are likely to be used often and not change often.
|
||||
* This corresponds to the gl.STATIC_DRAW flag.
|
||||
* If true, the GPU is informed that contents of the buffer are likely to be used often and change often.
|
||||
* This corresponds to the gl.DYNAMIC_DRAW flag.
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.dynamic = false;
|
||||
|
||||
/**
|
||||
* Object containing:
|
||||
* offset: Default is 0. Position at whcih to start update.
|
||||
* count: Default is -1, which means don't use update ranges.
|
||||
* This can be used to only update some components of stored vectors (for example, just the component related to color).
|
||||
*/
|
||||
this.updateRange = { offset: 0, count: -1 };
|
||||
|
||||
/**
|
||||
* A version number, incremented every time the data changes.
|
||||
* @type {Integer}
|
||||
* @default 0
|
||||
*/
|
||||
this.version = 0;
|
||||
},
|
||||
|
||||
setArray: function (array)
|
||||
{
|
||||
this.count = array !== undefined ? array.length / this.size : 0;
|
||||
|
||||
this.array = array;
|
||||
|
||||
// inc version?
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// copy / clone?
|
||||
|
||||
});
|
||||
|
||||
module.exports = BufferAttribute;
|
185
src/layer3d/geometry/Geometry.js
Normal file
185
src/layer3d/geometry/Geometry.js
Normal file
|
@ -0,0 +1,185 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2020 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Box3 = require('../math/Box3');
|
||||
var BufferAttribute = require('./BufferAttribute');
|
||||
var Class = require('../../utils/Class');
|
||||
var Sphere = require('../math/Sphere');
|
||||
|
||||
var geometryId = 1;
|
||||
|
||||
var Geometry = new Class({
|
||||
|
||||
initialize:
|
||||
|
||||
function Geometry ()
|
||||
{
|
||||
this.id = geometryId++;
|
||||
|
||||
/**
|
||||
* This hashmap has an id the name of the attribute to be set and as value the buffer to set it to.
|
||||
* Rather than accessing this property directly, use `addAttribute` and `getAttribute` to access attributes of this geometry.
|
||||
*/
|
||||
this.attributes = {};
|
||||
|
||||
/**
|
||||
* Hashmap of Attributes Array for morph targets.
|
||||
*/
|
||||
this.morphAttributes = {};
|
||||
|
||||
/**
|
||||
* Allows for vertices to be re-used across multiple triangles; this is called using "indexed triangles" and each triangle is associated with the indices of three vertices.
|
||||
* This attribute therefore stores the index of each vertex for each triangular face.
|
||||
* If this attribute is not set, the renderer assumes that each three contiguous positions represent a single triangle.
|
||||
* @type {BufferAttribute}
|
||||
*/
|
||||
this.index = null;
|
||||
|
||||
/**
|
||||
* Bounding box for the bufferGeometry, which can be calculated with `computeBoundingBox`.
|
||||
* @type {Box3}
|
||||
*/
|
||||
this.boundingBox = new Box3();
|
||||
|
||||
/**
|
||||
* Bounding sphere for the bufferGeometry, which can be calculated with `computeBoundingSphere`.
|
||||
* @type {Sphere}
|
||||
*/
|
||||
this.boundingSphere = new Sphere();
|
||||
|
||||
/**
|
||||
* Split the geometry into groups, each of which will be rendered in a separate WebGL draw call. This allows an array of materials to be used with the geometry.
|
||||
* Each group is an object of the form:
|
||||
* { start: Integer, count: Integer, materialIndex: Integer }
|
||||
*/
|
||||
this.groups = [];
|
||||
|
||||
/**
|
||||
* A version number, incremented every time the attribute object or index object changes to mark VAO drity.
|
||||
*/
|
||||
this.version = 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds an attribute to this geometry.
|
||||
* Use this rather than the attributes property.
|
||||
* @param {string} name
|
||||
* @param {BufferAttribute|InterleavedBufferAttribute} attribute
|
||||
*/
|
||||
addAttribute: function (name, attribute)
|
||||
{
|
||||
this.attributes[name] = attribute;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the attribute with the specified name.
|
||||
* @return {BufferAttribute|InterleavedBufferAttribute}
|
||||
*/
|
||||
getAttribute: function (name)
|
||||
{
|
||||
return this.attributes[name];
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the attribute with the specified name.
|
||||
*/
|
||||
removeAttribute: function (name)
|
||||
{
|
||||
delete this.attributes[name];
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the index buffer.
|
||||
* @param {Array|BufferAttribute} index
|
||||
*/
|
||||
setIndex: function (index)
|
||||
{
|
||||
if (Array.isArray(index))
|
||||
{
|
||||
this.index = new BufferAttribute(new Uint16Array(index), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a group to this geometry; see the groups for details.
|
||||
* @param {number} start
|
||||
* @param {number} count
|
||||
* @param {number} materialIndex
|
||||
*/
|
||||
addGroup: function (start, count, materialIndex)
|
||||
{
|
||||
this.groups.push({
|
||||
start: start,
|
||||
count: count,
|
||||
materialIndex: materialIndex !== undefined ? materialIndex : 0
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears all groups.
|
||||
*/
|
||||
clearGroups: function ()
|
||||
{
|
||||
this.groups = [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Computes bounding box of the geometry, updating `boundingBox`.
|
||||
* Bounding boxes aren't computed by default. They need to be explicitly computed.
|
||||
*/
|
||||
computeBoundingBox: function ()
|
||||
{
|
||||
var position = this.attributes['a_Position'] || this.attributes['position'];
|
||||
|
||||
if (position.isInterleavedBufferAttribute)
|
||||
{
|
||||
var data = position.data;
|
||||
|
||||
this.boundingBox.setFromArray(data.array, data.stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.boundingBox.setFromArray(position.array, position.size);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Computes bounding sphere of the geometry, updating `boundingSphere`.
|
||||
*
|
||||
* Bounding spheres aren't computed by default. They need to be explicitly computed.
|
||||
*/
|
||||
computeBoundingSphere: function ()
|
||||
{
|
||||
var position = this.attributes['a_Position'] || this.attributes['position'];
|
||||
|
||||
if (position.isInterleavedBufferAttribute)
|
||||
{
|
||||
var data = position.data;
|
||||
|
||||
this.boundingSphere.setFromArray(data.array, data.stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.boundingSphere.setFromArray(position.array, position.size);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Disposes the object from memory.
|
||||
* You need to call this when you want the BufferGeometry removed while the application is running.
|
||||
*/
|
||||
dispose: function ()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = Geometry;
|
100
src/layer3d/geometry/PlaneGeometry.js
Normal file
100
src/layer3d/geometry/PlaneGeometry.js
Normal file
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2020 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var BufferAttribute = require('./BufferAttribute');
|
||||
var Class = require('../../utils/Class');
|
||||
var Geometry = require('./Geometry');
|
||||
|
||||
var PlaneGeometry = new Class({
|
||||
|
||||
Extends: Geometry,
|
||||
|
||||
initialize:
|
||||
|
||||
function PlaneGeometry (width, height, widthSegments, heightSegments)
|
||||
{
|
||||
Geometry.call(this);
|
||||
|
||||
this.build(width, height, widthSegments, heightSegments);
|
||||
},
|
||||
|
||||
build: function (width, height, widthSegments, heightSegments)
|
||||
{
|
||||
width = width || 1;
|
||||
height = height || 1;
|
||||
|
||||
var halfWidth = width / 2;
|
||||
var halfHeight = height / 2;
|
||||
|
||||
var gridX = Math.floor(widthSegments) || 1;
|
||||
var gridY = Math.floor(heightSegments) || 1;
|
||||
|
||||
var gridX1 = gridX + 1;
|
||||
var gridY1 = gridY + 1;
|
||||
|
||||
var segmentWidth = width / gridX;
|
||||
var segmentHeight = height / gridY;
|
||||
|
||||
var ix, iy;
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for (iy = 0; iy < gridY1; iy++)
|
||||
{
|
||||
var y = iy * segmentHeight - halfHeight;
|
||||
|
||||
for (ix = 0; ix < gridX1; ix++)
|
||||
{
|
||||
var x = ix * segmentWidth - halfWidth;
|
||||
|
||||
vertices.push(x, 0, y);
|
||||
|
||||
normals.push(0, 1, 0);
|
||||
|
||||
uvs.push(ix / gridX);
|
||||
uvs.push(1 - (iy / gridY));
|
||||
}
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
for (iy = 0; iy < gridY; iy++)
|
||||
{
|
||||
for (ix = 0; ix < gridX; ix++)
|
||||
{
|
||||
var a = ix + gridX1 * iy;
|
||||
var b = ix + gridX1 * (iy + 1);
|
||||
var c = (ix + 1) + gridX1 * (iy + 1);
|
||||
var d = (ix + 1) + gridX1 * iy;
|
||||
|
||||
// faces
|
||||
|
||||
indices.push(a, b, d);
|
||||
indices.push(b, c, d);
|
||||
}
|
||||
}
|
||||
|
||||
// build geometry
|
||||
|
||||
this.setIndex(indices);
|
||||
this.addAttribute('a_Position', new BufferAttribute(new Float32Array(vertices), 3));
|
||||
this.addAttribute('a_Normal', new BufferAttribute(new Float32Array(normals), 3));
|
||||
this.addAttribute('a_Uv', new BufferAttribute(new Float32Array(uvs), 2));
|
||||
|
||||
this.computeBoundingBox();
|
||||
this.computeBoundingSphere();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = PlaneGeometry;
|
117
src/layer3d/geometry/SphereGeometry.js
Normal file
117
src/layer3d/geometry/SphereGeometry.js
Normal file
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2020 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var BufferAttribute = require('./BufferAttribute');
|
||||
var Class = require('../../utils/Class');
|
||||
var Geometry = require('./Geometry');
|
||||
var Vector3 = require('../../math/Vector3');
|
||||
|
||||
var SphereGeometry = new Class({
|
||||
|
||||
Extends: Geometry,
|
||||
|
||||
initialize:
|
||||
|
||||
function SphereGeometry (radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength)
|
||||
{
|
||||
Geometry.call(this);
|
||||
|
||||
this.build(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength);
|
||||
},
|
||||
|
||||
build: function (radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength)
|
||||
{
|
||||
radius = radius || 1;
|
||||
|
||||
widthSegments = Math.max(3, Math.floor(widthSegments) || 8);
|
||||
heightSegments = Math.max(2, Math.floor(heightSegments) || 6);
|
||||
|
||||
phiStart = phiStart !== undefined ? phiStart : 0;
|
||||
phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
|
||||
|
||||
thetaStart = thetaStart !== undefined ? thetaStart : 0;
|
||||
thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
|
||||
|
||||
var thetaEnd = thetaStart + thetaLength;
|
||||
|
||||
var ix, iy;
|
||||
|
||||
var index = 0;
|
||||
var grid = [];
|
||||
|
||||
var vertex = new Vector3();
|
||||
var normal = new Vector3();
|
||||
|
||||
// buffers
|
||||
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for (iy = 0; iy <= heightSegments; iy++)
|
||||
{
|
||||
var verticesRow = [];
|
||||
|
||||
var v = iy / heightSegments;
|
||||
|
||||
for (ix = 0; ix <= widthSegments; ix++)
|
||||
{
|
||||
var u = ix / widthSegments;
|
||||
|
||||
// vertex
|
||||
|
||||
vertex.x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
|
||||
vertex.y = radius * Math.cos(thetaStart + v * thetaLength);
|
||||
vertex.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
|
||||
|
||||
vertices.push(vertex.x, vertex.y, vertex.z);
|
||||
|
||||
// normal
|
||||
|
||||
normal.set(vertex.x, vertex.y, vertex.z).normalize();
|
||||
normals.push(normal.x, normal.y, normal.z);
|
||||
|
||||
// uv
|
||||
|
||||
uvs.push(u, 1 - v);
|
||||
|
||||
verticesRow.push(index++);
|
||||
}
|
||||
|
||||
grid.push(verticesRow);
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
for (iy = 0; iy < heightSegments; iy++)
|
||||
{
|
||||
for (ix = 0; ix < widthSegments; ix++)
|
||||
{
|
||||
var a = grid[iy][ix + 1];
|
||||
var b = grid[iy][ix];
|
||||
var c = grid[iy + 1][ix];
|
||||
var d = grid[iy + 1][ix + 1];
|
||||
|
||||
if (iy !== 0 || thetaStart > 0) { indices.push(a, b, d); }
|
||||
if (iy !== heightSegments - 1 || thetaEnd < Math.PI) { indices.push(b, c, d); }
|
||||
}
|
||||
}
|
||||
|
||||
this.setIndex(indices);
|
||||
this.addAttribute('a_Position', new BufferAttribute(new Float32Array(vertices), 3));
|
||||
this.addAttribute('a_Normal', new BufferAttribute(new Float32Array(normals), 3));
|
||||
this.addAttribute('a_Uv', new BufferAttribute(new Float32Array(uvs), 2));
|
||||
|
||||
this.computeBoundingBox();
|
||||
this.computeBoundingSphere();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = SphereGeometry;
|
18
src/layer3d/geometry/index.js
Normal file
18
src/layer3d/geometry/index.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2020 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @namespace Phaser.Layer3D.Geometry
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
|
||||
BufferAttribute: require('./BufferAttribute'),
|
||||
Geometry: require('./Geometry'),
|
||||
PlaneGeometry: require('./PlaneGeometry'),
|
||||
SphereGeometry: require('./SphereGeometry')
|
||||
|
||||
};
|
Loading…
Reference in a new issue