Merge multiple meshes to one.
Note that these meshes must have the same material

@param {Array.<clay.Mesh>} meshes
@param {boolean} applyWorldTransform
@return {clay.Mesh}
@memberOf clay.util.mesh
545143
function (meshes, applyWorldTransform) {

        if (! meshes.length) {
            return;
        }

        var templateMesh = meshes[0];
        var templateGeo = templateMesh.geometry;
        var material = templateMesh.material;

        var geometry = new Geometry({
            dynamic: false
        });
        geometry.boundingBox = new BoundingBox();

        var attributeNames = templateGeo.getEnabledAttributes();

        for (var i = 0; i < attributeNames.length; i++) {
            var name = attributeNames[i];
            var attr = templateGeo.attributes[name];
            // Extend custom attributes
            if (!geometry.attributes[name]) {
                geometry.attributes[name] = attr.clone(false);
            }
        }

        var inverseTransposeMatrix = mat4.create();
        // Initialize the array data and merge bounding box
        var nVertex = 0;
        var nFace = 0;
        for (var k = 0; k < meshes.length; k++) {
            var currentGeo = meshes[k].geometry;
            if (currentGeo.boundingBox) {
                currentGeo.boundingBox.applyTransform(applyWorldTransform ? meshes[k].worldTransform : meshes[k].localTransform);
                geometry.boundingBox.union(currentGeo.boundingBox);
            }
            nVertex += currentGeo.vertexCount;
            nFace += currentGeo.triangleCount;
        }
        for (var n = 0; n < attributeNames.length; n++) {
            var name = attributeNames[n];
            var attrib = geometry.attributes[name];
            attrib.init(nVertex);
        }
        if (nVertex >= 0xffff) {
            geometry.indices = new Uint32Array(nFace * 3);
        }
        else {
            geometry.indices = new Uint16Array(nFace * 3);
        }

        var vertexOffset = 0;
        var indicesOffset = 0;
        var useIndices = templateGeo.isUseIndices();

        for (var mm = 0; mm < meshes.length; mm++) {
            var mesh = meshes[mm];
            var currentGeo = mesh.geometry;

            var nVertex = currentGeo.vertexCount;

            var matrix = applyWorldTransform ? mesh.worldTransform.array : mesh.localTransform.array;
            mat4.invert(inverseTransposeMatrix, matrix);
            mat4.transpose(inverseTransposeMatrix, inverseTransposeMatrix);

            for (var nn = 0; nn < attributeNames.length; nn++) {
                var name = attributeNames[nn];
                var currentAttr = currentGeo.attributes[name];
                var targetAttr = geometry.attributes[name];
                // Skip the unused attributes;
                if (!currentAttr.value.length) {
                    continue;
                }
                var len = currentAttr.value.length;
                var size = currentAttr.size;
                var offset = vertexOffset * size;
                var count = len / size;
                for (var i = 0; i < len; i++) {
                    targetAttr.value[offset + i] = currentAttr.value[i];
                }
                // Transform position, normal and tangent
                if (name === 'position') {
                    vec3.forEach(targetAttr.value, size, offset, count, vec3.transformMat4, matrix);
                }
                else if (name === 'normal' || name === 'tangent') {
                    vec3.forEach(targetAttr.value, size, offset, count, vec3.transformMat4, inverseTransposeMatrix);
                }
            }

            if (useIndices) {
                var len = currentGeo.indices.length;
                for (var i = 0; i < len; i++) {
                    geometry.indices[i + indicesOffset] = currentGeo.indices[i] + vertexOffset;
                }
                indicesOffset += len;
            }

            vertexOffset += nVertex;
        }

        return new Mesh({
            material: material,
            geometry: geometry
        });
    }
1134625
private static boolean supportsTransform3d() {
    if (transform == null) {
      return false;
    }
    String rotate = "rotateY(1deg)";
    divStyle.setProperty(transform, rotate);
    rotate = divStyle.getProperty(transform);
    return rotate != null && !rotate.isEmpty();
  }
