初始化

This commit is contained in:
SmallMain
2022-06-25 00:23:03 +08:00
commit ef0589e8e5
2264 changed files with 617829 additions and 0 deletions

View File

@@ -0,0 +1,573 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
const renderer = require('../renderer');
const EventTarget = require('../event/event-target');
import InputAssembler from '../../renderer/core/input-assembler';
import gfx from '../../renderer/gfx';
import { Primitive, VertexBundle, MeshData} from './mesh-data';
function applyColor (data, offset, value) {
data[offset] = value._val;
}
function applyVec2 (data, offset, value) {
data[offset] = value.x;
data[offset + 1] = value.y;
}
function applyVec3 (data, offset, value) {
data[offset] = value.x;
data[offset + 1] = value.y;
data[offset + 2] = value.z;
}
const _compType2fn = {
5120: 'getInt8',
5121: 'getUint8',
5122: 'getInt16',
5123: 'getUint16',
5124: 'getInt32',
5125: 'getUint32',
5126: 'getFloat32',
};
const _compType2write = {
5120: 'setInt8',
5121: 'setUint8',
5122: 'setInt16',
5123: 'setUint16',
5124: 'setInt32',
5125: 'setUint32',
5126: 'setFloat32',
};
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness
const littleEndian = (function () {
let buffer = new ArrayBuffer(2);
new DataView(buffer).setInt16(0, 256, true);
// Int16Array uses the platform's endianness.
return new Int16Array(buffer)[0] === 256;
})();
/**
* @module cc
*/
/**
* !#en Mesh Asset.
* !#zh 网格资源。
* @class Mesh
* @extends Asset
* @uses EventTarget
*/
let Mesh = cc.Class({
name: 'cc.Mesh',
extends: cc.Asset,
mixins: [EventTarget],
properties: {
_nativeAsset: {
override: true,
get () {
return this._buffer;
},
set (bin) {
this._buffer = ArrayBuffer.isView(bin) ? bin.buffer : bin;
this.initWithBuffer();
}
},
_vertexBundles: {
default: null,
type: VertexBundle
},
_primitives: {
default: null,
Primitive
},
_minPos: cc.v3(),
_maxPos: cc.v3(),
/**
* !#en Get ir set the sub meshes.
* !#zh 设置或者获取子网格。
* @property {[InputAssembler]} subMeshes
*/
subMeshes: {
get () {
return this._subMeshes;
},
set (v) {
this._subMeshes = v;
}
},
subDatas : {
get () {
return this._subDatas;
}
}
},
ctor () {
this._subMeshes = [];
this._subDatas = [];
this.loaded = false;
},
initWithBuffer () {
this._subMeshes.length = 0;
let primitives = this._primitives;
for (let i = 0; i < primitives.length; i++) {
let primitive = primitives[i];
// ib
let ibrange = primitive.data;
let ibData = new Uint8Array(this._buffer, ibrange.offset, ibrange.length);
// vb
let vertexBundle = this._vertexBundles[primitive.vertexBundleIndices[0]];
let vbRange = vertexBundle.data;
let gfxVFmt = new gfx.VertexFormat(vertexBundle.formats);
// Mesh binary may have several data format, must use Uint8Array to store data.
let vbData = new Uint8Array(this._buffer, vbRange.offset, vbRange.length);
let canBatch = this._canVertexFormatBatch(gfxVFmt);
let meshData = new MeshData();
meshData.vData = vbData;
meshData.iData = ibData;
meshData.vfm = gfxVFmt;
meshData.offset = vbRange.offset;
meshData.canBatch = canBatch;
this._subDatas.push(meshData);
if (CC_JSB && CC_NATIVERENDERER) {
meshData.vDirty = true;
this._subMeshes.push(new InputAssembler(null, null));
} else {
let vbBuffer = new gfx.VertexBuffer(
renderer.device,
gfxVFmt,
gfx.USAGE_STATIC,
vbData
);
let ibBuffer = new gfx.IndexBuffer(
renderer.device,
primitive.indexUnit,
gfx.USAGE_STATIC,
ibData
);
// create sub meshes
this._subMeshes.push(new InputAssembler(vbBuffer, ibBuffer));
}
}
this.loaded = true;
this.emit('load');
},
_canVertexFormatBatch (format) {
let aPosition = format._attr2el[gfx.ATTR_POSITION];
let canBatch = !aPosition ||
(aPosition.type === gfx.ATTR_TYPE_FLOAT32 &&
format._bytes % 4 === 0);
return canBatch;
},
/**
* !#en
* Init vertex buffer according to the vertex format.
* !#zh
* 根据顶点格式初始化顶点内存。
* @method init
* @param {gfx.VertexFormat} vertexFormat - vertex format
* @param {Number} vertexCount - how much vertex should be create in this buffer.
* @param {Boolean} [dynamic] - whether or not to use dynamic buffer.
* @param {Boolean} [index]
*/
init (vertexFormat, vertexCount, dynamic = false, index = 0) {
let data = new Uint8Array(vertexFormat._bytes * vertexCount);
let meshData = new MeshData();
meshData.vData = data;
meshData.vfm = vertexFormat;
meshData.vDirty = true;
meshData.canBatch = this._canVertexFormatBatch(vertexFormat);
if (!(CC_JSB && CC_NATIVERENDERER)) {
let vb = new gfx.VertexBuffer(
renderer.device,
vertexFormat,
dynamic ? gfx.USAGE_DYNAMIC : gfx.USAGE_STATIC,
data,
);
meshData.vb = vb;
this._subMeshes[index] = new InputAssembler(meshData.vb);
}
let oldSubData = this._subDatas[index];
if (oldSubData) {
if (oldSubData.vb) {
oldSubData.vb.destroy();
}
if (oldSubData.ib) {
oldSubData.ib.destroy();
}
}
this._subDatas[index] = meshData;
this.loaded = true;
this.emit('load');
this.emit('init-format');
},
/**
* !#en
* Set the vertex values.
* !#zh
* 设置顶点数据
* @method setVertices
* @param {String} name - the attribute name, e.g. gfx.ATTR_POSITION
* @param {[Vec2] | [Vec3] | [Color] | [Number] | Uint8Array | Float32Array} values - the vertex values
*/
setVertices (name, values, index) {
index = index || 0;
let subData = this._subDatas[index];
let el = subData.vfm.element(name);
if (!el) {
return cc.warn(`Cannot find ${name} attribute in vertex defines.`);
}
// whether the values is expanded
let isFlatMode = typeof values[0] === 'number';
let elNum = el.num;
let verticesCount = isFlatMode ? ((values.length / elNum) | 0) : values.length;
if (subData.vData.byteLength < verticesCount * el.stride) {
subData.setVData(new Uint8Array(verticesCount * subData.vfm._bytes));
}
let data;
let bytes = 4;
if (name === gfx.ATTR_COLOR) {
if (!isFlatMode) {
data = subData.getVData(Uint32Array);
}
else {
data = subData.getVData();
bytes = 1;
}
}
else {
data = subData.getVData(Float32Array);
}
let stride = el.stride / bytes;
let offset = el.offset / bytes;
if (isFlatMode) {
for (let i = 0, l = (values.length / elNum); i < l; i++) {
let sOffset = i * elNum;
let dOffset = i * stride + offset;
for (let j = 0; j < elNum; j++) {
data[dOffset + j] = values[sOffset + j];
}
}
}
else {
let applyFunc;
if (name === gfx.ATTR_COLOR) {
applyFunc = applyColor;
}
else {
if (elNum === 2) {
applyFunc = applyVec2;
}
else {
applyFunc = applyVec3;
}
}
for (let i = 0, l = values.length; i < l; i++) {
let v = values[i];
let vOffset = i * stride + offset;
applyFunc(data, vOffset, v);
}
}
subData.vDirty = true;
},
/**
* !#en
* Set the sub mesh indices.
* !#zh
* 设置子网格索引。
* @method setIndices
* @param {[Number]|Uint16Array|Uint8Array} indices - the sub mesh indices.
* @param {Number} [index] - sub mesh index.
* @param {Boolean} [dynamic] - whether or not to use dynamic buffer.
*/
setIndices (indices, index, dynamic) {
index = index || 0;
let iData = indices;
if (indices instanceof Uint16Array) {
iData = new Uint8Array(indices.buffer, indices.byteOffset, indices.byteLength);
}
else if (Array.isArray(indices)) {
iData = new Uint16Array(indices);
iData = new Uint8Array(iData.buffer, iData.byteOffset, iData.byteLength);
}
let usage = dynamic ? gfx.USAGE_DYNAMIC : gfx.USAGE_STATIC;
let subData = this._subDatas[index];
if (!subData.ib) {
subData.iData = iData;
if (!(CC_JSB && CC_NATIVERENDERER)) {
let buffer = new gfx.IndexBuffer(
renderer.device,
gfx.INDEX_FMT_UINT16,
usage,
iData,
iData.byteLength / gfx.IndexBuffer.BYTES_PER_INDEX[gfx.INDEX_FMT_UINT16]
);
subData.ib = buffer;
this._subMeshes[index]._indexBuffer = subData.ib;
}
}
else {
subData.iData = iData;
subData.iDirty = true;
}
},
/**
* !#en
* Set the sub mesh primitive type.
* !#zh
* 设置子网格绘制线条的方式。
* @method setPrimitiveType
* @param {Number} type
* @param {Number} index
*/
setPrimitiveType (type, index) {
index = index || 0;
let subMesh = this._subMeshes[index];
if (!subMesh) {
cc.warn(`Do not have sub mesh at index ${index}`);
return;
}
this._subMeshes[index]._primitiveType = type;
},
/**
* !#en
* Clear the buffer data.
* !#zh
* 清除网格创建的内存数据。
* @method clear
*/
clear () {
this._subMeshes.length = 0;
let subDatas = this._subDatas;
for (let i = 0, len = subDatas.length; i < len; i++) {
let vb = subDatas[i].vb;
if (vb) {
vb.destroy();
}
let ib = subDatas[i].ib;
if (ib) {
ib.destroy();
}
}
subDatas.length = 0;
},
/**
* !#en Set mesh bounding box
* !#zh 设置网格的包围盒
* @method setBoundingBox
* @param {Vec3} min
* @param {Vec3} max
*/
setBoundingBox (min, max) {
this._minPos = min;
this._maxPos = max;
},
destroy () {
this.clear();
},
_uploadData () {
let subDatas = this._subDatas;
for (let i = 0, len = subDatas.length; i < len; i++) {
let subData = subDatas[i];
if (subData.vDirty) {
let buffer = subData.vb, data = subData.vData;
buffer.update(0, data);
subData.vDirty = false;
}
if (subData.iDirty) {
let buffer = subData.ib, data = subData.iData;
buffer.update(0, data);
subData.iDirty = false;
}
}
},
_getAttrMeshData (subDataIndex, name) {
let subData = this._subDatas[subDataIndex];
if (!subData) return [];
let format = subData.vfm;
let fmt = format.element(name);
if (!fmt) return [];
if (!subData.attrDatas) {
subData.attrDatas = {};
}
let attrDatas = subData.attrDatas;
let data = attrDatas[name];
if (data) {
return data;
}
else {
data = attrDatas[name] = [];
}
let vbData = subData.vData;
let dv = new DataView(vbData.buffer, vbData.byteOffset, vbData.byteLength);
let stride = fmt.stride;
let eleOffset = fmt.offset;
let eleNum = fmt.num;
let eleByte = fmt.bytes / eleNum;
let fn = _compType2fn[fmt.type];
let vertexCount = vbData.byteLength / format._bytes;
for (let i = 0; i < vertexCount; i++) {
let offset = i * stride + eleOffset;
for (let j = 0; j < eleNum; j++) {
let v = dv[fn](offset + j * eleByte, littleEndian);
data.push(v);
}
}
return data;
},
/**
* !#en Read the specified attributes of the subgrid into the target buffer.
* !#zh 读取子网格的指定属性到目标缓冲区中。
* @param {Number} primitiveIndex The subgrid index.
     * @param {String} attributeName attribute name.
     * @param {ArrayBuffer} buffer The target buffer.
     * @param {Number} stride The byte interval between adjacent attributes in the target buffer.
     * @param {Number} offset The offset of the first attribute in the target buffer.
     * @returns {Boolean} If the specified sub-grid does not exist, the sub-grid does not exist, or the specified attribute cannot be read, return `false`, otherwise return` true`.
* @method copyAttribute
*/
copyAttribute (primitiveIndex, attributeName, buffer, stride, offset) {
let written = false;
let subData = this._subDatas[primitiveIndex];
if (!subData) return written;
let format = subData.vfm;
let fmt = format.element(attributeName);
if (!fmt) return written;
let writter = _compType2write[fmt.type];
if (!writter) return written;
let data = this._getAttrMeshData(primitiveIndex, attributeName);
let vertexCount = subData.vData.byteLength / format._bytes;
let eleByte = fmt.bytes / fmt.num;
if (data.length > 0) {
const outputView = new DataView(buffer, offset);
let outputStride = stride;
let num = fmt.num;
for (let i = 0; i < vertexCount; ++i) {
let index = i * num;
for (let j = 0; j < num; ++j) {
const inputOffset = index + j;
const outputOffset = outputStride * i + eleByte * j;
outputView[writter](outputOffset, data[inputOffset], littleEndian);
}
}
written = true;
}
return written;
},
/**
* !#en Read the index data of the subgrid into the target array.
* !#zh 读取子网格的索引数据到目标数组中。
* @param {Number} primitiveIndex The subgrid index.
     * @param {TypedArray} outputArray The target array.
     * @returns {Boolean} returns `false` if the specified sub-grid does not exist or the sub-grid does not have index data, otherwise returns` true`.
* @method copyIndices
*/
copyIndices (primitiveIndex, outputArray) {
let subData = this._subDatas[primitiveIndex];
if (!subData) return false;
const iData = subData.iData;
const indexCount = iData.length / 2;
const dv = new DataView(iData.buffer, iData.byteOffset, iData.byteLength);
const fn = _compType2fn[gfx.INDEX_FMT_UINT8];
for (let i = 0; i < indexCount; ++i) {
outputArray[i] = dv[fn](i * 2);
}
return true;
}
});
cc.Mesh = module.exports = Mesh;

