three.js beginner stuck on first step: "undefined is not a function" - javascript

My problem is the same as this question: Three.js - Uncaught TypeError: undefined is not a function -- which did not have a solution that works for me.
I am starting on the Getting Started page in three.js (http://threejs.org/docs/index.html#Manual/Introduction/Creating_a_scene) which presents an
application with the three.js library in a folder accompanying the HTML file. The heart of the code is here:
<script src="js/three.js"></script>
<script>
// Javascript will go here
var scene = new THREE.Scene();
var camera = THREE.PerspectiveCamera( 75,
window.innerWidth / window.innerHeight, 1, 10000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight);
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 1000;
function render() {
requestAnimationFrame( render );
renderer.render( scene, camera );
}
render();
</script>
One may use either the minimized library (three.min.js) in which case I get the error Uncaught TypeError: undefined is not a function and Chrome developer tools cites a line in that file. Likewise, using the unminimized version (three.js) from the mr.doob build folder, the same error occurs but on line 10614. In three.js this is the blank line above this.updateProjectionMatrix() in the following code:
THREE.PerspectiveCamera = function ( fov, aspect, near, far ) {
THREE.Camera.call( this );
this.type = 'PerspectiveCamera';
this.zoom = 1;
this.fov = fov !== undefined ? fov : 50;
this.aspect = aspect !== undefined ? aspect : 1;
this.near = near !== undefined ? near : 0.1;
this.far = far !== undefined ? far : 2000;
this.updateProjectionMatrix();
};
Notice the use of undefined in the four lines above where the error pointed.
I am presenting the code using a MAMP Web server. I have installed it both on my iMac and my Windows 8 PC. The page has failed to appear in both Chrome and Firefox always with the same diagnostic message.
I feel I'm making some very basic error. Help?

You missed the tiny word "new" when creating an instance of THREE.PerspectiveCamera:
<script src="js/three.js"></script>
<script>
// Javascript will go here
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75,
window.innerWidth / window.innerHeight, 1, 10000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight);
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 1000;
function render() {
requestAnimationFrame( render );
renderer.render( scene, camera );
}
render();
</script>
Also please note, that you won't see much as your camera is too far away from that tiny box :)
Make it
camera.position.z = 50;
to see your box shining in green in front of you..

Related

Jquery .html method does not seem to work

The editor project I am making should allow me to Import a cdn library and use it to write code . So to show my problem , enter https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js in the import cdn input and click import . Then enter this in the code section :
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
const animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
Click the run button at the top . You should get a tiny three js window at the bottom. My first question is , why is the text undefined coming above the render ? And two , if you change the code in the input to :
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
const animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
It adds another render to the div . Why ? especially when I have used the .html method to replace the contents of the div . My complete code is visible here
By inspecting the Javascript console, it's clear that the renderer is not added to #body2 but rather to the document.body.
This line:
document.body.appendChild( renderer.domElement );
appends the renderer to the body element.
The undefined is because of String( eval( $("#editor #editor-textarea").val() ));
The text content in eval must return something.
https://www.w3schools.com/jsref/jsref_eval.asp
In this case, the return value of $("#editor #editor-textarea").val() is undefined. Hence eval(undefined) is undefined and String(undefined) is "undefined"

Three.js — Uncaught TypeError: THREE.OrbitControls is not a constructor