702324
public static PolyMesh buildPolyMesh(Context ctx, ContourSet cset, int nvp) {
        ctx.startTimer("BUILD_POLYMESH");
        PolyMesh mesh = new PolyMesh();
        RecastVectors.copy(mesh.bmin, cset.bmin, 0);
        RecastVectors.copy(mesh.bmax, cset.bmax, 0);
        mesh.cs = cset.cs;
        mesh.ch = cset.ch;
        mesh.borderSize = cset.borderSize;
        mesh.maxEdgeError = cset.maxError;

        int maxVertices = 0;
        int maxTris = 0;
        int maxVertsPerCont = 0;
        for (int i = 0; i < cset.conts.size(); ++i) {
            // Skip null contours.
            if (cset.conts.get(i).nverts < 3)
                continue;
            maxVertices += cset.conts.get(i).nverts;
            maxTris += cset.conts.get(i).nverts - 2;
            maxVertsPerCont = Math.max(maxVertsPerCont, cset.conts.get(i).nverts);
        }
        if (maxVertices >= 0xfffe) {
            throw new RuntimeException("rcBuildPolyMesh: Too many vertices " + maxVertices);
        }
        int[] vflags = new int[maxVertices];

        mesh.verts = new int[maxVertices * 3];
        mesh.polys = new int[maxTris * nvp * 2];
        Arrays.fill(mesh.polys, RC_MESH_NULL_IDX);
        mesh.regs = new int[maxTris];
        mesh.areas = new int[maxTris];

        mesh.nverts = 0;
        mesh.npolys = 0;
        mesh.nvp = nvp;
        mesh.maxpolys = maxTris;

        int[] nextVert = new int[maxVertices];

        int[] firstVert = new int[VERTEX_BUCKET_COUNT];
        for (int i = 0; i < VERTEX_BUCKET_COUNT; ++i)
            firstVert[i] = -1;

        int[] indices = new int[maxVertsPerCont];
        int[] tris = new int[maxVertsPerCont * 3];
        int[] polys = new int[(maxVertsPerCont + 1) * nvp];

        int tmpPoly = maxVertsPerCont * nvp;

        for (int i = 0; i < cset.conts.size(); ++i) {
            Contour cont = cset.conts.get(i);

            // Skip null contours.
            if (cont.nverts < 3)
                continue;

            // Triangulate contour
            for (int j = 0; j < cont.nverts; ++j)
                indices[j] = j;
            int ntris = triangulate(cont.nverts, cont.verts, indices, tris);
            if (ntris <= 0) {
                // Bad triangulation, should not happen.
                ctx.warn("buildPolyMesh: Bad triangulation Contour " + i + ".");
                ntris = -ntris;
            }

            // Add and merge vertices.
            for (int j = 0; j < cont.nverts; ++j) {
                int v = j * 4;
                int[] inv = addVertex(cont.verts[v + 0], cont.verts[v + 1], cont.verts[v + 2], mesh.verts, firstVert,
                        nextVert, mesh.nverts);
                indices[j] = inv[0];
                mesh.nverts = inv[1];
                if ((cont.verts[v + 3] & RC_BORDER_VERTEX) != 0) {
                    // This vertex should be removed.
                    vflags[indices[j]] = 1;
                }
            }

            // Build initial polygons.
            int npolys = 0;
            Arrays.fill(polys, RC_MESH_NULL_IDX);
            for (int j = 0; j < ntris; ++j) {
                int t = j * 3;
                if (tris[t + 0] != tris[t + 1] && tris[t + 0] != tris[t + 2] && tris[t + 1] != tris[t + 2]) {
                    polys[npolys * nvp + 0] = indices[tris[t + 0]];
                    polys[npolys * nvp + 1] = indices[tris[t + 1]];
                    polys[npolys * nvp + 2] = indices[tris[t + 2]];
                    npolys++;
                }
            }
            if (npolys == 0)
                continue;

            // Merge polygons.
            if (nvp > 3) {
                for (;;) {
                    // Find best polygons to merge.
                    int bestMergeVal = 0;
                    int bestPa = 0, bestPb = 0, bestEa = 0, bestEb = 0;

                    for (int j = 0; j < npolys - 1; ++j) {
                        int pj = j * nvp;
                        for (int k = j + 1; k < npolys; ++k) {
                            int pk = k * nvp;
                            int[] veaeb = getPolyMergeValue(polys, pj, pk, mesh.verts, nvp);
                            int v = veaeb[0];
                            int ea = veaeb[1];
                            int eb = veaeb[2];
                            if (v > bestMergeVal) {
                                bestMergeVal = v;
                                bestPa = j;
                                bestPb = k;
                                bestEa = ea;
                                bestEb = eb;
                            }
                        }
                    }

                    if (bestMergeVal > 0) {
                        // Found best, merge.
                        int pa = bestPa * nvp;
                        int pb = bestPb * nvp;
                        mergePolyVerts(polys, pa, pb, bestEa, bestEb, tmpPoly, nvp);
                        int lastPoly = (npolys - 1) * nvp;
                        if (pb != lastPoly) {
                            System.arraycopy(polys, lastPoly, polys, pb, nvp);
                        }
                        npolys--;
                    } else {
                        // Could not merge any polygons, stop.
                        break;
                    }
                }
            }

            // Store polygons.
            for (int j = 0; j < npolys; ++j) {
                int p = mesh.npolys * nvp * 2;
                int q = j * nvp;
                for (int k = 0; k < nvp; ++k)
                    mesh.polys[p + k] = polys[q + k];
                mesh.regs[mesh.npolys] = cont.reg;
                mesh.areas[mesh.npolys] = cont.area;
                mesh.npolys++;
                if (mesh.npolys > maxTris) {
                    throw new RuntimeException(
                            "rcBuildPolyMesh: Too many polygons " + mesh.npolys + " (max:" + maxTris + ").");
                }
            }
        }

        // Remove edge vertices.
        for (int i = 0; i < mesh.nverts; ++i) {
            if (vflags[i] != 0) {
                if (!canRemoveVertex(ctx, mesh, i))
                    continue;
                removeVertex(ctx, mesh, i, maxTris);
                // Remove vertex
                // Note: mesh.nverts is already decremented inside removeVertex()!
                // Fixup vertex flags
                for (int j = i; j < mesh.nverts; ++j)
                    vflags[j] = vflags[j + 1];
                --i;
            }
        }

        // Calculate adjacency.
        buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, nvp);

        // Find portal edges
        if (mesh.borderSize > 0) {
            int w = cset.width;
            int h = cset.height;
            for (int i = 0; i < mesh.npolys; ++i) {
                int p = i * 2 * nvp;
                for (int j = 0; j < nvp; ++j) {
                    if (mesh.polys[p + j] == RC_MESH_NULL_IDX)
                        break;
                    // Skip connected edges.
                    if (mesh.polys[p + nvp + j] != RC_MESH_NULL_IDX)
                        continue;
                    int nj = j + 1;
                    if (nj >= nvp || mesh.polys[p + nj] == RC_MESH_NULL_IDX)
                        nj = 0;
                    int va = mesh.polys[p + j] * 3;
                    int vb = mesh.polys[p + nj] * 3;

                    if (mesh.verts[va + 0] == 0 && mesh.verts[vb + 0] == 0)
                        mesh.polys[p + nvp + j] = 0x8000 | 0;
                    else if (mesh.verts[va + 2] == h && mesh.verts[vb + 2] == h)
                        mesh.polys[p + nvp + j] = 0x8000 | 1;
                    else if (mesh.verts[va + 0] == w && mesh.verts[vb + 0] == w)
                        mesh.polys[p + nvp + j] = 0x8000 | 2;
                    else if (mesh.verts[va + 2] == 0 && mesh.verts[vb + 2] == 0)
                        mesh.polys[p + nvp + j] = 0x8000 | 3;
                }
            }
        }

        // Just allocate the mesh flags array. The user is resposible to fill it.
        mesh.flags = new int[mesh.npolys];

        if (mesh.nverts > 0xffff) {
            throw new RuntimeException("rcBuildPolyMesh: The resulting mesh has too many vertices " + mesh.nverts
                    + " (max " + 0xffff + "). Data can be corrupted.");
        }
        if (mesh.npolys > 0xffff) {
            throw new RuntimeException("rcBuildPolyMesh: The resulting mesh has too many polygons " + mesh.npolys
                    + " (max " + 0xffff + "). Data can be corrupted.");
        }

        ctx.stopTimer("BUILD_POLYMESH");
        return mesh;

    }
