Skip to content

Commit

Permalink
set scale with manifest
Browse files Browse the repository at this point in the history
  • Loading branch information
memelotsqui committed Oct 24, 2023
1 parent 929c549 commit 2126689
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 29 deletions.
5 changes: 3 additions & 2 deletions src/components/ExportMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const ExportMenu = ({getFaceScreenshot}) => {
// Translate hook
const { t } = useContext(LanguageContext);
const [name] = React.useState(localStorage.getItem("name") || defaultName)
const { model, avatar } = useContext(SceneContext)
const { model, avatar,templateInfo } = useContext(SceneContext)

return (
<React.Fragment>
Expand Down Expand Up @@ -46,7 +46,8 @@ export const ExportMenu = ({getFaceScreenshot}) => {
className={styles.button}
onClick={() => {
const screenshot = getFaceScreenshot();
downloadVRM(model, avatar, name, screenshot, 4096, true)
console.log(templateInfo.exportScale)
downloadVRM(model, avatar, name, screenshot, 4096,templateInfo.exportScale||1, true)
}}
/>
</React.Fragment>
Expand Down
25 changes: 13 additions & 12 deletions src/library/download-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,52 +61,53 @@ function getUnopotimizedGLB (avatarToDownload){

return unoptimizedGLB;
}
function getOptimizedGLB(avatarToDownload, atlasSize, isVrm0 = false){
function getOptimizedGLB(avatarToDownload, atlasSize, scale = 1, isVrm0 = false){
const avatarToDownloadClone = cloneAvatarModel(avatarToDownload)
return combine({
transparentColor: new Color(1,1,1),
avatar: avatarToDownloadClone,
atlasSize,
scale
}, isVrm0)
}

export async function getGLBBlobData(avatarToDownload, atlasSize = 4096, optimized = true){
export async function getGLBBlobData(avatarToDownload, atlasSize = 4096, optimized = true, scale = 1){
const model = await (optimized ?
getOptimizedGLB(avatarToDownload, atlasSize) :
getOptimizedGLB(avatarToDownload, atlasSize,scale) :
getUnopotimizedGLB(avatarToDownload))
const glb = await parseGLB(model);
return new Blob([glb], { type: 'model/gltf-binary' });
}

export async function getVRMBlobData(avatarToDownload, avatar, screenshot = null, atlasSize = 4096, isVrm0 = false){
const model = await getOptimizedGLB(avatarToDownload, atlasSize, isVrm0)
export async function getVRMBlobData(avatarToDownload, avatar, screenshot = null, atlasSize = 4096, scale = 1, isVrm0 = false){
const model = await getOptimizedGLB(avatarToDownload, atlasSize,scale, isVrm0)
const vrm = await parseVRM(model, avatar, screenshot, isVrm0);
// save it as glb now
return new Blob([vrm], { type: 'model/gltf-binary' });
}

// returns a promise with the parsed data
async function getGLBData(avatarToDownload, atlasSize = 4096, optimized = true){
async function getGLBData(avatarToDownload, atlasSize = 4096, optimized = true, scale = 1){
if (optimized){
const model = await getOptimizedGLB(avatarToDownload, atlasSize)
const model = await getOptimizedGLB(avatarToDownload, atlasSize,scale)
return parseGLB(model);
}
else{
const model = getUnopotimizedGLB(avatarToDownload)
return parseGLB(model);
}
}
async function getVRMData(avatarToDownload, avatar, screenshot = null, atlasSize = 4096, isVrm0 = false){
async function getVRMData(avatarToDownload, avatar, screenshot = null, atlasSize = 4096, scale = 1, isVrm0 = false){

const vrmModel = await getOptimizedGLB(avatarToDownload, atlasSize, isVrm0);
const vrmModel = await getOptimizedGLB(avatarToDownload, atlasSize, scale, isVrm0);
return parseVRM(vrmModel,avatar,screenshot, isVrm0)
}

export async function downloadVRM(avatarToDownload, avatar, fileName = "", screenshot = null, atlasSize = 4096, isVrm0 = false){
export async function downloadVRM(avatarToDownload, avatar, fileName = "", screenshot = null, atlasSize = 4096, scale = 1, isVrm0 = false){
const downloadFileName = `${
fileName && fileName !== "" ? fileName : "AvatarCreatorModel"
}`
getVRMData(avatarToDownload, avatar, screenshot, atlasSize, isVrm0).then((vrm)=>{
getVRMData(avatarToDownload, avatar, screenshot, atlasSize,scale, isVrm0).then((vrm)=>{
saveArrayBuffer(vrm, `${downloadFileName}.vrm`)
})
}
Expand All @@ -116,7 +117,7 @@ export async function downloadGLB(avatarToDownload, optimized = true, fileName
}`

const model = optimized ?
await getOptimizedGLB(avatarToDownload, atlasSize):
await getOptimizedGLB(avatarToDownload, atlasSize, scale):
getUnopotimizedGLB(avatarToDownload)

parseGLB(model)
Expand Down
27 changes: 14 additions & 13 deletions src/library/merge-geometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function cloneSkeleton(skinnedMesh) {
return newSkeleton;
}

function createMergedSkeleton(meshes){
function createMergedSkeleton(meshes, scale){
/* user should be careful with naming convetions in custom bone names out from humanoids vrm definition,
for example ones that come from head (to add hair movement), should start with vrm's connected bone
followed by the number of the bone in reference to the base bone (head > head_hair_00 > head_hair_01),
Expand Down Expand Up @@ -98,7 +98,7 @@ function createMergedSkeleton(meshes){
newSkeleton.pose();

newSkeleton.bones.forEach(bn => {
bn.position.set(bn.position.x *0.7, bn.position.y*0.7,bn.position.z*0.7);
bn.position.set(bn.position.x *scale, bn.position.y*scale,bn.position.z*scale);
});
return newSkeleton
}
Expand Down Expand Up @@ -168,14 +168,14 @@ function removeUnusedAttributes(attribute,arrayMatch){
return new BufferAttribute(typedArr,attribute.itemSize,attribute.normalized)
}

export async function combine({ transparentColor, avatar, atlasSize = 4096 }, isVrm0 = false) {
export async function combine({ transparentColor, avatar, atlasSize = 4096, scale = 1 }, isVrm0 = false) {
const { bakeObjects, textures, vrmMaterial } =
await createTextureAtlas({ transparentColor, atlasSize, meshes: findChildrenByType(avatar, "SkinnedMesh")});
// if (vrmMaterial != null)
// vrmMaterial.userData.textureProperties = {_MainTex:0, _ShadeTexture:0
const meshes = bakeObjects.map((bakeObject) => bakeObject.mesh);

const newSkeleton = createMergedSkeleton(meshes);
const newSkeleton = createMergedSkeleton(meshes, scale);

meshes.forEach((mesh) => {
const geometry = mesh.geometry;
Expand Down Expand Up @@ -221,7 +221,7 @@ export async function combine({ transparentColor, avatar, atlasSize = 4096 }, is
}
});

const { dest } = mergeGeometry({ meshes },isVrm0);
const { dest } = mergeGeometry({ meshes, scale },isVrm0);
const geometry = new THREE.BufferGeometry();

if (isVrm0){
Expand All @@ -238,9 +238,9 @@ export async function combine({ transparentColor, avatar, atlasSize = 4096 }, is

const vertices = geometry.attributes.position.array;
for (let i = 0; i < vertices.length; i += 3) {
vertices[i] *= 0.7;
vertices[i + 1] *= 0.7;
vertices[i + 2] *= 0.7;
vertices[i] *= scale;
vertices[i + 1] *= scale;
vertices[i + 2] *= scale;
}

const material = new THREE.MeshStandardMaterial({
Expand Down Expand Up @@ -337,7 +337,7 @@ function mergeSourceMorphTargetDictionaries({ sourceMorphTargetDictionaries }) {
});
return destMorphTargetDictionary;
}
function mergeSourceMorphAttributes({ meshes, sourceMorphTargetDictionaries, sourceMorphAttributes, destMorphTargetDictionary, }, isVrm0 = false) {
function mergeSourceMorphAttributes({ meshes, sourceMorphTargetDictionaries, sourceMorphAttributes, destMorphTargetDictionary, scale}, isVrm0 = false) {
const propertyNameSet = new Set(); // e.g. ["position", "normal"]
const allSourceMorphAttributes = Array.from(sourceMorphAttributes.values());
allSourceMorphAttributes.forEach((sourceMorphAttributes) => {
Expand Down Expand Up @@ -380,9 +380,9 @@ function mergeSourceMorphAttributes({ meshes, sourceMorphTargetDictionaries, sou
}
}
for (let j = 0; j < buffArr.length; j+=3){
buffArr[j] *= 0.7;
buffArr[j+1] *= 0.7;
buffArr[j+2] *= 0.7;
buffArr[j] *= scale;
buffArr[j+1] *= scale;
buffArr[j+2] *= scale;
}
}
});
Expand Down Expand Up @@ -573,7 +573,7 @@ function mergeSourceIndices({ meshes }) {
// function remapAnimationClips({ animationClips, sourceMorphTargetDictionaries, meshes, destMorphTargetDictionary }) {
// return animationClips.map((clip) => new THREE.AnimationClip(clip.name, clip.duration, clip.tracks.map((track) => remapKeyframeTrack({ track, sourceMorphTargetDictionaries, meshes, destMorphTargetDictionary })), clip.blendMode));
// }
export function mergeGeometry({ meshes }, isVrm0 = false) {
export function mergeGeometry({ meshes, scale }, isVrm0 = false) {
// eslint-disable-next-line no-unused-vars
let uvcount = 0;
meshes.forEach(mesh => {
Expand Down Expand Up @@ -605,6 +605,7 @@ export function mergeGeometry({ meshes }, isVrm0 = false) {
sourceMorphAttributes: source.morphAttributes,
sourceMorphTargetDictionaries: source.morphTargetDictionaries,
destMorphTargetDictionary,
scale,
},isVrm0);
dest.morphTargetInfluences = mergeMorphTargetInfluences({
meshes,
Expand Down
4 changes: 2 additions & 2 deletions src/library/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const cullHiddenMeshes = (avatar) => {
CullHiddenFaces(models)
}

export async function getModelFromScene(avatarScene, format = 'glb', skinColor = new THREE.Color(1, 1, 1)) {
export async function getModelFromScene(avatarScene, format = 'glb', skinColor = new THREE.Color(1, 1, 1), scale = 1) {
if (format && format === 'glb') {
const exporter = new GLTFExporter();
const options = {
Expand All @@ -91,7 +91,7 @@ export async function getModelFromScene(avatarScene, format = 'glb', skinColor =
maxTextureSize: 1024 || Infinity
};

const avatar = await combine({ transparentColor: skinColor, avatar: avatarScene });
const avatar = await combine({ transparentColor: skinColor, avatar: avatarScene, scale:scale });

const glb = await new Promise((resolve) => exporter.parse(avatar, resolve, (error) => console.error("Error getting model", error), options));
return new Blob([glb], { type: 'model/gltf-binary' });
Expand Down

0 comments on commit 2126689

Please sign in to comment.