By checking the source code, it is found that uRotationCenter and vRotationCenter cannot be exported when they are not 0, view code:
if (babylonTexture.uAng !== 0 || babylonTexture.vAng !== 0) {
Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation in the u or v axis is not supported in glTF.`);
resolve(null);
} else if (babylonTexture.wAng !== 0 && (babylonTexture.uRotationCenter !== 0 || babylonTexture.vRotationCenter !== 0)) {
Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation not centered at the origin cannot be exported with ${NAME}`);
resolve(null);
} else {
resolve(babylonTexture);
}
For the default texture, both uRotationCenter and vRotationCenter are 0.5:
So this is where the cause lies, is it reasonable
When loading glb with KHR_texture_transform extension attribute, uRotationCenter and vRotationCenter will be set to 0, see:
So how to export wAng from KHR_texture_transform in glTFExporter
TL;DR: the KHR_texture_transform spec defines that rotations must be applied at the origin, but we should be able to calculate this ourselves by displacing the offset property using uRotationCenter and vRotationCenter.
I just tried using the latest version of the sandbox, adjusted wAngle and offset, and exported it. However, when I imported the exported model back into the sandbox, the results were inconsistent.
@alexchuber I too am experiencing issues with this (ive tried latest as well as the version we were using (^7.14.0). Infact, when I use latest, NONE of the scaling and rotation is being exported correctly so its even more broken. (we use uv scaling/offsets pretty much on every material).
with 7.14.0 I am essentially seeing the above discussed behavior and warning. Soooo any updates on this?
I see the comment in the PR:
/**
Computes the adjusted offset for a rotation centered about the origin.
This does not work when scaling is involved; investigation is needed.
@internal
*/
i’ll assume this is still being actively investigated? I’ll try to dig around and see if I can fix it but would appreciate your assistance.
Could you share a playground example of the issue?
Exporting texture rotation is tricky. We can’t export any rotation along the U or V axes, as there is no equivalent representation in the KHR_texture_transform spec. The schema only supports W rotation around the origin.
Up until recently, this meant that we would not export any W rotation if either of the U and V rotation centers were not at the origin. But, when I initially encountered this post, I had the idea of baking this transform to the origin in the U and V offsets-- which is where you found that comment-- so long as scaling was uninvolved. I couldn’t derive the right equation to account for scaling. I’m not sure if it is impossible, or if I just didn’t find it
While this is not being actively investigated, I’d be happy to support anyone looking to tackle the issue. You could also make a feature request.
In any case, the best way to approach exporting texture transforms would be to make sure that your materials U and V rotation centers are at 0. It’s regrettable that the Babylon default values for these are not 0, but I doubt it’d be worth the breaking change to update them.
Greetings, thanks for the quick response. I made a small modification to your code. Seems like its better ish but still does not match exactly. I guess for now we dont really need the pivot to match exactly on export as long as the UVs are rotated and scales are correct. The resulting asset for us has pretty close visual appearance. the below solution seems to work better but still not good enough for a PR Im going to try to undregister the babylonjs KHR_texture_transform and register our own on export. Hoping that will unblock us for now. Perhaps the below code will inspire some further ideas.
/**
* Computes the adjusted offset for a rotation centered about the origin.
* @internal
*/
function AdjustOffsetForRotationCenter(babylonTexture: Texture): [number, number] {
const { uOffset, vOffset, uRotationCenter, vRotationCenter, wAng, uScale, vScale } = babylonTexture;
const cosAngle = Math.cos(-wAng);
const sinAngle = Math.sin(-wAng);
// Apply scaling to rotation center coordinates
const scaledUCenter = uRotationCenter * uScale;
const scaledVCenter = vRotationCenter * vScale;
// Calculate offset adjustments with scaling
const deltaU = scaledUCenter * (1 - cosAngle) - scaledVCenter * sinAngle;
const deltaV = scaledVCenter * (1 - cosAngle) + scaledUCenter * sinAngle;
// Apply scaling to the final offset
return [
(uOffset + deltaU) * uScale,
(vOffset + deltaV) * vScale
];
}
then just need to change the part where we check wAng
if (babylonTexture.wAng !== 0) {
if (babylonTexture.uRotationCenter !== 0 || babylonTexture.vRotationCenter !== 0) {
Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation not centered at the origin will be exported with an adjusted texture offset for ${NAME}.`);
textureTransform.offset = AdjustOffsetForRotationCenter(babylonTexture);
}
textureTransform.rotation = -babylonTexture.wAng;
transformIsRequired = true;
}
I’ll try to get this shim working, if not I’ll post a PG example. But to repro: any asset that has wAng, scales are ignored on export.
The code you posted is on the right track That’s one of the methods I tried-- but, as you’ve already pointed out, the visual result was not exact. If we want to support scaling with wAng at a non-origin, I think we’d either want to get it 100% right or not support it at all. Otherwise, it might lead to more confusion.
As far as the repro goes… that is odd. If I recall correctly, in the past, assets with non-origin rotation center + wAng + scale would have exported with just their scale only, no rotation at all not exported KHR_texture_transform at all. That should be the same behavior today.
I agree with you, cant really make any updates at the core API without getting it 100% right. Hence my attempt to override the extension behavior with our own code. I’ll keep you posted. At the very least it might be useful for people to see how to customize the exporter for their own needs/usecase.
@alexchuber instead of moving this thread off topic I decided to just post a new topic on how to create a custom extension handeler on export. Unfortunately I dont seem to have access to the GLTFExport api to register/unregister my own extensions on export. see: How to register/unregister custom extensions when using GLTF2Exporter
Sounds good, we will talk more there about registering extensions.
Could you confirm, though, that behavior hasn’t regressed in the latest version? When I try to repro by exporting with a non-zero origin + wAng + scale, in both versions, I get a warning and the KHR_texture_transform extension is (intentionally and correctly) not exported at all.
It seems it has regressed at least from my tests. I’ll post a repro here from latest version vs the BJS version we were using (^7.14.0) sometime today.