Add WebGL book headbands and bounce lighting
This commit is contained in:
@@ -68,6 +68,12 @@ function createBookContext(options) {
|
||||
envMapIntensity: 0.08,
|
||||
side: THREE.DoubleSide
|
||||
}),
|
||||
headband: options.materials?.headband ?? new THREE.MeshStandardMaterial({
|
||||
color: 0xf4dcc0,
|
||||
roughness: 0.82,
|
||||
metalness: 0,
|
||||
envMapIntensity: 0.06
|
||||
}),
|
||||
pageTop: options.materials?.pageTop ?? new THREE.MeshStandardMaterial({
|
||||
color: 0xf1dfba,
|
||||
roughness: 0.82,
|
||||
@@ -324,26 +330,53 @@ function addClothSpine(group, context, model) {
|
||||
mesh.userData.bookPart = 'spine';
|
||||
configurePartMaterial(context, mesh.material, 'spine');
|
||||
group.add(mesh);
|
||||
|
||||
createHeadbandMeshes(context, model).forEach((headband) => group.add(headband));
|
||||
}
|
||||
|
||||
function createHeadbandMeshes(context, model) {
|
||||
const radius = 0.0046;
|
||||
const centerOffset = radius * 0.62;
|
||||
const spineProfile = [];
|
||||
for (let i = 2; i <= 30; i += 1) {
|
||||
const point = spineCurvePoint(i / 32, model.spineWidth);
|
||||
spineProfile.push(new THREE.Vector3(point.x, point.y + 0.0012, 0));
|
||||
}
|
||||
const meshes = [];
|
||||
[-1, 1].forEach((zSide) => {
|
||||
const z = zSide * (model.pageDepth * 0.5 + centerOffset);
|
||||
const curve = new THREE.CatmullRomCurve3(spineProfile.map((point) => point.clone().setZ(z)));
|
||||
const geometry = new THREE.TubeGeometry(curve, 56, radius, 10, false);
|
||||
const mesh = new THREE.Mesh(geometry, context.materials.headband);
|
||||
mesh.userData.bookPart = 'headband';
|
||||
configurePartMaterial(context, mesh.material, 'headband');
|
||||
meshes.push(mesh);
|
||||
});
|
||||
return meshes;
|
||||
}
|
||||
|
||||
function createClothSpineGeometry(depth, spineWidth) {
|
||||
const endOverrun = 0.0012;
|
||||
const profile = [];
|
||||
for (let i = 0; i <= 32; i += 1) {
|
||||
profile.push(spineCurvePoint(i / 32, spineWidth));
|
||||
}
|
||||
const positions = [];
|
||||
const uvs = [];
|
||||
const indices = [];
|
||||
const front = [];
|
||||
const back = [];
|
||||
const push = (point, z) => {
|
||||
const push = (point, z, uv) => {
|
||||
const index = positions.length / 3;
|
||||
positions.push(point.x, point.y, z);
|
||||
uvs.push(uv.u, uv.v);
|
||||
return index;
|
||||
};
|
||||
|
||||
profile.forEach((point) => {
|
||||
front.push(push(point, depth * 0.5 + 0.024));
|
||||
back.push(push(point, -depth * 0.5 - 0.024));
|
||||
profile.forEach((point, index) => {
|
||||
const u = profile.length <= 1 ? 0.5 : index / (profile.length - 1);
|
||||
front.push(push(point, depth * 0.5 + endOverrun, { u, v: 1 }));
|
||||
back.push(push(point, -depth * 0.5 - endOverrun, { u, v: 0 }));
|
||||
});
|
||||
for (let i = 0; i < profile.length - 1; i += 1) {
|
||||
indices.push(front[i], back[i], front[i + 1]);
|
||||
@@ -353,6 +386,7 @@ function createClothSpineGeometry(depth, spineWidth) {
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setIndex(indices);
|
||||
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
||||
geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));
|
||||
geometry.computeVertexNormals();
|
||||
return geometry;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user