Interactive 3D Graphics-Lesson4 Problem Set

第四课讲的是变换,还有坐标系之类的,不是很深。

第四课的Problem set记录。

1.机器人手臂

要求是添加机器人手臂的底座,只要理解好THREE.Object3D()就可以了。参考一下原有的代码就可以得到结果。


/*global THREE, Coordinates, $, document, window, dat*/

var camera, scene, renderer;
var cameraControls, effectController;
var clock = new THREE.Clock();
var gridX = true;
var gridY = false;
var gridZ = false;
var axes = true;
var ground = true;
var arm, forearm, body;

function fillScene() {
	scene = new THREE.Scene();
	scene.fog = new THREE.Fog( 0x808080, 2000, 4000 );

	// LIGHTS
	var ambientLight = new THREE.AmbientLight( 0x222222 );
	var light = new THREE.DirectionalLight( 0xffffff, 1.0 );
	light.position.set( 200, 400, 500 );
	var light2 = new THREE.DirectionalLight( 0xffffff, 1.0 );
	light2.position.set( -500, 250, -200 );
	scene.add(ambientLight);
	scene.add(light);
	scene.add(light2);

    // Robot definitions
	var robotBaseMaterial = new THREE.MeshPhongMaterial( { color: 0x6E23BB, specular: 0x6E23BB, shininess: 20 } );
	var robotForearmMaterial = new THREE.MeshPhongMaterial( { color: 0xF4C154, specular: 0xF4C154, shininess: 100 } );
	var robotUpperArmMaterial = new THREE.MeshPhongMaterial( { color: 0x95E4FB, specular: 0x95E4FB, shininess: 100 } );
	var robotBodyMaterial = new THREE.MeshPhongMaterial( { color: 0x279933, specular: 0x279933, shininess: 100 } );

	var torus = new THREE.Mesh( 
		new THREE.TorusGeometry( 22, 15, 32, 32 ), robotBaseMaterial );
	torus.rotation.x = 90 * Math.PI/180;
	scene.add( torus );

	forearm = new THREE.Object3D();
	var faLength = 80;

	createRobotExtender( forearm, faLength, robotForearmMaterial );

	arm = new THREE.Object3D();
	var uaLength = 120;	
	
	createRobotCrane( arm, uaLength, robotUpperArmMaterial );
	
	// Move the forearm itself to the end of the upper arm.
	forearm.position.y = uaLength;	
	arm.add( forearm );
	//scene.add( arm );

    // YOUR CODE HERE
  	body = new THREE.Object3D();
	var bodyLength = 60;
        arm.position.y = bodyLength;
        body.add( arm );
        createRobotBody( body, bodyLength, robotBodyMaterial );
        scene.add( body );
}

function createRobotExtender( part, length, material )
{
	var cylinder = new THREE.Mesh( 
		new THREE.CylinderGeometry( 22, 22, 6, 32 ), material );
	part.add( cylinder );

	var i;
	for ( i = 0; i < 4; i++ )
	{
		var box = new THREE.Mesh( 
			new THREE.CubeGeometry( 4, length, 4 ), material );
		box.position.x = (i < 2) ? -8 : 8;
		box.position.y = length/2;
		box.position.z = (i%2) ? -8 : 8;
		part.add( box );
	}
	
	cylinder = new THREE.Mesh( 
		new THREE.CylinderGeometry( 15, 15, 40, 32 ), material );
	cylinder.rotation.x = 90 * Math.PI/180;
	cylinder.position.y = length;
	part.add( cylinder );
}

function createRobotCrane( part, length, material )
{
	var box = new THREE.Mesh( 
		new THREE.CubeGeometry( 18, length, 18 ), material );
	box.position.y = length/2;
	part.add( box );
	
	var sphere = new THREE.Mesh( 
		new THREE.SphereGeometry( 20, 32, 16 ), material );
	// place sphere at end of arm
	sphere.position.y = length;
	part.add( sphere );
}

