THREE.Object3D.add: object not an instance of THREE.Object3D

I am trying to create a shadow map using location-based Sun API. I found a script that does it from GitHub. It works very well however it was written according to the threejs 78th version. But I had some issues with this issues like importing gltf models so I wanted to switch new version. I created a script that shows the shadows based on directionalLight and it looks like this;

So now I want to include this script;

I put both the old version of threejs to make it run in my script. It also looks like this;

	<script src ='./lib/three.js'></script>
	<script src ='SunLight.js'></script>
	<script type="importmap">
		{
			"imports": {
				"three": "../build/three.module.js",
				"three/addons/": "./jsm/"
			}
		}
	</script>
	
	<script type="module">

		import * as THREE from 'three';
		import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
		import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
		//import { ShadowMapViewer } from 'three/addons/utils/ShadowMapViewer.js';
							
		var scene, root, renderer, camera, controls, mesh;
		//var dirLightShadowMapViewer, spotLightShadowMapViewer;
		init();
		createScene();
		animate();

                   ...
	
			
			var loader = new GLTFLoader;
			loader.load('./models/gltf/building_3.gltf', function(gltf) {
				gltf.scene.rotation.x = - Math.PI/2;
				mesh = gltf.scene.children[0];
				mesh.material = new THREE.MeshBasicMaterial({
					color: 0x160830
				});
				mesh.castShadow = true;
				mesh.receiveShadow = true;
				root.add(gltf.scene);
				render();
			})

			// Add an ambient light
			root.add( new THREE.AmbientLight( 0x333333) );


			var directionalLight = new THREE.DirectionalLight();
			directionalLight.castShadow = true;
			directionalLight.position.set( 0, 500, 0 );
			

			// Create the sun light and add it to the scene
			var sunLight = new SunLight(
				//Oulu
				new THREE.Vector2( 36.77, -119.41 ),
				new THREE.Vector3( 0.0, 0.0, 1.0 ),
				new THREE.Vector3( -1.0, 0.0, 0.0 ),
				new THREE.Vector3( 0.0, -1.0, 0.0 )
			);
			**root.add(sunLight);**

			sunLight.updateOrientation(true);
			sunLight.updateDirectionalLight();

			// Adjust the directional light's shadow camera dimensions 

			sunLight.directionalLight.shadow.camera.right = 1000.0; //add sunLight. 
			sunLight.directionalLight.shadow.camera.left = -1000.0;
			sunLight.directionalLight.shadow.camera.top = 1000.0;
			sunLight.directionalLight.shadow.camera.bottom = -1000.0;
			
			root.add(new THREE.CameraHelper(directionalLight.shadow.camera));
		}
		...

	</script>
</body>

But I instantly get an error like ‘THREE.Object3D.add: object not an instance of THREE.Object3D’ during the addition of sunlight. How could I add sunLight to my script?

Hi @sevval,

The github repo you’ve linked is pretty outdated (7 years) it may be worth looking at creating some sort of extended version of this up to date sky shader, it includes both elevation and azymuth positions in the sky and shouldn’t be too difficult to figure out a location based extension, I’ve never personally used this so not sure if it casts shadows…

Hi @Lawrence3DPK

Thanks for your answer and suggestion. The github repo still works perfectly and casts shadows. But it only works with the old version of threejs. That’s why in the beginning of my script, I also put the old version.

“…src =‘./lib/three.js’>
…src =‘SunLight.js’>”

But as I did not want to use the old version in the remaining part, I imported new version in the module. I will also try the link you wrote down but I am much more looking like something based on the current date and location as I said.

Yes that makes sense, have a look here I think i managed to convert your original reference to a class that should work with the latest versions of three…

you’ll have to copy the code to your local environment but let me know if this works…

EDIT: here’s a pen of it running in action

and here’s a link to the updated repo on github :slight_smile: i’ve created a PR into the original main repo

2 Likes

Hi @forerunrun,

It looks perfect! I think this solved my problem and worked with my script but whatever changed the position of directionalLight, it only covers half of the model. It looks like this:

It also creates straight lines on the ground, if I specify small parameters for directional light, it does not happen.

The numbers I used for directionalLight ;

sunLight.directionalLight.shadow.camera.right = 1000.0; //add sunLight.
sunLight.directionalLight.shadow.camera.left = -1000.0;
sunLight.directionalLight.shadow.camera.top = 1000.0;
sunLight.directionalLight.shadow.camera.bottom = -1000.0;

It is so weird because they used to cover all of the model to cast shadows in the script I did not add the SunLight.

Yes there’s been a lot of changes since r77…

I updated the pen above before seeing your reply, to overcome the shadow stopping haf way you need to set both the near and far parameter on the shadow camera…

sunLight.directionalLight.shadow.camera.near = -1000.0; 
sunLight.directionalLight.shadow.camera.far = 1000.0; 

As for the lines you’ll need to set and play with the light shadow bias to somewhere in the range of -0.0001 to 0.0001 give or take a 0 or two depending on what works best for your use case

sunLight.directionalLight.shadow.bias = 0.0001

you can also consider setting the shadow.mapSize

sunLight.directionalLight.shadow.mapSize.width = 1024;
sunLight.directionalLight.shadow.mapSize.height = 1024;
1 Like

Yes! that worked! I thank you very very much. This helped me a lot :slight_smile:

1 Like