# 实例化Mesh实体

 `InstancedMeshEntity` 是由 实体`Entity` 和 `InstancedMeshModule` 模块组合而成的新的实体。

 [InstancedMeshEntity](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html) =  [Entity](https://vjmap.com/map3d/api/classes/Entity.html) + [InstancedMeshModule](https://vjmap.com/map3d/api/classes/InstancedMeshModule.html) 

 ## 常用方法


 `InstancedMeshEntity` 是由 实体`Entity` 派生而来。具体 [Entity](https://vjmap.com/map3d/api/classes/Entity.html) 的所有属性和方法。同时也具有[InstancedMeshModule](https://vjmap.com/map3d/api/classes/InstancedMeshModule.html)  的相关方法。


|方法|描述|
|:---|:---|
|[addInstance](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#addInstance)|增加实例化对象，如存在则修改。⚠️ 只有显式传 `id: ""` 才自动生成 id（**省略 id** 会以字符串 `"undefined"` 作 id，第二次省略就变成"修改"上一个）；容量上限是构造时的 `maxCapacity`（取它与初始 `instances.length` 的较大者），**满了直接抛** `InstancedMesh maxCapacity is N`；`color` 必须是 `THREE.Color`（传字符串/数字会抛错）|
|[setInstance](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#setInstance)|根据id设置实例化对象属性，如不存在则走 `addInstance` 新增（同上：仅 `id: ""` 自动生成、超容量抛错、`color` 须为 `THREE.Color`，传 `color: null` 还原原色）|
|[removeInstance](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#removeInstance)|根据一个id删除实例化对象|
|[getInstancedMeshList](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#getInstancedMeshList)|获取实体化mesh列表|
|[getGroup](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#getGroup)|获取实体化的组对象|
|[getIdByIndex](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#getIdByIndex)|通过索引获取id|
|[getIndexById](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#getIndexById)|通过id获取索引|
|[setInstanceHighlight](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#setInstanceHighlight)|设置实例高亮与否|
|[isInstanceHighlight](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#isInstanceHighlight)|实例是否高亮|
|[clearInstanceHighlight](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#clearInstanceHighlight)|清除所有实例高亮|
|[setInstanceSelected](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#setInstanceSelected)|设置实例选择与否|
|[isInstanceSelected](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#isInstanceSelected)|实例是否选中|
|[clearInstanceSelected](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#clearInstanceSelected)|清除所有实例选中|
|[setInstanceBloom](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#setInstanceBloom)|设置实例辉光与否|
|[isInstanceBloom](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#isInstanceBloom)|实例是否辉光|
|[clearInstanceBloom](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#clearInstanceBloom)|清除所有实例辉光|
|[setInstanceOutline](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#setInstanceOutline)|设置实例描边与否|
|[isInstanceOutline](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#isInstanceOutline)|实例是否描边|
|[clearInstanceOutline](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#clearInstanceOutline)|清除所有实例描边|
|[setInstanceAttr](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#setInstanceAttr)|设置实例属性|
|[getInstanceAttr](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#getInstanceAttr)|获取实例属性|
|[getInstanceBox3](https://vjmap.com/map3d/api/classes/InstancedMeshEntity.html#getInstanceBox3)|获取实例的外包盒|

 
 

## 用法
```js

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    stat: {
        show: true,
        left: "0"
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
// 生成资源加载生成一个mesh
let mesh = await vjmap3d.ResManager.loadModel(env.assetsPath + "models/car.glb", {
    toEntity: false
});
// 根据这个mesh生成多个实例对象。这里模拟生成10000个
let instances = [];
for(let i = 0; i < 100; i++) {
    for(let j = 0; j < 100; j++) {
        instances.push({
            id: "inst" + (j * 100 + i), // 实例id，后续高亮/选中/属性接口都按id操作
            position: new THREE.Vector3(i - 50, 0, j - 50),
            rotation: new THREE.Vector3(0, Math.random() * Math.PI, 0),
            scale: Math.random() * 0.5 + 0.5,
            color: vjmap3d.randColor(),
            card: j * 100 + i
        })
    }
}
// 创建mesh实例化对象
let instanceMesh = new vjmap3d.InstancedMeshEntity({
    mesh: mesh,
    maxCapacity: 100 * 100,
    instances
})
instanceMesh.addTo(app)
//
// 设置实体能响应鼠标事件
instanceMesh.pointerEvents = true;
let instId; // 当前鼠标在的实例id（setInstanceHighlight/Selected 等接口均按id操作）
let popup;
const cancelSelect = () => {
    // 取消之前的选择
    if (instId !== undefined) {
        // 取消之前的高亮（不传颜色即恢复原色）
        instanceMesh.setInstanceHighlight(instId)
        //instanceMesh.setInstanceSelected(instId, false)  // 用选择的话，用这个，不用上面的
    }
    if (popup) {
        popup.remove();
        popup = null;
    }
}
instanceMesh.on("mouseover", e => {
    cancelSelect();
    if (e.intersection.object.isInstancedMesh) {
        // 通过射线拾取的数组索引获取实例id
        instId = instanceMesh.getIdByIndex(e.intersection.instanceId);
        // 设置高亮
        instanceMesh.setInstanceHighlight(instId, "#777");
        //instanceMesh.setInstanceSelected(instId, true); // 用选择的话，用这个，不用上面的
        let box3d = instanceMesh.getInstanceBox3(instId);
        if (!popup) {
        popup = new vjmap3d.Popup2D({
            backgroundColor: "#A0FFA0",
            closeButton: false
        })
        popup.addTo(app);
        }
        let position = vjmap3d.getObjectAnchorPoint(box3d, 'middle-top');
        popup.setPosition(position); // 设置位置 
        popup.setHTML(`第 ${instances[e.intersection.instanceId].card} 辆`);
    } 
})
instanceMesh.on("mouseout", e => {
    cancelSelect();
})
```

<mapFrame>
<pre>
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    stat: {
        show: true,
        left: "0"
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
// 生成资源加载生成一个mesh
let mesh = await vjmap3d.ResManager.loadModel(env.assetsPath + "models/car.glb", {
    toEntity: false
});
// 根据这个mesh生成多个实例对象。这里模拟生成10000个
let instances = [];
for(let i = 0; i < 100; i++) {
    for(let j = 0; j < 100; j++) {
        instances.push({
            id: "inst" + (j * 100 + i), // 实例id，后续高亮/选中/属性接口都按id操作
            position: new THREE.Vector3(i - 50, 0, j - 50),
            rotation: new THREE.Vector3(0, Math.random() * Math.PI, 0),
            scale: Math.random() * 0.5 + 0.5,
            color: vjmap3d.randColor(),
            card: j * 100 + i
        })
    }
}
// 创建mesh实例化对象
let instanceMesh = new vjmap3d.InstancedMeshEntity({
    mesh: mesh,
    maxCapacity: 100 * 100,
    instances
})
instanceMesh.addTo(app)
//
// 设置实体能响应鼠标事件
instanceMesh.pointerEvents = true;
let instId; // 当前鼠标在的实例id（setInstanceHighlight/Selected 等接口均按id操作）
let popup;
const cancelSelect = () => {
    // 取消之前的选择
    if (instId !== undefined) {
        // 取消之前的高亮（不传颜色即恢复原色）
        instanceMesh.setInstanceHighlight(instId)
        //instanceMesh.setInstanceSelected(instId, false)  // 用选择的话，用这个，不用上面的
    }
    if (popup) {
        popup.remove();
        popup = null;
    }
}
instanceMesh.on("mouseover", e => {
    cancelSelect();
    if (e.intersection.object.isInstancedMesh) {
        // 通过射线拾取的数组索引获取实例id
        instId = instanceMesh.getIdByIndex(e.intersection.instanceId);
        // 设置高亮
        instanceMesh.setInstanceHighlight(instId, "#777");
        //instanceMesh.setInstanceSelected(instId, true); // 用选择的话，用这个，不用上面的
        let box3d = instanceMesh.getInstanceBox3(instId);
        if (!popup) {
        popup = new vjmap3d.Popup2D({
            backgroundColor: "#A0FFA0",
            closeButton: false
        })
        popup.addTo(app);
        }
        let position = vjmap3d.getObjectAnchorPoint(box3d, 'middle-top');
        popup.setPosition(position); // 设置位置 
        popup.setHTML(`第 ${instances[e.intersection.instanceId].card} 辆`);
    } 
})
instanceMesh.on("mouseout", e => {
    cancelSelect();
})
</pre>
</mapFrame>