function createRobotBody( part, length, material )
{
	var cylinder = new THREE.Mesh( 
		new THREE.CylinderGeometry( 50, 12, length/2, 18 ), material );
	cylinder.position.y = length/4;
	part.add( cylinder );
	
	cylinder = new THREE.Mesh( 
		new THREE.CylinderGeometry( 12, 50, length/2, 18 ), material );
	cylinder.position.y = 3*length/4;
	part.add( cylinder );
	
	var box = new THREE.Mesh( 
		new THREE.CubeGeometry( 12, length/4, 110 ), material );
	box.position.y = length/2;
	part.add( box );

	var sphere = new THREE.Mesh( 
		new THREE.SphereGeometry( 20, 32, 16 ), material );
	// place sphere at end of arm
	sphere.position.y = length;
	part.add( sphere );
}

function init() {
	var canvasWidth = 846;
	var canvasHeight = 494;
	var canvasRatio = canvasWidth / canvasHeight;

	// RENDERER
	renderer = new THREE.WebGLRenderer( { antialias: true } );
	renderer.gammaInput = true;
	renderer.gammaOutput = true;
	renderer.setSize(canvasWidth, canvasHeight);
	renderer.setClearColorHex( 0xAAAAAA, 1.0 );

	// CAMERA
	camera = new THREE.PerspectiveCamera( 38, canvasRatio, 1, 10000 );
	camera.position.set( -510, 240, 100 );
	// CONTROLS
	cameraControls = new THREE.OrbitAndPanControls(camera, renderer.domElement);
	cameraControls.target.set(0,120,0);
	camera.position.set(-102, 177, 20);
	cameraControls.target.set(-13, 60, 2);
	fillScene();

}

function addToDOM() {
    var container = document.getElementById('container');
    var canvas = container.getElementsByTagName('canvas');
    if (canvas.length>0) {
        container.removeChild(canvas[0]);
    }
    container.appendChild( renderer.domElement );
}

function drawHelpers() {
    if (ground) {
		Coordinates.drawGround({size:10000});		
	}
	if (gridX) {
		Coordinates.drawGrid({size:10000,scale:0.01});
	}
	if (gridY) {
		Coordinates.drawGrid({size:10000,scale:0.01, orientation:"y"});
	}
	if (gridZ) {
		Coordinates.drawGrid({size:10000,scale:0.01, orientation:"z"});	
	}
	if (axes) {
		Coordinates.drawAllAxes({axisLength:200,axisRadius:1,axisTess:50});
	}
}

function animate() {
	window.requestAnimationFrame(animate);
	render();
}

function render() {
	var delta = clock.getDelta();
	cameraControls.update(delta);

	if ( effectController.newGridX !== gridX || effectController.newGridY !== gridY || effectController.newGridZ !== gridZ || effectController.newGround !== ground || effectController.newAxes !== axes)
	{
		gridX = effectController.newGridX;
		gridY = effectController.newGridY;
		gridZ = effectController.newGridZ;
		ground = effectController.newGround;
		axes = effectController.newAxes;

		fillScene();
	}
  
    // UNCOMMENT FOLLOWING LINES TO ENABLE CONTROLS FOR BODY:
  
	// body.rotation.y = effectController.by * Math.PI/180;	// yaw

	arm.rotation.y = effectController.uy * Math.PI/180;	// yaw
	arm.rotation.z = effectController.uz * Math.PI/180;	// roll
	
	forearm.rotation.y = effectController.fy * Math.PI/180;	// yaw
	forearm.rotation.z = effectController.fz * Math.PI/180;	// roll
	
	renderer.render(scene, camera);
}