I am trying to add Orbit Controls to my scene without success. The code below keeps giving me an error Uncaught TypeError: THREE.OrbitControls is not a constructor. I have tried different solutions I came across the web but, the error still persists. What am I doing wrong?
Pseudocode
Add Orbit Controls
Be able to use Orbit Controls in the scene
Thank you in advance.
Codepen
HTML
<html>
<head>
<title>My first three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="js/three.js"></script>
<script src="https://82mou.github.io/threejs/js/OrbitControls.js"></script>
</body>
</html>
JS
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var scene = new THREE.Scene();
// var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
// var renderer = new THREE.WebGLRenderer();
// renderer.setSize( window.innerWidth, window.innerHeight );
// document.body.appendChild( renderer.domElement );
// CAMERA
var camera = new THREE.PerspectiveCamera(75, 320 / 240, 1, 1000);
camera.position.set(250, 200, 250);
camera.lookAt(0, 0, 0);
// add controls for the camera
var controls = new THREE.OrbitControls(camera);
var geometry = new THREE.PlaneGeometry(100, 50);
var material = new THREE.MeshBasicMaterial( { color: 0xFFFFFF } );
var plane = new THREE.Mesh( geometry, material );
scene.add( plane );
camera.position.z = 200;
var animate = function () {
requestAnimationFrame( animate );
controls.update();
// plane.rotation.x += 0.01;
// plane.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
There is an issue in your codepen. When you import OrbitControls via ES6 imports, it's not necessary to use the THREE namespace. So when doing something like this:
import { OrbitControls } from "https://unpkg.com/three#0.112/examples/jsm/controls/OrbitControls.js";
you have to to create OrbitControls like so:
controls = new OrbitControls( camera, renderer.domElement );
Live example: https://jsfiddle.net/68kzagry/1/

THREE.DragControls is not a constructor error

I am trying to use Three.DragControls constructor for my application in three.js.
I run npm install and npm install three-dragcontrols, receiving the message the dependency was added to the package.
When i am trying to use new Three.DragControls i receive the error:
"THREE.DragControls is not a constructor"
The code:
var scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
var camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
var objects = [];
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
camera.position.z = 1000;
var startColor;
function init() {
scene.add( new THREE.AmbientLight( 0x0f0f0f ) );
var light = new THREE.SpotLight( 0xffffff, 1.5 );
light.position.set( 0, 500, 2000 );
scene.add(light);
var geometry = new THREE.BoxGeometry( 40, 40, 40 );
var geometry = new THREE.SphereGeometry( 40, 40, 40 );
for (var i = 0; i < 100; i++) {
var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
object.position.x = Math.random() * 1000 - 500;
object.position.y = Math.random() * 600 - 300;
object.position.z = Math.random() * 800 - 400;
object.castShadow = true;
object.receiveShadow = true;
scene.add( object );
objects.push( object );
}
var controls = new THREE.DragControls( objects, camera, renderer.domElement );
controls.addEventListener( 'dragstart', dragStartCallback );
controls.addEventListener( 'dragend', dragendCallback );
}
function dragStartCallback(event) {
startColor = event.object.material.color.getHex();
event.object.material.color.setHex(0x000000);
}
function dragendCallback(event) {
event.object.material.color.setHex(startColor);
}
function animate() {
requestAnimationFrame( animate );
renderer.render(scene, camera);
};
init();
animate();
Possible answer (can't post this as a comment because of SO's stupid rules):
Please share the part of your code in which you import/require the module. In many cases with these modules for Three.js you have to attach them to the THREE object.
For example:
// Doesn't work:
THREE.DragControls = require("three-drag-controls");
// Does work:
THREE.DragControls = require("three-drag-controls")(THREE);
This is because the module is in fact a function which returns the constructor for the controls. If you don't run the function first with THREE as an argument, you get "THREE.DragControls is not a constructor".
For those coming here while trying to follow the 'Three.js Drag and Drop Tutorial' and get stuck with the above error message, the solution is to install the Drag Controls module and follow the usage instructions on the repo (https://www.npmjs.com/package/drag-controls), namely changing the imports to:
import * as THREE from 'three';
import DragControls from 'drag-controls'
DragControls.install({THREE: THREE})
And then creating the DragControls instance this way:
var controls = new DragControls( objects, camera, renderer.domElement );
Things should work after that.
Hope this saved some of you some time!

Uncaught TypeError: Cannot read property 'setRGB' of undefined

I'm in the middle of following some beginning lessons on webgl on udacity. In the online snippets they used material.ambient for MeshLambertMaterial.
Below, I'm attempting to create a basic cube example from scratch, but when I try to replace MeshBasicMaterial with MeshLambertMaterial I'm running into problems trying to get the cube to display.
Why isn't ambient defined on material, the way it is in the udacity tutorials? The threejs docs aren't very helpful, they don't even mention an ambient method on material... did the API change?
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshLambertMaterial( { color: 0x00ff00 } );
var kv = 0.4;
//this line gets error: app.js:36 Uncaught TypeError: Cannot read property 'setRGB' of undefined
material.ambient.setRGB(kv * material.color.r, kv * material.color.g, kv * material.color.b);
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
function render() {
requestAnimationFrame( render );
renderer.render( scene, camera );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
}
render();
three.js materials no longer have an ambient property.
The ambient reflectance of the material (how the material responds to indirect, or ambient, light) is now assumed to be the same as the diffuse reflectance of the material (how the material responds to direct light).
The diffuse reflectance of the material is also known as the material's color.
three.js r.80

"Wrap" three.js in SmartMS

I would like to add this simple three.js example in Smart Mobile Studio. Is it possible to do without a whole lot of complex wrapping ? I have tried a naive attempt by copying the window.onload content into an asm section - but of course without luck.
<!DOCTYPE html>
<html>
<head>
<title>Getting Started with Three.js</title>
<script src="three.min.js"></script>
<script>
window.onload = function() {
var renderer = new THREE.WebGLRenderer();
renderer.setSize( 800, 600 );
document.body.appendChild( renderer.domElement );
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
35, // Field of view
800 / 600, // Aspect ratio
0.1, // Near plane
10000 // Far plane
);
camera.position.set( -15, 10, 10 );
camera.lookAt( scene.position );
var geometry = new THREE.CubeGeometry( 5, 5, 5 );
var material = new THREE.MeshLambertMaterial( { color: 0xFF0000 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var light = new THREE.PointLight( 0xFFFF00 );
light.position.set( 10, 0, 10 );
scene.add( light );
renderer.render( scene, camera );
};
</script>
</head>
<body></body>
</html>
I generated a wrapper unit (using my own experimental internal typescript to pascal converter) and also tested the output (and fixed some generator errors):
https://github.com/andremussche/AndrewsDelphiStuff/tree/master/Smart/ThreeJS
Still not perfect (some external class names are missing) but it is good starting point anyway.
In the above demo you can also see how to create a plain html project in SMS IDE :)
I have created a demo, which intentionally deviates as little as possible of Andre’s sample.
More details, see at: http://smartmobilestudio.com/forums/topic/smartms-intro-with-threejs/
#warleyalex your example is wery enlightening for me. The getID function was just what i needed ! But sadly it also makes sms crash. Almost the same way as André's wrapped solution.
function getID(OwnerHandle : TObject): string;
begin
result := TW3TagObj(OwnerHandle).Handle.id;
end;
procedure TForm1.W3ButtonRunClick(Sender: TObject);
var canvas : variant;
begin
canvas := getID(myCanvas); // myCanvas is a TW3DIVHtmlElement
asm
var renderer = new THREE.WebGLRenderer();
renderer.setSize( 800, 600 );
var ctnEl = document.getElementById(#canvas);
ctnEl.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
35, // Field of view
800 / 600, // Aspect ratio
0.1, // Near plane
10000 // Far plane
);
camera.position.set( -15, 10, 10 );
camera.lookAt( scene.position );
var geometry = new THREE.CubeGeometry( 5, 5, 5 );
var material = new THREE.MeshLambertMaterial( { color: 0xFF0000 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var light = new THREE.PointLight( 0xFFFF00 );
light.position.set( 10, 0, 10 );
scene.add( light );
renderer.render( scene, camera );
end;
end;

Categories