思路: 根据指定半径的圆形 和需要物体存在的角度 计算点在圆上的坐标
/**
* 根据一个模型生成一个围绕一圈的组合
*/
export const modelSurround = (model: Object3D, radius: number, count: number) => {
const group = new THREE.Group();
const onceAngle = (Math.PI * 2) / 360; //一度
const spaceAngle = (360 / count) * onceAngle; //两个物体中间的夹角度数
for (let i = 1; i <= count; i++) {
const item = model.clone();
const x = Math.sin(spaceAngle * i) * radius;
const y = Math.cos(spaceAngle * i) * radius;
item.position.set(x, y, 0);
group.add(item);
}
return group;
};
调用
const model = new THREE.Mesh(
new THREE.BoxGeometry(3, 3, 3),
new THREE.MeshPhongMaterial({
color: 0xa88afa,
flatShading: true,
side: THREE.DoubleSide,
})
);
const roundModel = modelSurround(model, 10, 10);
scene.add(roundModel);
/**
* 根据一个模型生成一个围绕一圈的组合
*/
export const modelSurround = (model: Object3D, radius: number, count: number, column: number = 1) => {
const group = new THREE.Group();
const onceAngle = (Math.PI * 2) / 360; //一度
const spaceAngle = (360 / count) * onceAngle; //两个物体中间的夹角度数
for (let l = 0; l < column; l++) {
const columnGroup = new THREE.Group();
for (let i = 0; i < count; i++) {
const item = model.clone();
const x = Math.sin(spaceAngle * i) * radius;
const y = Math.cos(spaceAngle * i) * radius;
item.position.set(x, y, 0);
columnGroup.add(item);
}
columnGroup.rotation.y = (180 / column) * onceAngle * l;
group.add(columnGroup);
}
return group;
};
调用
const model = new THREE.Mesh(
new THREE.BoxGeometry(3, 3, 3),
new THREE.MeshPhongMaterial({
color: 0xa88afa,
flatShading: true,
side: THREE.DoubleSide,
})
);
const roundModel = modelSurround(model, 10, 20, 8);
roundModel.position.y = 70;
scene.add(roundModel);
/**
* 根据一个模型生成一个围绕一圈的组合
*/
export const modelSurround = ({
model,
radius,
count,
radian = 360,
column = 1,
}: {
/**
* 模型
*/
model: Object3D;
/**
* 半径
*/
radius: number;
/**
* 重复数量
*/
count: number;
/**
* 排列弧度默认360度(一周)
* @default 360
*/
radian?: number;
/**
* 绕y轴旋转几列360列即为球形 默认1列
* @default 1
*/
column?: number;
}) => {
const group = new THREE.Group();
const onceAngle = (Math.PI * 2) / 360; //一度
const spaceAngle = (radian / count) * onceAngle; //两个物体中间的夹角度数
for (let l = 0; l < column; l++) {
const columnGroup = new THREE.Group();
for (let i = 0; i < count; i++) {
const item = model.clone();
const x = Math.sin(spaceAngle * i) * radius;
const y = Math.cos(spaceAngle * i) * radius;
item.position.set(x, y, 0);
columnGroup.add(item);
}
columnGroup.rotation.y = (180 / column) * onceAngle * l;
group.add(columnGroup);
}
return group;
};
调用
const model = new THREE.Mesh(
new THREE.BoxGeometry(3, 3, 3),
new THREE.MeshPhongMaterial({
color: 0xa88afa,
flatShading: true,
side: THREE.DoubleSide,
})
);
const roundModel = modelSurround({ model, radius: 10, count: 10, radian: 90, column: 1 });
roundModel.position.y = 70;
scene.add(roundModel);
/**
* 根据一个模型生成一个围绕一圈的组合
*/
export const modelSurround = ({
model,
radius,
count,
radian = 360,
column = 1,
syncRotation = false,
}: {
/**
* 模型 或者一个返回模型的函数
*/
model: Object3D | (() => Object3D);
/**
* 半径
*/
radius: number;
/**
* 重复数量
*/
count: number;
/**
* 排列弧度默认360度(一周)
* @default 360
*/
radian?: number;
/**
* 绕y轴旋转几列360列即为球形 默认1列
* @default 1
*/
column?: number;
/**
* 旋转角度同步旋转
* @default false
*/
syncRotation?: boolean;
}) => {
const group = new THREE.Group();
const onceAngle = (Math.PI * 2) / 360; //一度
const spaceAngle = (radian / count) * onceAngle; //两个物体中间的夹角度数
for (let l = 0; l < column; l++) {
const columnGroup = new THREE.Group();
for (let i = 0; i < count; i++) {
const item = typeof model === "function" ? model().clone() : model.clone();
const x = Math.sin(spaceAngle * i) * radius;
const y = Math.cos(spaceAngle * i) * radius;
item.position.set(x, y, 0);
columnGroup.add(item);
syncRotation && (item.rotation.z = spaceAngle * -i);
}
columnGroup.rotation.y = (360 / column) * onceAngle * l;
group.add(columnGroup);
}
return group;
};
调用 传入一个随机生成的模型
/**
* 获得三块砖的模型
*/
const one = gltf.scene.getObjectByName("1");
const two = gltf.scene.getObjectByName("2");
const three = gltf.scene.getObjectByName("3");
if (!one || !two || !three) return;
const provider = [one, two, three];
const { length: count } = provider;
const space = getSize(one).z + 1;
const blocksGroup = modelSurround({
model: () => {
const row = new Group();
for (let i = 0; i < count; i++) {
//随机获取得一个模型
const model = provider[Math.floor(Math.random() * count)].clone();
row.add(model);
//这样 0,1,2 是 0 3,4,5 是 1 有序排列保持坐标一致
const column = Math.floor(i / count);
const x = column * space;
const y = 0;
const z = (i % count) * space;
model.position.set(x, y, z);
}
return row;
},
count: 30,
radius: 460 * 4,
radian: 6,
syncRotation: true,
column: 4,
});