function setupGui() {

	effectController = {

		newGridX: gridX,
		newGridY: gridY,
		newGridZ: gridZ,
		newGround: ground,
		newAxes: axes,
		
        // UNCOMMENT FOLLOWING LINE TO SET DEFAULT VALUE OF CONTROLS FOR BODY:
		// by: 0.0,
		
		uy: 70.0,
		uz: -15.0,

		fy: 10.0,
		fz: 60.0
	};

	var gui = new dat.GUI();
	var h = gui.addFolder("Grid display");
	h.add( effectController, "newGridX").name("Show XZ grid");
	h.add( effectController, "newGridY" ).name("Show YZ grid");
	h.add( effectController, "newGridZ" ).name("Show XY grid");
	h.add( effectController, "newGround" ).name("Show ground");
	h.add( effectController, "newAxes" ).name("Show axes");
	h = gui.addFolder("Arm angles");
	// student, uncomment: h.add(effectController, "by", -180.0, 180.0, 0.025).name("Body y");
	h.add(effectController, "uy", -180.0, 180.0, 0.025).name("Upper arm y");
	h.add(effectController, "uz", -45.0, 45.0, 0.025).name("Upper arm z");
	h.add(effectController, "fy", -180.0, 180.0, 0.025).name("Forearm y");
	h.add(effectController, "fz", -120.0, 120.0, 0.025).name("Forearm z");
}

init();
fillScene();
drawHelpers();
addToDOM();
setupGui();
animate();



2.添加机器人手指

首先参照leftHand的创建方式创建rightHand,然后在render()方法中添加对手指的控制。


/*global THREE, Coordinates, $, document, window, dat*/

var camera, scene, renderer;
var cameraControls, effectController;
var clock = new THREE.Clock();
var gridX = true;
var gridY = false;
var gridZ = false;
var axes = true;
var ground = true;
var arm, forearm, body, handLeft, handRight;

function fillScene() {
	scene = new THREE.Scene();
	scene.fog = new THREE.Fog( 0x808080, 2000, 4000 );

	// LIGHTS
	var ambientLight = new THREE.AmbientLight( 0x222222 );
	var light = new THREE.DirectionalLight( 0xffffff, 1.0 );
	light.position.set( 200, 400, 500 );
	var light2 = new THREE.DirectionalLight( 0xffffff, 1.0 );
	light2.position.set( -500, 250, -200 );
	scene.add(ambientLight);
	scene.add(light);
	scene.add(light2);

    // Robot definitions
	var robotHandLeftMaterial = new THREE.MeshPhongMaterial( { color: 0xCC3399, specular: 0xCC3399, shininess: 20 } );
	var robotHandRightMaterial = new THREE.MeshPhongMaterial( { color: 0xDD3388, specular: 0xDD3388, shininess: 20 } );
	var robotBaseMaterial = new THREE.MeshPhongMaterial( { color: 0x6E23BB, specular: 0x6E23BB, shininess: 20 } );
	var robotForearmMaterial = new THREE.MeshPhongMaterial( { color: 0xF4C154, specular: 0xF4C154, shininess: 100 } );
	var robotUpperArmMaterial = new THREE.MeshPhongMaterial( { color: 0x95E4FB, specular: 0x95E4FB, shininess: 100 } );

	var torus = new THREE.Mesh( 
		new THREE.TorusGeometry( 22, 15, 32, 32 ), robotBaseMaterial );
	torus.rotation.x = 90 * Math.PI/180;
	scene.add( torus );
	
	forearm = new THREE.Object3D();
	var faLength = 80;

	createRobotExtender( forearm, faLength, robotForearmMaterial );

	arm = new THREE.Object3D();
	var uaLength = 120;	
	
	createRobotCrane( arm, uaLength, robotUpperArmMaterial );
	
	// Move the forearm itself to the end of the upper arm.
	forearm.position.y = uaLength;	
	arm.add( forearm );
	
	scene.add( arm );

	var handLength = 38;

	handLeft = new THREE.Object3D();
	createRobotGrabber( handLeft, handLength, robotHandLeftMaterial );
	// Move the hand part to the end of the forearm.
	handLeft.position.y = faLength;		
	forearm.add( handLeft );
  
    // YOUR CODE HERE
	// Add the second grabber handRight. Note that it uses a different color, defined above
     handRight= new THREE.Object3D();
	createRobotGrabber( handRight, handLength, robotHandRightMaterial );
	// Move the hand part to the end of the forearm.
	handRight.position.y = faLength;		
	forearm.add( handRight );
    // ALSO EDIT render() TO ENABLE CONTROLS FOR GRABBER

}

