Jump to content

Need help with Terrain Heightmap to Mesh Three.js code


Aerion
 Share

Recommended Posts

Hi all. Just as the title says, I need some help with this Three.js code. I would like to know why "img" is reporting "null" even though the image location is correct, the image is there, and the DIV tag is in the right place.

 

Here's the source html file, and all other files needed to make this work.

 

http://mega.co.nz/#!bokBQZib!FFGspP-lTM4dSG9H_fVJSxgdaweDzajQIViyHL09xhk

 

If you open Developer in Mozilla, you will see that the error that you get is: "img is null".

 

Thank You all so much for all of your help! :)

 

Sincerely,

 

Mythros

Link to comment
Share on other sites

2 things to get you further along (still isn't rendering for me)

#assets { visibility: hidden; }

display: none makes it have width of 0

$('#landscape-image').ready(function() {	console.log('image ready, start it up!');	init();	animate();});

need to wait for the image to finish loading, since you have jquery this should work...

Link to comment
Share on other sites

Hi, thanks for the answer. It DOES load now, but it won't show the terrain.

<!doctype html><html lang="en"><head>    <title>Shader - Height Map (Three.js)</title>    <meta charset="utf-8">    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">    <link rel=stylesheet href="css/base.css"/>		<style type="text/css">		#canvas { visibility: hidden; }		#assets { visibility: hidden; }	</style>	</head><body><script src="./js/jquery-1.9.1.js"></script><script src="./js/jquery-ui.js"></script><script src="./js/Three.js"></script><script src="./js/Detector.js"></script><script src="./js/Stats.js"></script><script src="./js/OrbitControls.js"></script><script src="./js/KeyboardState.js"></script><script src="./js/THREEx.js"></script><script src="./js/THREEx_002.js"></script><script src="./js/THREEx.FullScreen.js"></script><script src="./js/THREEx.WindowResize.js"></script><!-- ---------------- Custom Shader Code ------------------------ --><script id="vertexShader" type="x-shader/x-vertex">uniform sampler2D bumpTexture;uniform float bumpScale;varying float vAmount;varying vec2 vUV;void main() {	vUV = uv;	vec4 bumpData = texture2D( bumpTexture, uv );	vAmount = bumpData.g; // assuming map is grayscale it doesn't matter if you use r, g, or b.	// move the position along the normal    vec3 newPosition = (position + normal * bumpScale * vAmount);	gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );}</script><!-- fragment shader a.k.a. pixel shader --><script id="fragmentShader" type="x-shader/x-vertex"> uniform sampler2D oceanTexture;uniform sampler2D sandyTexture;uniform sampler2D grassTexture;uniform sampler2D rockyTexture;uniform sampler2D snowyTexture;varying vec2 vUV;varying float vAmount;void main() {	vec4 water = (smoothstep(0.01, 0.25, vAmount) - smoothstep(0.24, 0.26, vAmount)) * texture2D( oceanTexture, vUV * 10.0 );	vec4 sandy = (smoothstep(0.24, 0.27, vAmount) - smoothstep(0.28, 0.31, vAmount)) * texture2D( sandyTexture, vUV * 10.0 );	vec4 grass = (smoothstep(0.28, 0.32, vAmount) - smoothstep(0.35, 0.40, vAmount)) * texture2D( grassTexture, vUV * 20.0 );	vec4 rocky = (smoothstep(0.30, 0.50, vAmount) - smoothstep(0.40, 0.70, vAmount)) * texture2D( rockyTexture, vUV * 20.0 );	vec4 snowy = (smoothstep(0.50, 0.65, vAmount))                                   * texture2D( snowyTexture, vUV * 10.0 );	gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) + water + sandy + grass + rocky + snowy; //, 1.0);}  </script><!-- ----------------------------------------------------------- --><!-- Code to display an information button and box when clicked. --><link rel=stylesheet href="./css/jquery-ui.css" /><link rel=stylesheet href="./css/info.css"/><script src="./js/info.js"></script><div id="infoButton"></div><!-- ------------------------------------------------------------ --><div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div><script>//To get the pixels, draw the image onto a canvas. From the canvas get the Pixel (R,G,B,A)function getTerrainPixelData(){	var img = document.getElementById("landscape-image");	var canvas = document.getElementById("canvas");	canvas.width = img.width;	canvas.height = img.height;	canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);	var data = canvas.getContext('2d').getImageData(0,0, img.height, img.width).data;	var normPixels = []	for (var i = 0, n = data.length; i < n; i += 4)	{		// get the average value of R, G and B.		normPixels.push((data[i] + data[i+1] + data[i+2]) / 3);	}	return {normPixels: normPixels};}function CreateTerrain(geometry, width, height, numSegments){	width = width || 2400;	height = height || 2400;	numSegments = numSegments || 100;	var material = new THREE.MeshLambertMaterial({		color: 0xccccff,		wireframe: false	});	var terrain = getTerrainPixelData();  	// keep in mind, that the plane has more vertices than segments. If there's one segment, there's two vertices, if	// there's 10 segments, there's 11 vertices, and so forth. 	// The simplest is, if like here you have 100 segments, the image to have 101 pixels. You don't have to worry about	// "skewing the landscape" then..	// to check uncomment the next line, numbers should be equal	 console.log("length: " + terrain.length + ", vertices length: " + geometry.vertices.length);	for (var i = 0, l = geometry.vertices.length; i < l; i++)	{		var terrainValue = terrain[i] / 255;		geometry.vertices[i].z = geometry.vertices[i].z + terrainValue * 200;	}	geometry.computeFaceNormals();	geometry.computeVertexNormals();	var plane = new THREE.Mesh(geometry, material);	plane.position = new THREE.Vector3(0,0,0);	// rotate the plane so up is where y is growing..	var q = new THREE.Quaternion();	q.setFromAxisAngle( new THREE.Vector3(-1,0,0), 90 * Math.PI / 180 );	plane.quaternion.multiplyQuaternions( q, plane.quaternion );	scene.add(plane)	return plane;}// standard global variablesvar container, scene, camera, renderer, controls, stats;var keyboard = new KeyboardState();var clock = new THREE.Clock();// custom global variablesvar mesh;$('#landscape-image').ready(function() {	console.log('image ready, start it up!');	init();	animate();});// FUNCTIONS 		function init() {	// SCENE	scene = new THREE.Scene();	// CAMERA	var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;	var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;	camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);	scene.add(camera);	camera.position.set(0,100,400);	camera.lookAt(scene.position);		// RENDERER	if ( Detector.webgl )		renderer = new THREE.WebGLRenderer( {antialias:true} );	else		renderer = new THREE.CanvasRenderer(); 	renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);	container = document.getElementById( 'ThreeJS' );	container.appendChild( renderer.domElement );	// EVENTS	THREEx.WindowResize(renderer, camera);	THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });	// CONTROLS	controls = new THREE.OrbitControls( camera, renderer.domElement );	// STATS	stats = new Stats();	stats.domElement.style.position = 'absolute';	stats.domElement.style.bottom = '0px';	stats.domElement.style.zIndex = 100;	container.appendChild( stats.domElement );	// LIGHT	var light = new THREE.PointLight(0xffffff);	light.position.set(100,250,100);	scene.add(light);	// SKYBOX	var skyBoxGeometry = new THREE.CubeGeometry( 20000, 20000, 20000 );	var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: 0x99ccff, side: THREE.BackSide } );	var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );	scene.add(skyBox);		////////////	// CUSTOM //	////////////		// texture used to generate "bumpiness"	var bumpTexture = new THREE.ImageUtils.loadTexture( './images/heightmap.png' );	bumpTexture.wrapS = bumpTexture.wrapT = THREE.RepeatWrapping; 	// magnitude of normal displacement	var bumpScale   = 200.0;		var oceanTexture = new THREE.ImageUtils.loadTexture( './images/dirt4-2048.jpg' );	oceanTexture.wrapS = oceanTexture.wrapT = THREE.RepeatWrapping; 		var sandyTexture = new THREE.ImageUtils.loadTexture( './images/sand-waves-2048.jpg' );	sandyTexture.wrapS = sandyTexture.wrapT = THREE.RepeatWrapping; 		var grassTexture = new THREE.ImageUtils.loadTexture( './images/grass2-2048.jpg' );	grassTexture.wrapS = grassTexture.wrapT = THREE.RepeatWrapping; 		var rockyTexture = new THREE.ImageUtils.loadTexture( './images/rock-512.jpg' );	rockyTexture.wrapS = rockyTexture.wrapT = THREE.RepeatWrapping; 		var snowyTexture = new THREE.ImageUtils.loadTexture( './images/snow-2048.jpg' );	snowyTexture.wrapS = snowyTexture.wrapT = THREE.RepeatWrapping; 		// use "this." to create global object	this.customUniforms = {		bumpTexture:	{ type: "t", value: bumpTexture },		bumpScale:	    { type: "f", value: bumpScale },		oceanTexture:	{ type: "t", value: oceanTexture },		sandyTexture:	{ type: "t", value: sandyTexture },		grassTexture:	{ type: "t", value: grassTexture },		rockyTexture:	{ type: "t", value: rockyTexture },		snowyTexture:	{ type: "t", value: snowyTexture },	};		// create custom material from the shader code above	//   that is within specially labelled script tags	var customMaterial = new THREE.ShaderMaterial( 	{	    uniforms: customUniforms,		vertexShader:   document.getElementById( 'vertexShader'   ).textContent,		fragmentShader: document.getElementById( 'fragmentShader' ).textContent,	    side: THREE.DoubleSide	}   );			var planeGeo = new THREE.PlaneGeometry( 1000, 1000, 100, 100 );	var plane = new THREE.Mesh(	planeGeo, customMaterial );	plane.rotation.x = -Math.PI / 2;	plane.position.y = -100;	scene.add( plane );	var terrain = CreateTerrain(planeGeo, 2400, 2400, 100);	var waterGeo = new THREE.PlaneGeometry( 1000, 1000, 1, 1 );	var waterTex = new THREE.ImageUtils.loadTexture( './images/water512.jpg' );	waterTex.wrapS = waterTex.wrapT = THREE.RepeatWrapping; 	waterTex.repeat.set(5, 5);	var waterMat = new THREE.MeshBasicMaterial( {map: waterTex, transparent:true, opacity:0.40} );	var water = new THREE.Mesh(	planeGeo, waterMat );	water.rotation.x = -Math.PI / 2;	water.position.y = -50;	scene.add( water);	}function animate() {    requestAnimationFrame( animate );	render();			update();}function update(){	if ( keyboard.pressed("z") ) 	{	  		// do something	}		controls.update();	stats.update();}function render() {	renderer.render( scene, camera );}</script><canvas id="canvas"></canvas><div id="assets"><img id="landscape-image" src="images/heightmap.png" /></div></body></html>
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...