811888
function mergeWithoutOverwrite(object1, object2) {
		if (object1 === object2) {
			return object1;
		}

		var oMergedObject = {};

		// Clone object1
		Object.keys(object1).forEach(function(sKey) {
			oMergedObject[sKey] = object1[sKey];
		});

		// merge
		Object.keys(object2).forEach(function(sKey) {
			if (!oMergedObject.hasOwnProperty(sKey)) {
				oMergedObject[sKey] = object2[sKey];
			}
		});

		return oMergedObject;
	}
1063385
function createVoxelMesh(gl, voxels, voxelSideTextureIDs, voxelSideTextureSizes, position, pad, that) {
  //Create mesh
  var vert_data = createAOMesh(voxels, voxelSideTextureIDs, voxelSideTextureSizes)
  var vertexArrayObjects = {}

  if (vert_data === null) {
    // no vertices allocated
  } else {
    //Upload triangle mesh to WebGL
    var vert_buf = createBuffer(gl, vert_data)
    var triangleVAO = createVAO(gl, [
      { "buffer": vert_buf,
        "type": gl.UNSIGNED_BYTE,
        "size": 4,
        "offset": 0,
        "stride": 8,
        "normalized": false
      },
      { "buffer": vert_buf,
        "type": gl.UNSIGNED_BYTE,
        "size": 4,
        "offset": 4,
        "stride": 8,
        "normalized": false
      }
    ])
    triangleVAO.length = Math.floor(vert_data.length/8)

    vertexArrayObjects.surface = triangleVAO
  }

  // move the chunk into place
  var modelMatrix = mat4.create()
  var w = voxels.shape[2] - pad  // =[1]=[0]=game.chunkSize
  var translateVector = [
    position[0] * w,
    position[1] * w,
    position[2] * w]

  mat4.translate(modelMatrix, modelMatrix, translateVector)

  //Bundle result and return
  var result = {
    vertexArrayObjects: vertexArrayObjects, // other plugins can add their own VAOs
    center: [w>>1, w>>1, w>>1],
    radius: w,
    modelMatrix: modelMatrix
  }

  if (that) that.emit('meshed', result, gl, vert_data, voxels)

  return result
}
172671
function mergeChildren(children) {
            var nameToItems = ts.createMap();
            ts.filterMutate(children, function (child) {
                var decl = child.node;
                var name = decl.name && nodeText(decl.name);
                if (!name) {
                    // Anonymous items are never merged.
                    return true;
                }
                var itemsWithSameName = nameToItems[name];
                if (!itemsWithSameName) {
                    nameToItems[name] = child;
                    return true;
                }
                if (itemsWithSameName instanceof Array) {
                    for (var _i = 0, itemsWithSameName_1 = itemsWithSameName; _i < itemsWithSameName_1.length; _i++) {
                        var itemWithSameName = itemsWithSameName_1[_i];
                        if (tryMerge(itemWithSameName, child)) {
                            return false;
                        }
                    }
                    itemsWithSameName.push(child);
                    return true;
                }
                else {
                    var itemWithSameName = itemsWithSameName;
                    if (tryMerge(itemWithSameName, child)) {
                        return false;
                    }
                    nameToItems[name] = [itemWithSameName, child];
                    return true;
                }
                function tryMerge(a, b) {
                    if (shouldReallyMerge(a.node, b.node)) {
                        merge(a, b);
                        return true;
                    }
                    return false;
                }
            });
            /** a and b have the same name, but they may not be mergeable. */
            function shouldReallyMerge(a, b) {
                return a.kind === b.kind && (a.kind !== 225 /* ModuleDeclaration */ || areSameModule(a, b));
                // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes.
                // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'!
                function areSameModule(a, b) {
                    if (a.body.kind !== b.body.kind) {
                        return false;
                    }
                    if (a.body.kind !== 225 /* ModuleDeclaration */) {
                        return true;
                    }
                    return areSameModule(a.body, b.body);
                }
            }
            /** Merge source into target. Source should be thrown away after this is called. */
            function merge(target, source) {
                target.additionalNodes = target.additionalNodes || [];
                target.additionalNodes.push(source.node);
                if (source.additionalNodes) {
                    (_a = target.additionalNodes).push.apply(_a, source.additionalNodes);
                }
                target.children = ts.concatenate(target.children, source.children);
                if (target.children) {
                    mergeChildren(target.children);
                    sortChildren(target.children);
                }
                var _a;
            }
        }