function createRobotGrabber( part, length, material )
{
	var box = new THREE.Mesh( 
		new THREE.CubeGeometry( 30, length, 4 ), material );
	box.position.y = length/2;
	part.add( box );
}

function createRobotExtender( part, length, material )
{
	var cylinder = new THREE.Mesh( 
		new THREE.CylinderGeometry( 22, 22, 6, 32 ), material );
	part.add( cylinder );

	var i;
	for ( i = 0; i < 4; i++ )
	{
		var box = new THREE.Mesh( 
			new THREE.CubeGeometry( 4, length, 4 ), material );
		box.position.x = (i < 2) ? -8 : 8;
		box.position.y = length/2;
		box.position.z = (i%2) ? -8 : 8;
		part.add( box );
	}
	
	cylinder = new THREE.Mesh( 
		new THREE.CylinderGeometry( 15, 15, 40, 32 ), material );
	cylinder.rotation.x = 90 * Math.PI/180;
	cylinder.position.y = length;
	part.add( cylinder );
}

function createRobotCrane( part, length, material )
{
	var box = new THREE.Mesh( 
		new THREE.CubeGeometry( 18, length, 18 ), material );
	box.position.y = length/2;
	part.add( box );
	
	var sphere = new THREE.Mesh( 
		new THREE.SphereGeometry( 20, 32, 16 ), material );
	// place sphere at end of arm
	sphere.position.y = length;
	part.add( sphere );
}

function init() {
	var canvasWidth = 846;
	var canvasHeight = 494;
	var canvasRatio = canvasWidth / canvasHeight;

	// RENDERER
	renderer = new THREE.WebGLRenderer( { antialias: true } );
	renderer.gammaInput = true;
	renderer.gammaOutput = true;
	renderer.setSize(canvasWidth, canvasHeight);
	renderer.setClearColorHex( 0xAAAAAA, 1.0 );

	// CAMERA
	camera = new THREE.PerspectiveCamera( 38, canvasRatio, 1, 10000 );
	// CONTROLS
	cameraControls = new THREE.OrbitAndPanControls(camera, renderer.domElement);
	camera.position.set(-49, 242,54);
	cameraControls.target.set(54, 106, 33);
	fillScene();

}

function addToDOM() {
    var container = document.getElementById('container');
    var canvas = container.getElementsByTagName('canvas');
    if (canvas.length>0) {
        container.removeChild(canvas[0]);
    }
    container.appendChild( renderer.domElement );
}

function drawHelpers() {
    if (ground) {
		Coordinates.drawGround({size:10000});		
	}
	if (gridX) {
		Coordinates.drawGrid({size:10000,scale:0.01});
	}
	if (gridY) {
		Coordinates.drawGrid({size:10000,scale:0.01, orientation:"y"});
	}
	if (gridZ) {
		Coordinates.drawGrid({size:10000,scale:0.01, orientation:"z"});	
	}
	if (axes) {
		Coordinates.drawAllAxes({axisLength:200,axisRadius:1,axisTess:50});
	}
}

function animate() {
	window.requestAnimationFrame(animate);
	render();
}

function render() {
	var delta = clock.getDelta();
	cameraControls.update(delta);

	if ( effectController.newGridX !== gridX || effectController.newGridY !== gridY || effectController.newGridZ !== gridZ || effectController.newGround !== ground || effectController.newAxes !== axes)
	{
		gridX = effectController.newGridX;
		gridY = effectController.newGridY;
		gridZ = effectController.newGridZ;
		ground = effectController.newGround;
		axes = effectController.newAxes;

		fillScene();
	}
  
	arm.rotation.y = effectController.uy * Math.PI/180;	// yaw
	arm.rotation.z = effectController.uz * Math.PI/180;	// roll
	
	forearm.rotation.y = effectController.fy * Math.PI/180;	// yaw
	forearm.rotation.z = effectController.fz * Math.PI/180;	// roll
	
    // ADD handRight yaw AND translate HERE
    handLeft.rotation.z = effectController.hz * Math.PI/180;	// yaw
	handLeft.position.z = effectController.htz;	// translate
    
    handRight.rotation.z = effectController.hz * Math.PI/180;
    handRight.position.z = -effectController.htz;
	renderer.render(scene, camera);
}