View File

@@ -0,0 +1,482 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import gfx from '../../renderer/gfx';
import InputAssembler from '../../renderer/core/input-assembler';
import Aabb from '../geom-utils/aabb';
import Vec3 from '../value-types/vec3';
import Mat4 from '../value-types/mat4';
import MaterialVariant from '../assets/material/material-variant';
const RenderComponent = require('../components/CCRenderComponent');
const Mesh = require('./CCMesh');
const RenderFlow = require('../renderer/render-flow');
const Renderer = require('../renderer');
const Material = require('../assets/material/CCMaterial');
/**
* !#en Shadow projection mode
*
* !#ch 阴影投射方式
* @static
* @enum MeshRenderer.ShadowCastingMode
*/
let ShadowCastingMode = cc.Enum({
/**
* !#en
*
* !#ch 关闭阴影投射
* @property OFF
* @readonly
* @type {Number}
*/
OFF: 0,
/**
* !#en
*
* !#ch 开启阴影投射,当阴影光产生的时候
* @property ON
* @readonly
* @type {Number}
*/
ON: 1,
// /**
// * !#en
// *
// * !#ch 可以从网格的任意一遍投射出阴影
// * @property TWO_SIDED
// * @readonly
// * @type {Number}
// */
// TWO_SIDED: 2,
// /**
// * !#en
// *
// * !#ch 只显示阴影
// * @property SHADOWS_ONLY
// * @readonly
// * @type {Number}
// */
// SHADOWS_ONLY: 3,
});
/**
* !#en
* Mesh Renderer Component
* !#zh
* 网格渲染组件
* @class MeshRenderer
* @extends RenderComponent
*/
let MeshRenderer = cc.Class({
name: 'cc.MeshRenderer',
extends: RenderComponent,
editor: CC_EDITOR && {
menu: 'i18n:MAIN_MENU.component.mesh/MeshRenderer',
},
properties: {
_mesh: {
default: null,
type: Mesh
},
_receiveShadows: false,
_shadowCastingMode: ShadowCastingMode.OFF,
_enableAutoBatch: false,
/**
* !#en
* The mesh which the renderer uses.
* !#zh
* 设置使用的网格
* @property {Mesh} mesh
*/
mesh: {
get () {
return this._mesh;
},
set (v) {
if (this._mesh === v) return;
this._setMesh(v);
if (!v) {
this.disableRender();
return;
}
this.markForRender(true);
this.node._renderFlag |= RenderFlow.FLAG_TRANSFORM;
},
type: Mesh,
animatable: false
},
textures: {
default: [],
type: cc.Texture2D,
visible: false
},
/**
* !#en
* Whether the mesh should receive shadows.
* !#zh
* 网格是否接受光源投射的阴影
* @property {Boolean} receiveShadows
*/
receiveShadows: {
get () {
return this._receiveShadows;
},
set (val) {
this._receiveShadows = val;
this._updateReceiveShadow();
},
animatable: false
},
/**
* !#en
* Shadow Casting Mode
* !#zh
* 网格投射阴影的模式
* @property {ShadowCastingMode} shadowCastingMode
*/
shadowCastingMode: {
get () {
return this._shadowCastingMode;
},
set (val) {
this._shadowCastingMode = val;
this._updateCastShadow();
},
type: ShadowCastingMode,
animatable: false
},
/**
* !#en
* Enable auto merge mesh, only support when mesh's VertexFormat, PrimitiveType, materials are all the same
* !#zh
* 开启自动合并 mesh 功能,只有在网格的 顶点格式PrimitiveType, 使用的材质 都一致的情况下才会有效
* @property {Boolean} enableAutoBatch
*/
enableAutoBatch: {
get () {
return this._enableAutoBatch;
},
set (val) {
this._enableAutoBatch = val;
}
},
},
statics: {
ShadowCastingMode: ShadowCastingMode
},
ctor () {
this._boundingBox = cc.geomUtils && new Aabb();
if (CC_DEBUG) {
this._debugDatas = {
wireFrame: [],
normal: []
};
}
},
onEnable () {
this._super();
if (this._mesh && !this._mesh.loaded) {
this.disableRender();
this._mesh.once('load', () => {
if (!this.isValid) return;
this._setMesh(this._mesh);
this.markForRender(true);
});
cc.assetManager.postLoadNative(this._mesh);
}
else {
this._setMesh(this._mesh);
}
this._updateRenderNode();
this._updateMaterial();
},
onDestroy () {
this._setMesh(null);
cc.pool.assembler.put(this._assembler);
},
_updateRenderNode () {
this._assembler.setRenderNode(this.node);
},
_setMesh (mesh) {
if (cc.geomUtils && mesh) {
Aabb.fromPoints(this._boundingBox, mesh._minPos, mesh._maxPos);
}
if (this._mesh) {
this._mesh.off('init-format', this._updateMeshAttribute, this);
}
if (mesh) {
mesh.on('init-format', this._updateMeshAttribute, this);
}
this._mesh = mesh;
this._assembler && (this._assembler._worldDatas = {});
this._updateMeshAttribute();
},
_getDefaultMaterial () {
return Material.getBuiltinMaterial('unlit');
},
_validateRender () {
let mesh = this._mesh;
if (mesh && mesh._subDatas.length > 0) {
return;
}
this.disableRender();
},
_updateMaterial () {
// TODO: used to upgrade from 2.1, should be removed
let textures = this.textures;
if (textures && textures.length > 0) {
let defaultMaterial = this._getDefaultMaterial();
for (let i = 0; i < textures.length; i++) {
let material = this._materials[i];
if (material && material._uuid !== defaultMaterial._uuid) continue;
if (!material) {
material = MaterialVariant.create(defaultMaterial, this);
this.setMaterial(i, material);
}
material.setProperty('diffuseTexture', textures[i]);
}
}
this._updateReceiveShadow();
this._updateCastShadow();
this._updateMeshAttribute();
},
_updateReceiveShadow () {
let materials = this.getMaterials();
for (let i = 0; i < materials.length; i++) {
materials[i].define('CC_USE_SHADOW_MAP', this._receiveShadows, undefined, true);
}
},
_updateCastShadow () {
let materials = this.getMaterials();
for (let i = 0; i < materials.length; i++) {
materials[i].define('CC_CASTING_SHADOW', this._shadowCastingMode === ShadowCastingMode.ON, undefined, true);
}
},
_updateMeshAttribute () {
let subDatas = this._mesh && this._mesh.subDatas;
if (!subDatas) return;
let materials = this.getMaterials();
for (let i = 0; i < materials.length; i++) {
if (!subDatas[i]) break;
let vfm = subDatas[i].vfm;
let material = materials[i];
material.define('CC_USE_ATTRIBUTE_COLOR', !!vfm.element(gfx.ATTR_COLOR), undefined, true);
material.define('CC_USE_ATTRIBUTE_UV0', !!vfm.element(gfx.ATTR_UV0), undefined, true);
material.define('CC_USE_ATTRIBUTE_NORMAL', !!vfm.element(gfx.ATTR_NORMAL), undefined, true);
material.define('CC_USE_ATTRIBUTE_TANGENT', !!vfm.element(gfx.ATTR_TANGENT), undefined, true);
}
if (CC_DEBUG) {
for (let name in this._debugDatas) {
this._debugDatas[name].length = 0;
}
}
if (CC_JSB && CC_NATIVERENDERER) {
this._assembler.updateMeshData(this);
}
},
_checkBacth () {
},
});
if (CC_DEBUG) {
const BLACK_COLOR = cc.Color.BLACK;
const RED_COLOR = cc.Color.RED;
let v3_tmp = [cc.v3(), cc.v3()];
let mat4_tmp = cc.mat4();
let createDebugDataFns = {
normal (comp, ia, subData, subIndex) {
let oldVfm = subData.vfm;
let normalEle = oldVfm.element(gfx.ATTR_NORMAL);
let posEle = oldVfm.element(gfx.ATTR_POSITION);
let jointEle = oldVfm.element(gfx.ATTR_JOINTS);
let weightEle = oldVfm.element(gfx.ATTR_WEIGHTS);
if (!normalEle || !posEle) {
return;
}
let indices = [];
let vbData = [];
let lineLength = 100;
Vec3.set(v3_tmp[0], 5, 0, 0);
Mat4.invert(mat4_tmp, comp.node._worldMatrix);
Vec3.transformMat4Normal(v3_tmp[0], v3_tmp[0], mat4_tmp);
lineLength = v3_tmp[0].mag();
let mesh = comp.mesh;
let posData = mesh._getAttrMeshData(subIndex, gfx.ATTR_POSITION);
let normalData = mesh._getAttrMeshData(subIndex, gfx.ATTR_NORMAL);
let jointData = mesh._getAttrMeshData(subIndex, gfx.ATTR_JOINTS);
let weightData = mesh._getAttrMeshData(subIndex, gfx.ATTR_WEIGHTS);
let vertexCount = posData.length / posEle.num;
for (let i = 0; i < vertexCount; i++) {
let normalIndex = i * normalEle.num;
let posIndex = i * posEle.num;
Vec3.set(v3_tmp[0], normalData[normalIndex], normalData[normalIndex+1], normalData[normalIndex+2]);
Vec3.set(v3_tmp[1], posData[posIndex], posData[posIndex+1], posData[posIndex+2]);
Vec3.scaleAndAdd(v3_tmp[0], v3_tmp[1], v3_tmp[0], lineLength);
for (let lineIndex = 0; lineIndex < 2; lineIndex++) {
vbData.push(v3_tmp[lineIndex].x, v3_tmp[lineIndex].y, v3_tmp[lineIndex].z);
if (jointEle) {
let jointIndex = i * jointEle.num;
for (let j = 0; j < jointEle.num; j++) {
vbData.push(jointData[jointIndex + j]);
}
}
if (weightEle) {
let weightIndex = i * weightEle.num;
for (let j = 0; j < weightEle.num; j++) {
vbData.push(weightData[weightIndex + j]);
}
}
}
indices.push(i*2, i*2+1);
}
let formatOpts = [
{ name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 3 },
];
if (jointEle) {
formatOpts.push({ name: gfx.ATTR_JOINTS, type: gfx.ATTR_TYPE_FLOAT32, num: jointEle.num })
}
if (weightEle) {
formatOpts.push({ name: gfx.ATTR_WEIGHTS, type: gfx.ATTR_TYPE_FLOAT32, num: weightEle.num })
}
let gfxVFmt = new gfx.VertexFormat(formatOpts);
let vb = new gfx.VertexBuffer(
Renderer.device,
gfxVFmt,
gfx.USAGE_STATIC,
new Float32Array(vbData)
);
let ibData = new Uint16Array(indices);
let ib = new gfx.IndexBuffer(
Renderer.device,
gfx.INDEX_FMT_UINT16,
gfx.USAGE_STATIC,
ibData,
ibData.length
);
let m = MaterialVariant.createWithBuiltin('unlit');
m.setProperty('diffuseColor', RED_COLOR);
return {
material: m,
ia: new InputAssembler(vb, ib, gfx.PT_LINES)
};
},
wireFrame (comp, ia, subData) {
let oldIbData = subData.getIData(Uint16Array);
let m = MaterialVariant.createWithBuiltin('unlit');
m.setProperty('diffuseColor', BLACK_COLOR);
let indices = [];
for (let i = 0; i < oldIbData.length; i+=3) {
let a = oldIbData[ i + 0 ];
let b = oldIbData[ i + 1 ];
let c = oldIbData[ i + 2 ];
indices.push(a, b, b, c, c, a);
}
let ibData = new Uint16Array(indices);
let ib = new gfx.IndexBuffer(
Renderer.device,
gfx.INDEX_FMT_UINT16,
gfx.USAGE_STATIC,
ibData,
ibData.length
);
return {
material: m,
ia: new InputAssembler(ia._vertexBuffer, ib, gfx.PT_LINES)
};
}
};
let _proto = MeshRenderer.prototype;
_proto._updateDebugDatas = function () {
let debugDatas = this._debugDatas;
let subMeshes = this._mesh.subMeshes;
let subDatas = this._mesh._subDatas;
for (let name in debugDatas) {
let debugData = debugDatas[name];
if (debugData.length === subMeshes.length) continue;
if (!cc.macro['SHOW_MESH_' + name.toUpperCase()]) continue;
debugData.length = subMeshes.length;
for (let i = 0; i < subMeshes.length; i++) {
debugData[i] = createDebugDataFns[name](this, subMeshes[i], subDatas[i], i);
}
}
};
}
cc.MeshRenderer = module.exports = MeshRenderer;