1231843
function() {
            if (this.polygons.length === 0) {
                var m = new CSG.Matrix4x4(); // unity
                return [m,m];
            } else {
                // get a list of unique planes in the CSG:
                var csg = this.canonicalized();
                var planemap = {};
                csg.polygons.map(function(polygon) {
                    planemap[polygon.plane.getTag()] = polygon.plane;
                });
                // try each plane in the CSG and find the plane that, when we align it flat onto z=0,
                // gives the least height in z-direction.
                // If two planes give the same height, pick the plane that originally had a normal closest
                // to [0,0,-1].
                var xvector = new CSG.Vector3D(1, 0, 0);
                var yvector = new CSG.Vector3D(0, 1, 0);
                var zvector = new CSG.Vector3D(0, 0, 1);
                var z0connectorx = new CSG.Connector([0, 0, 0], [0, 0, -1], xvector);
                var z0connectory = new CSG.Connector([0, 0, 0], [0, 0, -1], yvector);
                var isfirst = true;
                var minheight = 0;
                var maxdotz = 0;
                var besttransformation, bestinversetransformation;
                for (var planetag in planemap) {
                    var plane = planemap[planetag];
                    var pointonplane = plane.normal.times(plane.w);
                    var transformation, inversetransformation;
                    // We need a normal vecrtor for the transformation
                    // determine which is more perpendicular to the plane normal: x or y?
                    // we will align this as much as possible to the x or y axis vector
                    var xorthogonality = plane.normal.cross(xvector).length();
                    var yorthogonality = plane.normal.cross(yvector).length();
                    if (xorthogonality > yorthogonality) {
                        // x is better:
                        var planeconnector = new CSG.Connector(pointonplane, plane.normal, xvector);
                        transformation = planeconnector.getTransformationTo(z0connectorx, false, 0);
                        inversetransformation = z0connectorx.getTransformationTo(planeconnector, false, 0);
                    } else {
                        // y is better:
                        var planeconnector = new CSG.Connector(pointonplane, plane.normal, yvector);
                        transformation = planeconnector.getTransformationTo(z0connectory, false, 0);
                        inversetransformation = z0connectory.getTransformationTo(planeconnector, false, 0);
                    }
                    var transformedcsg = csg.transform(transformation);
                    var dotz = -plane.normal.dot(zvector);
                    var bounds = transformedcsg.getBounds();
                    var zheight = bounds[1].z - bounds[0].z;
                    var isbetter = isfirst;
                    if (!isbetter) {
                        if (zheight < minheight) {
                            isbetter = true;
                        } else if (zheight == minheight) {
                            if (dotz > maxdotz) isbetter = true;
                        }
                    }
                    if (isbetter) {
                        // translate the transformation around the z-axis and onto the z plane:
                        var translation = new CSG.Vector3D([-0.5 * (bounds[1].x + bounds[0].x), -0.5 * (bounds[1].y + bounds[0].y), -bounds[0].z]);
                        transformation = transformation.multiply(CSG.Matrix4x4.translation(translation));
                        inversetransformation = CSG.Matrix4x4.translation(translation.negated()).multiply(inversetransformation);
                        minheight = zheight;
                        maxdotz = dotz;
                        besttransformation = transformation;
                        bestinversetransformation = inversetransformation;
                    }
                    isfirst = false;
                }
                return [besttransformation, bestinversetransformation];
            }
        }