function setupGui() {

	effectController = {

		newGridX: gridX,
		newGridY: gridY,
		newGridZ: gridZ,
		newGround: ground,
		newAxes: axes,
		
		uy: 70.0,
		uz: -15.0,

		fy: 10.0,
		fz: 60.0,
        
        hz: 30.0,
		htz: 12.0
	};

	var gui = new dat.GUI();
	var h = gui.addFolder("Grid display");
	h.add( effectController, "newGridX").name("Show XZ grid");
	h.add( effectController, "newGridY" ).name("Show YZ grid");
	h.add( effectController, "newGridZ" ).name("Show XY grid");
	h.add( effectController, "newGround" ).name("Show ground");
	h.add( effectController, "newAxes" ).name("Show axes");
	h = gui.addFolder("Arm angles");
	h.add(effectController, "uy", -180.0, 180.0, 0.025).name("Upper arm y");
	h.add(effectController, "uz", -45.0, 45.0, 0.025).name("Upper arm z");
	h.add(effectController, "fy", -180.0, 180.0, 0.025).name("Forearm y");
	h.add(effectController, "fz", -120.0, 120.0, 0.025).name("Forearm z");
    h.add(effectController, "hz", -45.0, 45.0, 0.025).name("Hand z");
	h.add(effectController, "htz", 2.0, 17.0, 0.025).name("Hand spread");
}

init();
fillScene();
drawHelpers();
addToDOM();
setupGui();
animate();



3.画一朵花

这里给出了花的柄,要求画出24朵花瓣。

花瓣的绘制方法已经给出,通过循环变换就可以绘制出来,注意变换的顺序。


// Make a Flower

/*global THREE, Coordinates, document, window, dat*/

var camera, scene, renderer;
var cameraControls, effectController;
var clock = new THREE.Clock();
var gridX = true;
var gridY = false;
var gridZ = false;
var axes = true;
var ground = true;


function fillScene() {
	scene = new THREE.Scene();
	scene.fog = new THREE.Fog( 0x808080, 2000, 4000 );

	// LIGHTS
	var ambientLight = new THREE.AmbientLight( 0x222222 );
	var light = new THREE.DirectionalLight( 0xffffff, 1.0 );
	light.position.set( 200, 400, 500 );
	var light2 = new THREE.DirectionalLight( 0xffffff, 1.0 );
	light2.position.set( -500, 250, -200 );
	scene.add(ambientLight);
	scene.add(light);
	scene.add(light2);

    // FLOWER
    var petalMaterial = new THREE.MeshLambertMaterial( { color: 0xCC5920 } );
	var flowerHeight = 200;
	var petalLength = 120;
	var cylGeom = new THREE.CylinderGeometry( 15, 0, petalLength, 32 );
	var flower = new THREE.Object3D();
    
    /
    // YOUR CODE HERE
	// add code here to make 24 petals, radiating around the sphere
    for (var i=0;i<24;i++)
    {
    	var cylinder = new THREE.Mesh( cylGeom, petalMaterial );
        
        cylinder.rotation.x = 90*Math.PI/180;
        cylinder.position.z = petalLength/2;
        var petal = new THREE.Object3D();
        petal.position.y = flowerHeight;
         petal.rotation.y = i*15*Math.PI/180;
        petal.add( cylinder );
        flower.add( petal );
    }

    
	var stamenMaterial = new THREE.MeshLambertMaterial( { color: 0x333310 } );
	var stamen = new THREE.Mesh( 
		new THREE.SphereGeometry( 20, 32, 16 ), stamenMaterial );
	stamen.position.y = flowerHeight;	// move to flower center
	flower.add( stamen );

	var stemMaterial = new THREE.MeshLambertMaterial( { color: 0x339424 } );
	var stem = new THREE.Mesh( 
		new THREE.CylinderGeometry( 10, 10, flowerHeight, 32 ), stemMaterial );
	stem.position.y = flowerHeight/2;	// move from ground to stamen
	flower.add( stem );

	scene.add( flower );

}


