If you download the source to the toolbar from GitHub it contains a runtime decimator.
This is the scripts 1 version (the GitHub code is Scripts 2.0 and ES6/babel/webpack):
pc.script.attribute('enabled', 'boolean', true)
pc.script.attribute('deleteOriginal', 'boolean', true)
pc.script.attribute('collision', 'boolean', false)
pc.script.create('meshcombiner', function (app) {
var MeshCombiner = function MeshCombiner(entity) {
this.entity = entity
//this.enabled = this.enabled;
}
var validTypes = {
"POSITION": true,
"NORMAL": true,
"TANGENT": true,
"TEXCOORD0": true
}
window.nextId = window.nextId || 1
var fixer
var id = 0
MeshCombiner.prototype = {
postInitialize: function () {
var self = this
if (!this.enabled && this.entity.enabled) {
return
}
this.entity.setPosition(0,0,0)
this.entity.setEulerAngles(0,0,0)
console.log("COMBINING", this.entity.name)
this.enabled = false
var meshes = []
pc.utils.ofType(this.entity, 'marker').forEach(function (m) {
m.entity.removeComponent('model')
})
pc.utils.ofType(this.entity, 'model')
.forEach(function (model) {
if (model.model && model.enabled && model.entity._enabled) {
model.model.meshInstances.forEach(function (mesh) {
meshes.push({
mesh: mesh,
material: mesh.material,
model: model
})
})
}
})
var byMaterial = _.filter(_.groupBy(meshes, function (mesh) {
return mesh.material.name
}), function (g) {
return g.length > 0
})
var replace = new pc.Entity(app)
// replace.syncHierarchy = makeEasy(replace);
replace.name = "Replace"
replace.enabled = true
var transform = new pc.Mat4()
var worldToLocal = new pc.Mat4()
worldToLocal.copy(this.entity.getWorldTransform())
worldToLocal.invert()
var models = []
_.forEachRight(byMaterial, function (list) {
var material = list[0].material
var combined = new pc.Entity()
replace.addChild(combined)
combined.addComponent('model')
combined.name = material.name + " Holder"
combined.enabled = true
combined.model.castShadows = true
combined.model.receiveShadows = true
//combined.model.type = 'box'
var pos = []
var uv = []
var normal = []
var indices = []
var tangents = []
var p = 0
var ind = 0
//Now loop through and transform everything
list.forEach(function (m) {
//First get the world transform of the item
transform.copy(m.mesh.node.getWorldTransform())
transform.mul(worldToLocal)
var vb = m.mesh.mesh.vertexBuffer
var ib = m.mesh.mesh.indexBuffer[pc.RENDERSTYLE_SOLID]
var iblocked = ib.lock()
var indexes = new Uint16Array(iblocked)
var locked = vb.lock()
var format = vb.getFormat()
var base = m.mesh.mesh.primitive[0].base
var stride = format.size / 4
var data = {}
for (j = 0; j < format.elements.length; j++) {
var element = format.elements[j]
if (validTypes[element.name]) {
data[element.name] = new Float32Array(locked, element.offset)
}
}
var positions = data["POSITION"]
var vec = new pc.Vec3()
var t = p
//Make room for the new ones
for (var i = 0; i < Math.floor(positions.length / stride); i++) {
pos.push(0)
pos.push(0)
pos.push(0)
uv.push(0)
uv.push(0)
tangents.push(0)
tangents.push(0)
tangents.push(0)
normal.push(0)
normal.push(0)
normal.push(0)
}
var tv
for (i = 0; i < positions.length; i += stride) {
vec.set(positions[i], positions[i + 1], positions[i + 2])
tv = transform.transformPoint(vec)
pos[t] = tv.x
pos[t + 1] = tv.y
pos[t + 2] = tv.z
t += 3
}
var normals = data["NORMAL"]
t = p
if (normals) {
for (i = 0; i < normals.length; i += stride) {
vec.set(normals[i], normals[i + 1], normals[i + 2])
vec = transform.transformVector(vec)
normal[t] = vec.x
normal[t + 1] = vec.y
normal[t + 2] = vec.z
t += 3
}
}
var uvs = data["TEXCOORD0"]
t = p / 3 * 2
if (uvs) {
for (i = 0; i < uvs.length; i += stride, t += 2) {
uv[t] = uvs[i]
uv[t + 1] = uvs[i + 1]
}
}
var numIndices = m.mesh.mesh.primitive[0].count
for (i = 0; i < numIndices; i++) {
indices.push(indexes[i + base] + p / 3)
}
p += (positions.length / stride) * 3
//Turn off the existing object
models.push(m.model.entity)
vb.unlock()
ib.unlock()
})
var mesh = pc.scene.procedural.createMesh(app.graphicsDevice, pos, {
normals: normal,
uvs: uv,
indices: indices,
tangents: pc.calculateTangents(pos, normal, uv, indices)
})
console.log(material.name, "triangles", indices.length/3, "vertices", pos.length/3, "models", list.length)
var root = new pc.scene.GraphNode()
var instance = new pc.scene.MeshInstance(root, mesh, material)
instance._aabb = mesh.aabb
var model = new pc.scene.Model()
model.graph = root
model.meshInstances = [instance]
var asset = new pc.Asset('Combined Mesh', 'model')
asset.loaded = true
asset.resource = model
app.assets.add(asset)
combined.model.data.asset = asset
combined.model.data.type = 'asset'
combined.model.model = model
if (self.collision) {
combined.addComponent('collision',
{
type: 'mesh',
model: model
})
combined.collision.model = model
}
var id = nextId++
combined.enabled = true
})
replace.enabled = true
this.entity.addChild(replace)
models.forEach(function(m) {
if(self.deleteOriginal) {
m.destroy()
} else {
if(m.model)
m.removeComponent('model')
delete m.model
}
})
// setTimeout(function () {
// self.entity.destroy();
// });
// }.bind(this));
}
}
return MeshCombiner
})
This requires lodash on _ - oh crap it also needs my pc.utils.ofType (but that could easily be rewritten). The GitHub version uses import
for all of this stuff