963220
public GeoShapeMapper transform(GeoTransformation... transformations) {
        if (this.transformations == null) {
            this.transformations = Arrays.asList(transformations);
        } else {
            this.transformations.addAll(Arrays.asList(transformations));
        }
        return this;
    }
638624
def parallel_apply_transformations(x, transforms, black_border_size=0):
  
  transforms = tf.convert_to_tensor(transforms, dtype=tf.float32)
  x = _apply_black_border(x, black_border_size)

  num_transforms = transforms.get_shape().as_list()[0]
  im_shape = x.get_shape().as_list()[1:]

  # Pass a copy of x and a transformation to each iteration of the map_fn
  # callable
  tiled_x = tf.reshape(
      tf.tile(x, [num_transforms, 1, 1, 1]),
      [num_transforms, -1] + im_shape)
  elems = [tiled_x, transforms]
  transformed_ims = tf.map_fn(
      _apply_transformation,
      elems,
      dtype=tf.float32,
      parallel_iterations=1,  # Must be 1 to avoid keras race conditions
  )
  return transformed_ims
1236161
function applyModelTransform (el, state) {
  if (el.directives) {
    for (var i = 0; i < el.directives.length; i++) {
      var dir = el.directives[i];
      if (dir.name === 'model') {
        state.directives.model(el, dir, state.warn);
        // remove value for textarea as its converted to text
        if (el.tag === 'textarea' && el.props) {
          el.props = el.props.filter(function (p) { return p.name !== 'value'; });
        }
        break
      }
    }
  }
}
478879
function addShape( shape ) {

		var i, l, shapeHole;

		var indexOffset = vertices.length / 3;
		var points = shape.extractPoints( curveSegments );

		var shapeVertices = points.shape;
		var shapeHoles = points.holes;

		// check direction of vertices

		if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {

			shapeVertices = shapeVertices.reverse();

		}

		for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {

			shapeHole = shapeHoles[ i ];

			if ( ShapeUtils.isClockWise( shapeHole ) === true ) {

				shapeHoles[ i ] = shapeHole.reverse();

			}

		}

		var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );

		// join vertices of inner and outer paths to a single array

		for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {

			shapeHole = shapeHoles[ i ];
			shapeVertices = shapeVertices.concat( shapeHole );

		}

		// vertices, normals, uvs

		for ( i = 0, l = shapeVertices.length; i < l; i ++ ) {

			var vertex = shapeVertices[ i ];

			vertices.push( vertex.x, vertex.y, 0 );
			normals.push( 0, 0, 1 );
			uvs.push( vertex.x, vertex.y ); // world uvs

		}

		// incides

		for ( i = 0, l = faces.length; i < l; i ++ ) {

			var face = faces[ i ];

			var a = face[ 0 ] + indexOffset;
			var b = face[ 1 ] + indexOffset;
			var c = face[ 2 ] + indexOffset;

			indices.push( a, b, c );
			groupCount += 3;

		}

	}