function init() {
	var canvasWidth = 846; 
	var canvasHeight = 494;
	var canvasRatio = canvasWidth / canvasHeight;

	// RENDERER
	renderer = new THREE.WebGLRenderer( { antialias: false } );
	renderer.gammaInput = true;
	renderer.gammaOutput = true;
	renderer.setSize(canvasWidth, canvasHeight);
	renderer.setClearColorHex( 0xAAAAAA, 1.0 );

	// CAMERA
	camera = new THREE.PerspectiveCamera( 38, canvasRatio, 1, 10000 );
	// CONTROLS
	cameraControls = new THREE.OrbitAndPanControls(camera, renderer.domElement);
	camera.position.set(-200, 400, 20);
	cameraControls.target.set(0,150,0);
	fillScene();

}

function addToDOM() {
    var container = document.getElementById('container');
    var canvas = container.getElementsByTagName('canvas');
    if (canvas.length>0) {
        container.removeChild(canvas[0]);
    }
    container.appendChild( renderer.domElement );
}

function drawHelpers() {
  if (ground) {
		Coordinates.drawGround({size:10000});		
	}
	if (gridX) {
		Coordinates.drawGrid({size:10000,scale:0.01});
	}
	if (gridY) {
		Coordinates.drawGrid({size:10000,scale:0.01, orientation:"y"});
	}
	if (gridZ) {
		Coordinates.drawGrid({size:10000,scale:0.01, orientation:"z"});	
	}
	if (axes) {
		Coordinates.drawAllAxes({axisLength:200,axisRadius:1,axisTess:50});
	}
}

function animate() {
	window.requestAnimationFrame(animate);
	render();
}

function render() {
	var delta = clock.getDelta();
	cameraControls.update(delta);

	if ( effectController.newGridX !== gridX || effectController.newGridY !== gridY || effectController.newGridZ !== gridZ || effectController.newGround !== ground || effectController.newAxes !== axes)
	{
		gridX = effectController.newGridX;
		gridY = effectController.newGridY;
		gridZ = effectController.newGridZ;
		ground = effectController.newGround;
		axes = effectController.newAxes;

		fillScene();
	}

	renderer.render(scene, camera);
}



function setupGui() {

	effectController = {

		newGridX: gridX,
		newGridY: gridY,
		newGridZ: gridZ,
		newGround: ground,
		newAxes: axes

	};

	var gui = new dat.GUI();
	var h = gui.addFolder("Grid display");
	h.add( effectController, "newGridX").name("Show XZ grid");
	h.add( effectController, "newGridY" ).name("Show YZ grid");
	h.add( effectController, "newGridZ" ).name("Show XY grid");
	h.add( effectController, "newGround" ).name("Show ground");
	h.add( effectController, "newAxes" ).name("Show axes");

}


// this is the main action sequence
init();
fillScene();
drawHelpers();
addToDOM();
setupGui();
animate();



4.压扁的花

在上一个程序上的改进,然它看起来更棒一些。
对花瓣继续进行处理,压扁,并且产生一些倾角。最终效果如下:


关键代码

    

 for (var i=0;i<24;i++)
    {
    	var cylinder = new THREE.Mesh( cylGeom, petalMaterial );
       // cylinder.position.y = petalHeight;
        cylinder.scale.z = 0.25;
        cylinder.rotation.x = 90*Math.PI/180;
        //cylinder.rotation.x = -20*Math.PI/180;
        cylinder.position.z = petalLength/2;
        var petal = new THREE.Object3D();
        
        petal.add( cylinder );
        petal.rotation.x = -20*Math.PI/180;
        var tmpObject = new THREE.Object3D();
        tmpObject.add( petal);
        tmpObject.rotation.y = i*15*Math.PI/180;
        tmpObject.position.y = flowerHeight;
         
        
        flower.add( tmpObject );
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值