quasi functional push : needs branching all different elements + repairing light position adaptation to camera position

This commit is contained in:
Neyl
2025-06-23 14:08:57 +02:00
parent f3c47c3ed2
commit 789357a9a6
10 changed files with 139 additions and 14 deletions

View File

@@ -20,25 +20,31 @@ namespace gdjs {
light: THREE.DirectionalLight;
rotationObject: THREE.Group;
_isEnabled: boolean = false;
_isCastingShadow: boolean = true;
top: string = 'Y-';
elevation: float = 45;
rotation: float = 0;
shadowSize: float = 1024;
shadowSize: float = 1024; //1024 == medium quality
constructor() {
this.light = new THREE.DirectionalLight();
this.light.castShadow = true;
this.light.castShadow = this._isCastingShadow;
this.light.shadow.mapSize.width = this.shadowSize;
this.light.shadow.mapSize.height = this.shadowSize;
this.light.shadow.camera.near = 3;
this.light.shadow.camera.near = 1;
this.light.shadow.camera.far = 10000;
this.light.shadow.camera.right = 1000;
this.light.shadow.camera.left = -1000;
this.light.shadow.camera.top = 1000;
this.light.shadow.camera.bottom = -1000;
this.light.position.set(1, 0, 0);
this.light.shadow.camera.right = 500;
this.light.shadow.camera.left = -500;
this.light.shadow.camera.top = 500;
this.light.shadow.camera.bottom = -500;
this.light.position.set(0, 10, 0);
this.light.target.position.set(0,100,0);
this.rotationObject = new THREE.Group();
this.rotationObject.position.set(0,0,0);
this.rotationObject.rotation.set(0,0,0);
this.rotationObject.add(this.light);
const shadowCameraHelper = new THREE.CameraHelper(this.light.shadow.camera);
this.rotationObject.add(shadowCameraHelper);
this.light.shadow.camera.updateProjectionMatrix();
this.updateRotation();
}
@@ -65,6 +71,7 @@ namespace gdjs {
return false;
}
scene.add(this.rotationObject);
scene.add(this.light.target);
this._isEnabled = true;
return true;
}
@@ -77,10 +84,28 @@ namespace gdjs {
return false;
}
scene.remove(this.rotationObject);
scene.remove(this.light.target);
this._isEnabled = false;
return true;
}
updatePreRender(target: gdjs.EffectsTarget): any {}
updatePreRender(target: gdjs.EffectsTarget): any {
const layer = target.getRuntimeLayer();
const x = layer.getCameraX();
const y = layer.getCameraY();
const z = layer.getCameraZ(layer.getInitialCamera3DFieldOfView());
this.rotationObject.position.set( //This is probably wrong : our axis management require to add an abstraction layer here I think
x,
z + 100,
-y
);
this.light.target.position.set(
-layer.getCameraY(),
layer.getCameraZ(layer.getInitialCamera3DFieldOfView()),
-layer.getCameraX()
);
}
updateDoubleParameter(parameterName: string, value: number): void {
if (parameterName === 'intensity') {
this.light.intensity = value;

View File

@@ -855,7 +855,9 @@ module.exports = {
propertyName === 'rightFaceResourceRepeat' ||
propertyName === 'topFaceResourceRepeat' ||
propertyName === 'bottomFaceResourceRepeat' ||
propertyName === 'enableTextureTransparency'
propertyName === 'enableTextureTransparency' ||
propertyName === 'isCastingShadow' ||
propertyName === 'isReceivingShadow'
) {
objectContent[propertyName] = newValue === '1';
return true;
@@ -1085,6 +1087,20 @@ module.exports = {
.addExtraInfo('StandardWithoutMetalness')
.setLabel(_('Material type'));
objectProperties
.getOrCreate('isCastingShadow')
.setValue(objectContent.isCastingShadow)
.setType('boolean')
.setLabel(_('Shadow casting'))
.setGroup(_('Shadows'));
objectProperties
.getOrCreate('isReceivingShadow')
.setValue(objectContent.isReceivingShadow)
.setType('boolean')
.setLabel(_('Shadow receiving'))
.setGroup(_('Shadows'));
return objectProperties;
};
Cube3DObject.content = {
@@ -1114,6 +1130,8 @@ module.exports = {
bottomFaceResourceRepeat: false,
materialType: 'Basic',
tint: '255;255;255',
castShadow: true,
receiveShadow: true,
};
Cube3DObject.updateInitialInstanceProperty = function (
@@ -1909,6 +1927,19 @@ module.exports = {
.setLabel(_('Rotation (in degrees)'))
.setType('number')
.setGroup(_('Orientation'));
properties.getOrCreate('castShadow')
.setValue('true')
.setLabel(_('Casting shadows'))
.setType('boolean')
.setGroup(_('Shadows'));
properties.getOrCreate('shadowQuality')
.setValue("Medium")
.addExtraInfo("Low")
.addExtraInfo("Medium")
.addExtraInfo("High")
.setLabel(_("Shadow quality"))
.setType('choice')
.setGroup(_("Shadows"))
}
{
const effect = extension
@@ -2375,6 +2406,8 @@ module.exports = {
_backFaceUpThroughWhichAxisRotation = 'X';
_shouldUseTransparentTexture = false;
_tint = '';
_castShadow = true;
_receiveShadow = true;
constructor(
project,
@@ -3206,6 +3239,8 @@ module.exports = {
this._threeObject = new THREE.Group();
this._threeObject.rotation.order = 'ZYX';
this._threeObject.castShadow = true;
this._threeObject.receiveShadow = true;
this._threeGroup.add(this._threeObject);
}

View File

@@ -23,7 +23,7 @@ Model3DObjectConfiguration::Model3DObjectConfiguration()
: width(100), height(100), depth(100), rotationX(0), rotationY(0),
rotationZ(0), modelResourceName(""), materialType("StandardWithoutMetalness"),
originLocation("ModelOrigin"), centerLocation("ModelOrigin"),
keepAspectRatio(true), crossfadeDuration(0.1f) {}
keepAspectRatio(true), crossfadeDuration(0.1f), isCastingShadow(true), isReceivingShadow(true) {}
bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
const gd::String &newValue) {
@@ -75,6 +75,16 @@ bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
crossfadeDuration = newValue.To<double>();
return true;
}
if(propertyName == "isCastingShadow")
{
isCastingShadow = newValue.To<bool>();
return true;
}
if(propertyName == "isReceivingShadow")
{
isReceivingShadow = newValue.To<bool>();
return true;
}
return false;
}
@@ -178,6 +188,20 @@ Model3DObjectConfiguration::GetProperties() const {
.SetGroup(_("Animations"))
.SetMeasurementUnit(gd::MeasurementUnit::GetSecond());
objectProperties["isCastingShadow"]
.SetValue(gd::String::From(isCastingShadow))
.SetType("boolean")
.SetLabel(_("Shadow Casting"))
.SetGroup(_("Shadows"));
objectProperties["isReceivingShadow"]
.SetValue(gd::String::From(isReceivingShadow))
.SetType("boolean")
.SetLabel(_("Shadow receiving"))
.SetGroup(_("Shadows"));
return objectProperties;
}
@@ -210,6 +234,8 @@ void Model3DObjectConfiguration::DoUnserializeFrom(
centerLocation = content.GetStringAttribute("centerLocation");
keepAspectRatio = content.GetBoolAttribute("keepAspectRatio");
crossfadeDuration = content.GetDoubleAttribute("crossfadeDuration");
isCastingShadow = content.GetBoolAttribute("isCastingShadow");
isReceivingShadow = content.GetBoolAttribute("isReceivingShadow");
RemoveAllAnimations();
auto &animationsElement = content.GetChild("animations");
@@ -239,6 +265,8 @@ void Model3DObjectConfiguration::DoSerializeTo(
content.SetAttribute("centerLocation", centerLocation);
content.SetAttribute("keepAspectRatio", keepAspectRatio);
content.SetAttribute("crossfadeDuration", crossfadeDuration);
content.SetAttribute("castShadow", isCastingShadow);
content.SetAttribute("receiveShadow", isReceivingShadow);
auto &animationsElement = content.AddChild("animations");
animationsElement.ConsiderAsArrayOf("animation");

View File

@@ -160,6 +160,8 @@ public:
const gd::String& GetCenterLocation() const { return centerLocation; };
bool shouldKeepAspectRatio() const { return keepAspectRatio; };
bool shouldCastShadow() const { return isCastingShadow; };
bool shouldReceiveShadow() const { return isReceivingShadow; };
///@}
protected:
@@ -182,6 +184,8 @@ private:
gd::String centerLocation;
bool keepAspectRatio;
bool isCastingShadow;
bool isReceivingShadow;
std::vector<Model3DAnimation> animations;
static Model3DAnimation badAnimation; //< Bad animation when an out of bound

View File

@@ -38,6 +38,8 @@ namespace gdjs {
| 'BottomCenterY';
animations: Model3DAnimation[];
crossfadeDuration: float;
castShadow: boolean;
receiveShadow: boolean;
};
}
@@ -101,6 +103,8 @@ namespace gdjs {
_animationSpeedScale: float = 1;
_animationPaused: boolean = false;
_crossfadeDuration: float = 0;
_castShadow: boolean = true;
_receiveShadow: boolean = true;
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
@@ -127,6 +131,9 @@ namespace gdjs {
this._crossfadeDuration = objectData.content.crossfadeDuration || 0;
this._castShadow = objectData.content.castShadow;
this._receiveShadow = objectData.content.receiveShadow;
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
}
@@ -358,6 +365,16 @@ namespace gdjs {
return this._renderer.hasAnimationEnded();
}
setCastShadow(value: boolean): void
{
this._castShadow = value;
}
setReceiveShadow(value: boolean) : void
{
this._receiveShadow = value;
}
setCrossfadeDuration(duration: number): void {
if (this._crossfadeDuration === duration) return;
this._crossfadeDuration = duration;

View File

@@ -265,8 +265,6 @@ namespace gdjs {
// This group hold the rotation defined by properties.
const threeObject = new THREE.Group();
threeObject.castShadow = true;
threeObject.receiveShadow = true;
threeObject.rotation.order = 'ZYX';
const root = THREE_ADDONS.SkeletonUtils.clone(this._originalModel.scene);
threeObject.add(root);
@@ -304,6 +302,8 @@ namespace gdjs {
* Replace materials to better work with lights (or no light).
*/
private _replaceMaterials(threeObject: THREE.Object3D) {
threeObject.castShadow = this._model3DRuntimeObject._castShadow;
threeObject.receiveShadow = this._model3DRuntimeObject._receiveShadow;
if (
this._model3DRuntimeObject._materialType ===
gdjs.Model3DRuntimeObject.MaterialType.StandardWithoutMetalness

View File

@@ -116,6 +116,9 @@ namespace gdjs {
}
}
getRuntimeLayer(): gdjs.RuntimeLayer {
return this;
}
getRenderer(): gdjs.LayerRenderer {
return this._renderer;
}

View File

@@ -17,6 +17,7 @@ namespace gdjs {
getName: () => string;
getRendererObject: () => RendererObjectInterface | null | undefined;
get3DRendererObject: () => THREE.Object3D | null | undefined;
getRuntimeLayer:() => gdjs.RuntimeLayer;
}
/**

View File

@@ -98,7 +98,7 @@ namespace gdjs {
preserveDrawingBuffer: true, // Keep to true to allow screenshots.
});
this._threeRenderer.shadowMap.enabled = true;
this._threeRenderer.shadowMap.type = THREE.PCFShadowMap;
this._threeRenderer.shadowMap.type = THREE.PCFSoftShadowMap;
this._threeRenderer.useLegacyLights = true;
this._threeRenderer.autoClear = false;
this._threeRenderer.setSize(

View File

@@ -674,6 +674,18 @@ const Model3DEditor = ({
propertyName="crossfadeDuration"
/>
</Column>
<Text size="block-title">Shadows</Text>
<Column noMargin expand>
<PropertyCheckbox
objectConfiguration={objectConfiguration}
propertyName="isCastingShadow"
/>
<PropertyCheckbox
objectConfiguration={objectConfiguration}
propertyName="isReceivingShadow"
/>
</Column>
<Column noMargin expand useFullHeight>
{model3DConfiguration.getAnimationsCount() === 0 ? (
<Column noMargin expand justifyContent="center">