1010957
function appendTransform(defaults, transform) {
    defaults = angular.isArray(defaults) ? defaults : [defaults];
    return (transform) ? defaults.concat(transform) : defaults;
  }
201429
function mergeObjects(a, b) {
    var r = { };
    for (var k in a)
        r[k] = a[k];
    for (var k in b)
        r[k] = b[k];
    return r;
}
1296811
function ( relationships, deformerNodes ) {

			var rawBones = [];

			relationships.children.forEach( function ( child ) {

				var boneNode = deformerNodes[ child.ID ];

				if ( boneNode.attrType !== 'Cluster' ) return;

				var rawBone = {

					ID: child.ID,
					indices: [],
					weights: [],
					transform: new THREE.Matrix4().fromArray( boneNode.Transform.a ),
					transformLink: new THREE.Matrix4().fromArray( boneNode.TransformLink.a ),
					linkMode: boneNode.Mode,

				};

				if ( 'Indexes' in boneNode ) {

					rawBone.indices = boneNode.Indexes.a;
					rawBone.weights = boneNode.Weights.a;

				}

				rawBones.push( rawBone );

			} );

			return {

				rawBones: rawBones,
				bones: []

			};

		}
174219
function deepMerge(target, ...sources) {
	let src
	while (true) {
		if (!sources.length)
			return target
		src = sources.shift()
		if (src)
			break
	}

	for (let k in src) {

		let v = src[k]
		let existing = target[k]

		if (typeof v === 'object') {
			if (v === null) {
				target[k] = null
			} else if (Array.isArray(v)) {
				target[k] = v.slice()
			} else {
				if (typeof existing !== 'object')
					target[k] = deepMerge({}, v)
				else
					deepMerge(existing, v)
			}
		} else {
			//v is not object/array
			target[k] = v
		}
	}

	return deepMerge(target, ...sources)
}
1071368
function () {
    var dressing = new THREE.Object3D();
    this.dressing.setAttribute('visible', this.data.dressing != 'none');
    if (this.data.dressing == 'none') {
      return;
    }
    var geometry = new THREE.Geometry(); // mother geometry that will hold all instances

    // get array of geometries
    var geoset;
    switch (this.data.dressing){
      case 'cubes': {
        geoset = [new THREE.BoxGeometry(1, 1, 1)];
        geoset[0].applyMatrix(new THREE.Matrix4().makeTranslation(0, 0.5, 0));
        break;
      }
      case 'pyramids': {
        geoset = [new THREE.ConeGeometry(1, 1, 4, 1, true)];
        geoset[0].applyMatrix(new THREE.Matrix4().makeTranslation(0, 0.5, 0));
        break;
      }
      case 'cylinders': {
        geoset = [new THREE.CylinderGeometry(0.5, 0.5, 1, 8, 1, true)];
        geoset[0].applyMatrix(new THREE.Matrix4().makeTranslation(0, 0.5, 0));
        break;
      }
      default: {
        geoset = this.getAssetGeometry(this.assets[this.data.dressing]);
        if (!geoset) return;
        break;
      }
    }

    for (var i = 0, r = 88343; i < this.data.dressingAmount; i++, r++) {

      var geo = geoset[Math.floor(this.random(33 + i) * geoset.length)];
/*
      // change vertex colors
      var color = new THREE.Color(0xFFFFFF).multiplyScalar(1 - this.random(66 + i) * 0.3);

      for (var f = 0, fl = geo.faces.length; f < fl; f++) {
        var face = geo.faces[f];
        for (var v = 0; v < 3; v++) {
          p = geo.vertices[face[faceindex[v]]]; // get vertex position
          var floorao =  p.y / 4 + 0.75;
          face.vertexColors[v] = new THREE.Color(color.r * floorao, color.g * floorao, color.b * floorao);
        }
      }
*/
      // set random position, rotation and scale
      var ds = this.data.dressingScale;
      var dv = new THREE.Vector3(this.data.dressingVariance.x, this.data.dressingVariance.y, this.data.dressingVariance.z);
      var distance;
      var onPlayArea = this.random(r) < this.data.dressingOnPlayArea;
      if (onPlayArea) {
        distance = this.random(r + 1) * 15;
      }
      else {
        distance = 10 + Math.max(dv.x, dv.z) + 10 * this.random(r + 1) + this.random(r + 2) * this.STAGE_SIZE / 3;
      }

      var direction = this.random(r + 3) * Math.PI * 2;
      var matrix = new THREE.Matrix4();
      var scale = this.random(r + 4);
      var uniformScale = this.data.dressingUniformScale;

      matrix.compose(
        // position
        new THREE.Vector3(
          Math.cos(direction) * distance,
          0,
          Math.sin(direction) * distance
          ),
        // rotation
        new THREE.Quaternion().setFromAxisAngle(
          new THREE.Vector3(0, 1, 0),
          (this.random(r + 5) - 0.5) * dv.length() * Math.PI * 2
          ),
        // scale
        new THREE.Vector3(
           ds + (uniformScale ? scale : this.random(r + 6)) * dv.x,
           ds + (uniformScale ? scale : this.random(r + 7)) * dv.y,
           ds + (uniformScale ? scale : this.random(r + 8)) * dv.z
          )
        );

      // merge with mother geometry
      geometry.merge(geo, matrix);
    }

    // convert geometry to buffergeometry
    var bufgeo = new THREE.BufferGeometry();
    bufgeo.fromGeometry(geometry);

    // setup material
    var material = new THREE.MeshLambertMaterial({
      color: new THREE.Color(this.data.dressingColor),
      vertexColors: THREE.VertexColors
    });

    if (this.data.flatShading) {
      bufgeo.computeVertexNormals();
    }

    // create mesh
    var mesh = new THREE.Mesh(bufgeo, material);
    dressing.add(mesh);
    // add to scene
    this.dressing.setObject3D('mesh', dressing);
  }