View File

@@ -0,0 +1,5 @@
require('./CCMesh');
if (!CC_EDITOR || !Editor.isMainProcess) {
require('./CCMeshRenderer');
require('./mesh-renderer');
}

View File

@@ -0,0 +1,179 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import gfx from '../../renderer/gfx';
/**
* The class BufferRange denotes a range of the buffer.
* @class BufferRange
*/
export let BufferRange = cc.Class({
name: 'cc.BufferRange',
properties: {
/**
* The offset of the range.
* @property {Number} offset
*/
offset: 0,
/**
* The length of the range.
* @property {Number} length
*/
length: 0
}
});
/**
* @class VertexFormat
*/
export let VertexFormat = cc.Class({
name: 'cc.mesh.VertexFormat',
properties: {
name: '',
type: -1,
num: -1,
normalize: false
}
});
/**
* A vertex bundle describes a serials of vertex attributes.
* These vertex attributes occupy a range of the buffer and
* are interleaved, no padding bytes, in the range.
*/
export let VertexBundle = cc.Class({
name: 'cc.mesh.VertexBundle',
properties: {
/**
* The data range of this bundle.
* This range of data is essentially mapped to a GPU vertex buffer.
* @property {BufferRange} data
*/
data: {
default: null,
type: BufferRange
},
/**
* The attribute formats.
* @property {VertexFormat} formats
*/
formats: {
default: [],
type: VertexFormat
},
/**
* The bundle's vertices count.
*/
verticesCount: 0,
}
});
/**
* A primitive is a geometry constituted with a list of
* same topology primitive graphic(such as points, lines or triangles).
*/
export let Primitive = cc.Class({
name: 'cc.mesh.Primitive',
properties: {
/**
* The vertex bundle that the primitive use.
* @property {[Number]} vertexBundleIndices
*/
vertexBundleIndices: {
default: [],
type: cc.Float
},
/**
* The data range of the primitive.
* This range of data is essentially mapped to a GPU indices buffer.
* @property {BufferRange} data
*/
data: {
default: null,
type: BufferRange
},
/**
* The type of this primitive's indices.
* @property {Number} indexUnit
*/
indexUnit: gfx.INDEX_FMT_UINT16,
/**
* The primitive's topology.
* @property {Number} topology
*/
topology: gfx.PT_TRIANGLES
}
});
export function MeshData () {
this.vData = null; // Uint8Array;
this.float32VData = null;
this.uint32VData = null;
this.iData = null; // Uint8Array;
this.uint16IData = null;
this.vfm = null;
this.offset = 0;
this.vb = null;
this.ib = null;
this.vDirty = false;
this.iDirty = false;
this.enable = true;
}
MeshData.prototype.setVData = function (data) {
this.vData = data;
this.float32VData = null;
this.uint32VData = null;
}
MeshData.prototype.getVData = function (format) {
if (format === Float32Array) {
if (!this.float32VData) {
this.float32VData = new Float32Array(this.vData.buffer, this.vData.byteOffset, this.vData.byteLength / 4);
}
return this.float32VData;
}
else if (format === Uint32Array) {
if (!this.uint32VData) {
this.uint32VData = new Uint32Array(this.vData.buffer, this.vData.byteOffset, this.vData.byteLength / 4);
}
return this.uint32VData;
}
return this.vData;
}
MeshData.prototype.getIData = function (format) {
if (format === Uint16Array) {
if (!this.uint16IData) {
this.uint16IData = new Uint16Array(this.iData.buffer, this.iData.byteOffset, this.iData.byteLength / 2);
}
return this.uint16IData;
}
return this.iData;
}

View File

@@ -0,0 +1,181 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import Assembler from '../renderer/assembler';
import gfx from '../../renderer/gfx';
import Vec3 from '../value-types/vec3';
const MeshRenderer = require('./CCMeshRenderer');
let _tmp_vec3 = new Vec3();
export default class MeshRendererAssembler extends Assembler {
init (renderComp) {
super.init(renderComp);
this._worldDatas = {};
this._renderNode = null;
}
setRenderNode (node) {
this._renderNode = node;
}
fillBuffers (comp, renderer) {
if (!comp.mesh) return;
comp.mesh._uploadData();
// update culling mask
let isCullingMaskSame = renderer.cullingMask === comp.node._cullingMask;
let enableAutoBatch = comp.enableAutoBatch;
let materials = comp._materials;
let submeshes = comp.mesh._subMeshes;
let subDatas = comp.mesh.subDatas;
for (let i = 0; i < submeshes.length; i++) {
let ia = submeshes[i];
let meshData = subDatas[i];
let material = materials[i] || materials[0];
if (!enableAutoBatch || !meshData.canBatch || ia._primitiveType !== gfx.PT_TRIANGLES) {
renderer._flush();
renderer.material = material;
renderer.cullingMask = comp.node._cullingMask;
renderer.node = this._renderNode;
renderer._flushIA(ia);
continue;
}
if (!isCullingMaskSame ||
material.getHash() !== renderer.material.getHash()) {
renderer._flush();
}
renderer.material = material;
renderer.cullingMask = comp.node._cullingMask;
renderer.node = renderer._dummyNode;
this._fillBuffer(comp, meshData, renderer, i);
}
if (CC_DEBUG &&
(cc.macro.SHOW_MESH_WIREFRAME || cc.macro.SHOW_MESH_NORMAL) &&
!(comp.node._cullingMask & (1<<cc.Node.BuiltinGroupIndex.DEBUG))) {
renderer._flush();
renderer.node = this._renderNode;
comp._updateDebugDatas();
if (cc.macro.SHOW_MESH_WIREFRAME) {
this._drawDebugDatas(comp, renderer, 'wireFrame');
}
if (cc.macro.SHOW_MESH_NORMAL) {
this._drawDebugDatas(comp, renderer, 'normal');
}
}
}
_fillBuffer (comp, meshData, renderer, dataIndex) {
let vData = meshData.getVData(Float32Array);
let vtxFormat = meshData.vfm;
let vertexCount = (vData.byteLength / vtxFormat._bytes) | 0;
let indices = meshData.getIData(Uint16Array);
let indicesCount = indices.length;
let buffer = renderer.getBuffer('mesh', vtxFormat);
let offsetInfo = buffer.request(vertexCount, indicesCount);
// buffer data may be realloc, need get reference after request.
let indiceOffset = offsetInfo.indiceOffset,
vertexOffset = offsetInfo.byteOffset >> 2,
vertexId = offsetInfo.vertexOffset,
vbuf = buffer._vData,
ibuf = buffer._iData;
if (renderer.worldMatDirty || !this._worldDatas[dataIndex]) {
this._updateWorldVertices(dataIndex, vertexCount, vData, vtxFormat, comp.node._worldMatrix);
}
vbuf.set(this._worldDatas[dataIndex], vertexOffset);
for (let i = 0; i < indicesCount; i++) {
ibuf[indiceOffset + i] = vertexId + indices[i];
}
}
_updateWorldVertices (dataIndex, vertexCount, local, vtxFormat, wolrdMatrix) {
let world = this._worldDatas[dataIndex];
if (!world) {
world = this._worldDatas[dataIndex] = new Float32Array(local.length);
world.set(local);
}
let floatCount = vtxFormat._bytes / 4;
let elements = vtxFormat._elements;
for (let i = 0, n = elements.length; i < n; i++) {
let element = elements[i];
let attrOffset = element.offset / 4;
if (element.name === gfx.ATTR_POSITION || element.name === gfx.ATTR_NORMAL) {
let transformMat4 = element.name === gfx.ATTR_NORMAL ? Vec3.transformMat4Normal : Vec3.transformMat4;
for (let j = 0; j < vertexCount; j++) {
let offset = j * floatCount + attrOffset;
_tmp_vec3.x = local[offset];
_tmp_vec3.y = local[offset + 1];
_tmp_vec3.z = local[offset + 2];
transformMat4(_tmp_vec3, _tmp_vec3, wolrdMatrix);
world[offset] = _tmp_vec3.x;
world[offset + 1] = _tmp_vec3.y;
world[offset + 2] = _tmp_vec3.z;
}
}
}
}
_drawDebugDatas (comp, renderer, name) {
let debugDatas = comp._debugDatas[name];
if (!debugDatas) return;
for (let i = 0; i < debugDatas.length; i++) {
let debugData = debugDatas[i];
if (!debugData) continue;
let material = debugData.material;
renderer.material = material;
renderer._flushIA(debugData.ia);
}
}
}
Assembler.register(MeshRenderer, MeshRendererAssembler);