1239949
public static PolyMesh mergePolyMeshes(Context ctx, PolyMesh[] meshes, int nmeshes) {

        if (nmeshes == 0 || meshes == null)
            return null;

        ctx.startTimer("MERGE_POLYMESH");
        PolyMesh mesh = new PolyMesh();
        mesh.nvp = meshes[0].nvp;
        mesh.cs = meshes[0].cs;
        mesh.ch = meshes[0].ch;
        RecastVectors.copy(mesh.bmin, meshes[0].bmin, 0);
        RecastVectors.copy(mesh.bmax, meshes[0].bmax, 0);

        int maxVerts = 0;
        int maxPolys = 0;
        int maxVertsPerMesh = 0;
        for (int i = 0; i < nmeshes; ++i) {
            RecastVectors.min(mesh.bmin, meshes[i].bmin, 0);
            RecastVectors.max(mesh.bmax, meshes[i].bmax, 0);
            maxVertsPerMesh = Math.max(maxVertsPerMesh, meshes[i].nverts);
            maxVerts += meshes[i].nverts;
            maxPolys += meshes[i].npolys;
        }

        mesh.nverts = 0;
        mesh.verts = new int[maxVerts * 3];

        mesh.npolys = 0;
        mesh.polys = new int[maxPolys * 2 * mesh.nvp];
        Arrays.fill(mesh.polys, 0, mesh.polys.length, RC_MESH_NULL_IDX);
        mesh.regs = new int[maxPolys];
        mesh.areas = new int[maxPolys];
        mesh.flags = new int[maxPolys];

        int[] nextVert = new int[maxVerts];

        int[] firstVert = new int[VERTEX_BUCKET_COUNT];
        for (int i = 0; i < VERTEX_BUCKET_COUNT; ++i)
            firstVert[i] = -1;

        int[] vremap = new int[maxVertsPerMesh];

        for (int i = 0; i < nmeshes; ++i) {
            PolyMesh pmesh = meshes[i];

            int ox = (int) Math.floor((pmesh.bmin[0] - mesh.bmin[0]) / mesh.cs + 0.5f);
            int oz = (int) Math.floor((pmesh.bmin[2] - mesh.bmin[2]) / mesh.cs + 0.5f);

            boolean isMinX = (ox == 0);
            boolean isMinZ = (oz == 0);
            boolean isMaxX = (Math.floor((mesh.bmax[0] - pmesh.bmax[0]) / mesh.cs + 0.5f)) == 0;
            boolean isMaxZ = (Math.floor((mesh.bmax[2] - pmesh.bmax[2]) / mesh.cs + 0.5f)) == 0;
            boolean isOnBorder = (isMinX || isMinZ || isMaxX || isMaxZ);

            for (int j = 0; j < pmesh.nverts; ++j) {
                int v = j * 3;
                int[] inv = addVertex(pmesh.verts[v + 0] + ox, pmesh.verts[v + 1], pmesh.verts[v + 2] + oz, mesh.verts,
                        firstVert, nextVert, mesh.nverts);

                vremap[j] = inv[0];
                mesh.nverts = inv[1];
            }

            for (int j = 0; j < pmesh.npolys; ++j) {
                int tgt = mesh.npolys * 2 * mesh.nvp;
                int src = j * 2 * mesh.nvp;
                mesh.regs[mesh.npolys] = pmesh.regs[j];
                mesh.areas[mesh.npolys] = pmesh.areas[j];
                mesh.flags[mesh.npolys] = pmesh.flags[j];
                mesh.npolys++;
                for (int k = 0; k < mesh.nvp; ++k) {
                    if (pmesh.polys[src + k] == RC_MESH_NULL_IDX)
                        break;
                    mesh.polys[tgt + k] = vremap[pmesh.polys[src + k]];
                }

                if (isOnBorder) {
                    for (int k = mesh.nvp; k < mesh.nvp * 2; ++k) {
                        if ((pmesh.polys[src + k] & 0x8000) != 0 && pmesh.polys[src + k] != 0xffff) {
                            int dir = pmesh.polys[src + k] & 0xf;
                            switch (dir) {
                            case 0: // Portal x-
                                if (isMinX)
                                    mesh.polys[tgt + k] = pmesh.polys[src + k];
                                break;
                            case 1: // Portal z+
                                if (isMaxZ)
                                    mesh.polys[tgt + k] = pmesh.polys[src + k];
                                break;
                            case 2: // Portal x+
                                if (isMaxX)
                                    mesh.polys[tgt + k] = pmesh.polys[src + k];
                                break;
                            case 3: // Portal z-
                                if (isMinZ)
                                    mesh.polys[tgt + k] = pmesh.polys[src + k];
                                break;
                            }
                        }
                    }
                }
            }
        }

        // Calculate adjacency.
        buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, mesh.nvp);
        if (mesh.nverts > 0xffff) {
            throw new RuntimeException("rcBuildPolyMesh: The resulting mesh has too many vertices " + mesh.nverts
                    + " (max " + 0xffff + "). Data can be corrupted.");
        }
        if (mesh.npolys > 0xffff) {
            throw new RuntimeException("rcBuildPolyMesh: The resulting mesh has too many polygons " + mesh.npolys
                    + " (max " + 0xffff + "). Data can be corrupted.");
        }

        ctx.stopTimer("MERGE_POLYMESH");

        return mesh;
    }