Interactive 3D Graphics-Lesson2 Problem Set

本文记录了Udacity图形学公开课Interactive3DGraphics的学习进度及作业解答,包括多边形的三角形划分、指定位置绘制多边形、楼梯建模及三维空间物体建模等实践内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Interactive 3D Graphics是Udacity上的一门图形学公开课(需要翻墙),最近在学习,在这里记录一下课程的学习进度和作业的答案。


多边形的三角形划分

由于在图形学中,面的表示通常是用三角形来表示,所以要显示多边形的时候,就要将其碎片化。

////////////////////////////////////////////////////////////////////////////////
// Polygon Creation Exercise
// Your task is to complete the function PolygonGeometry(sides)
// which takes 1 argument:
//   sides - how many edges the polygon has.
// Return the mesh that defines the minimum number of triangles necessary
// to draw the polygon.
// Radius of the polygon is 1. Center of the polygon is at 0, 0.
////////////////////////////////////////////////////////////////////////////////
/*global, THREE, Coordinates, $, document, window*/

var camera, scene, renderer;
var windowScale;

function PolygonGeometry(sides) {
	var geo = new THREE.Geometry();
	
	// generate vertices
	for ( var pt = 0 ; pt < sides; pt++ )
	{
		// Add 90 degrees so we start at +Y axis, rotate counterclockwise around
		var angle = (Math.PI/2) + (pt / sides) * 2 * Math.PI;

		var x = Math.cos( angle );
		var y = Math.sin( angle );
		
		// YOUR CODE HERE
        //Save the vertex location - fill in the code
        geo.vertices.push(new THREE.Vector3(x,y,0));
	}
    // YOUR CODE HERE
	// Write the code to generate minimum number of faces for the polygon.
    for ( var fc = 0 ; fc < sides-1; fc++ )
	{
    geo.faces.push( new THREE.Face3( 0, fc, fc+1) );
    }
	// Return the geometry object
	return geo;
}

function init() {
	//  Setting up some parameters
	var canvasWidth = 846;
	var canvasHeight = 494;
	var canvasRatio = canvasWidth / canvasHeight;
	// scene
	scene = new THREE.Scene();

	// Camera: Y up, X right, Z up
	windowScale = 4;
	var windowWidth = windowScale * canvasRatio;
	var windowHeight = windowScale;

	camera = new THREE.OrthographicCamera( windowWidth / - 2, windowWidth / 2, windowHeight / 2, windowHeight / - 2, 0, 40 );
	
	var focus = new THREE.Vector3( 0,1,0 );
	camera.position.x = focus.x;
	camera.position.y = focus.y;
	camera.position.z = 10;
	camera.lookAt(focus);

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

}
function showGrids() {
  	// Background grid and axes. Grid step size is 1, axes cross at 0, 0
	Coordinates.drawGrid({size:100,scale:1,orientation:"z"});
	Coordinates.drawAxes({axisLength:4,axisOrientation:"x",axisRadius:0.02});
	Coordinates.drawAxes({axisLength:3,axisOrientation:"y",axisRadius:0.02});
}
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 render() {
	renderer.render( scene, camera );
}

// Main body of the script
init();
showGrids();
addToDOM();
var geo = PolygonGeometry(5);
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, side: THREE.FrontSide } );
var mesh = new THREE.Mesh( geo, material );
scene.add( mesh );
render();

运行结果:




在制定位置绘制制定半径的多边形

原先的函数变成了PolygonGeometry(sides,radius, location),只要在生成vertex的时候对坐标进行相应的变换就可已了。

////////////////////////////////////////////////////////////////////////////////
// Polygon Radius Exercise
// Your task is to write a function that will take 3 arguments:
//   sides - how many edges the polygon has.
//   location - location of the center of the polygon as a THREE.Vector3.
//   radius - radius of the polygon.
// Return the mesh that defines the minimum number of triangles necessary
// to draw the polygon.
////////////////////////////////////////////////////////////////////////////////
/*global, THREE, Coordinates, $, document, window*/

var camera, scene, renderer;
var windowScale;

function PolygonGeometry(sides, location, radius) {
	var geo = new THREE.Geometry();
	
	// generate vertices
	for ( var pt = 0 ; pt < sides; pt++ )
	{
		// Add 90 degrees so we start at +Y axis, rotate counterclockwise around
		var angle = (Math.PI/2) + (pt / sides) * 2 * Math.PI;

		var x = radius*Math.cos(angle) + location.x;
		var y = radius*Math.sin(angle) + location.y;
		
		// Save the vertex location
		geo.vertices.push( new THREE.Vector3( x, y, 0.0 ) );
	}

	// generate faces
	for ( var face = 0 ; face < sides-2; face++ )
	{
		// this makes a triangle fan, from the first +Y point around
		geo.faces.push( new THREE.Face3( 0, face+1, face+2 ) );
	}	
	// done: return it.
	return geo;
}

function init() {
	//  Setting up some parameters
	var canvasWidth = 846;
	var canvasHeight = 494;
	var canvasRatio = canvasWidth / canvasHeight;
	// scene
	scene = new THREE.Scene();

	// Camera: Y up, X right, Z up
	windowScale = 12;
	var windowWidth = windowScale * canvasRatio;
	var windowHeight = windowScale;

	camera = new THREE.OrthographicCamera( windowWidth / - 2, windowWidth / 2, windowHeight / 2, windowHeight / - 2, 0, 40 );
	
	var focus = new THREE.Vector3( 5,5,0 );
	camera.position.x = focus.x;
	camera.position.y = focus.y;
	camera.position.z = 10;
	camera.lookAt(focus);


	renderer = new THREE.WebGLRenderer({ antialias: false, preserveDrawingBuffer: true});
	renderer.gammaInput = true;
	renderer.gammaOutput = true;
	renderer.setSize(canvasWidth, canvasHeight);
	renderer.setClearColorHex( 0xffffff, 1.0 );
	
}
function showGrids() {
  	// Background grid and axes. Grid step size is 1, axes cross at 0, 0
	Coordinates.drawGrid({size:100,scale:1,orientation:"z"});
	Coordinates.drawAxes({axisLength:4,axisOrientation:"x",axisRadius:0.02});
	Coordinates.drawAxes({axisLength:3,axisOrientation:"y",axisRadius:0.02});
}
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 render() {
	renderer.render( scene, camera );
}

// Main body of the script
init();
showGrids();
addToDOM();
var geo = PolygonGeometry(9, new THREE.Vector3( 5, 5, 0 ), 4);
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, side: THREE.FrontSide } );
var mesh = new THREE.Mesh( geo, material );
scene.add( mesh );
render();




建造楼梯

搭建一个楼梯,最终获得奖杯。

////////////////////////////////////////////////////////////////////////////////
// Staircase exercise                                                         //
// Your task is to complete the model for simple stairs                       //
// Using the provided sizes and colors, complete the staircase                //
// and reach the Gold Cup!                                                    //
////////////////////////////////////////////////////////////////////////////////
/*global, THREE, Coordinates, $, document, window, dat*/

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

function createStairs() {

	// MATERIALS
	var stepMaterialVertical = new THREE.MeshLambertMaterial( { 
		color: 0xA85F35 
	} );
	var stepMaterialHorizontal = new THREE.MeshLambertMaterial( { 
		color: 0xBC7349 
	} );

	var stepWidth = 500;
	var stepSize = 200;
	var stepThickness = 50;
	// height from top of one step to bottom of next step up
	var verticalStepHeight = stepSize;
	var horizontalStepDepth = stepSize*2;

	var stepHalfThickness = stepThickness/2;
	
	// +Y direction is up
	// Define the two pieces of the step, vertical and horizontal
	// THREE.CubeGeometry takes (width, height, depth)
	var stepVertical = new THREE.CubeGeometry(stepWidth, verticalStepHeight, stepThickness);
	var stepHorizontal = new THREE.CubeGeometry(stepWidth, stepThickness, horizontalStepDepth);
	var stepMesh;

     for( var i=0;i<6;i++ )
    {
        stepMesh = new THREE.Mesh( stepVertical, stepMaterialVertical );
	// The position is where the center of the block will be put.
	// You can define position as THREE.Vector3(x, y, z) or in the following way:
        stepMesh.position.x = 0;			// centered at origin
        stepMesh.position.y = i*verticalStepHeight+verticalStepHeight/2+i*stepThickness;	// half of height: put it above ground plane
        stepMesh.position.z = i*horizontalStepDepth-i*stepThickness;			// centered at origin
        scene.add( stepMesh );
    }
	

	// Make and position the horizontal part
     for( var i=0;i<6;i++ )
    {
        stepMesh = new THREE.Mesh( stepHorizontal, stepMaterialHorizontal );
        stepMesh.position.x = 0;
        // Push up by half of horizontal step's height, plus vertical step's height
        stepMesh.position.y = i*stepThickness + (i+1)*verticalStepHeight+stepHalfThickness;
        // Push step forward by half the depth, minus half the vertical step's thickness
        stepMesh.position.z = i*horizontalStepDepth+horizontalStepDepth/2 -  i*stepThickness-stepHalfThickness;
        scene.add( stepMesh );
    }
}

function createCup() {
	var cupMaterial = new THREE.MeshLambertMaterial( { color: 0xFDD017});
	// THREE.CylinderGeometry takes (radiusTop, radiusBottom, height, segmentsRadius)
	var cupGeo = new THREE.CylinderGeometry( 200, 50, 400, 32 );
	var cup = new THREE.Mesh( cupGeo, cupMaterial );
	cup.position.x = 0;
	cup.position.y = 1725;
	cup.position.z = 1925;
	scene.add( cup );
	cupGeo = new THREE.CylinderGeometry( 100, 100, 50, 32 );
	cup = new THREE.Mesh( cupGeo, cupMaterial );
	cup.position.x = 0;
	cup.position.y = 1525;
	cup.position.z = 1925;
	scene.add( cup );
}

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( 45, canvasRatio, 1, 40000 );
	camera.position.set( -700, 500, -1600 );
	// CONTROLS
	cameraControls = new THREE.OrbitAndPanControls(camera, renderer.domElement);
	cameraControls.target.set(0,600,0);

	// Camera(2) for testing has following values:
	// camera.position.set( 1225, 2113, 1814 );
	// cameraControls.target.set(-1800,180,630);
  
	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 fillScene() {
	// SCENE
	scene = new THREE.Scene();
	scene.fog = new THREE.Fog( 0x808080, 3000, 6000 );
	// 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( -400, 200, -300 );

	scene.add(ambientLight);
	scene.add(light);
	scene.add(light2);

	scene.add(camera);

	if (ground) {
		Coordinates.drawGround({size:1000});		
	}
	if (gridX) {
		Coordinates.drawGrid({size:1000,scale:0.01});
	}
	if (gridY) {
		Coordinates.drawGrid({size:1000,scale:0.01, orientation:"y"});
	}
	if (gridZ) {
		Coordinates.drawGrid({size:1000,scale:0.01, orientation:"z"});	
	}
	if (axes) {
		Coordinates.drawAllAxes({axisLength:300,axisRadius:2,axisTess:50});
	}
	createCup();
	var stairs = createStairs();
	scene.add(stairs);
}
//

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,

		dummy: function() {
		}
	};

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

init();
addToDOM();
setupGui();
animate();



空间建模

第三题十一个三维建模的题目,需要一些空间想象。

和3dmax的建模类似,在max中建模是交互的,但这里是需要代码来实现。

主要用到了三个函数来创建空间物体:

//Create box
boxGeometry = New THREE.CubeGeometry(float width,float,height,float depth);
//Create sphere
sphereGeometry = New THREE.SphereGeometry(float radius,int segsWidth,int segsHeight);
// Create cylinder
cylinderGeometry = New THREE.CylinderGeometry(float radius1,float radius1,int height,int segs);

平面图如下:




代码如下

////////////////////////////////////////////////////////////////////////////////
// Drinking Bird Model exercise                                               //
// Your task is to complete the model for the drinking bird                   //
// The following forms and sizes should be used:                              //
// Hat: cylinder. color blue (cylinderMaterial)                               //
//      Diameter top 80, bottom, full height 80, edge 10                      //
// Head: sphere, red (sphereMaterial), diameter 104                           //
// Middle of base: cube, color orange (cubeMaterial), width 77, length 194     //
// Feet: cube, color orange, width 6, length 194, height 52                    //
// Legs: cube, color orange, width 6, length 64, height 386                    //
// Body: sphere, red, diameter 116                                            //
// Spine: cylinder, blue, diameter 24, length 390                             //
////////////////////////////////////////////////////////////////////////////////
/*global, THREE, Coordinates, $, document, window, dat*/

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

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( 45, canvasRatio, 1, 40000 );
	// CONTROLS
	cameraControls = new THREE.OrbitAndPanControls(camera, renderer.domElement);

	camera.position.set( -480, 659, -619 );
	cameraControls.target.set(4,301,92);

	fillScene();
}

// Supporting frame for the bird - base + legs + feet
function createSupport() {

   var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0xF07020 } );
	// base
	var cube;
	cube = new THREE.Mesh( 
		new THREE.CubeGeometry( 20+64+110, 4, 2*77 ), cubeMaterial );
	cube.position.x = -45;	// (20+32) - half of width (20+64+110)/2
	cube.position.y = 4/2;	// half of height
	cube.position.z = 0;	// centered at origin
	scene.add( cube );
	
	// left foot
	cube = new THREE.Mesh( 
		new THREE.CubeGeometry( 20+64+110, 52, 6 ), cubeMaterial );
	cube.position.x = -45;	// (20+32) - half of width (20+64+110)/2
	cube.position.y = 52/2;	// half of height
	cube.position.z = 77 + 6/2;	// offset 77 + half of depth 6/2
	scene.add( cube );
	
	// left leg
	cube = new THREE.Mesh( 
		new THREE.CubeGeometry( 64, 334+52, 6 ), cubeMaterial );
	cube.position.x = 0;	// centered on origin along X
	cube.position.y = (334+52)/2;
	cube.position.z = 77 + 6/2;	// offset 77 + half of depth 6/2
	scene.add( cube );
	
	// right foot
	cube = new THREE.Mesh( 
		new THREE.CubeGeometry( 20+64+110, 52, 6 ), cubeMaterial );
	cube.position.x = -45;	// (20+32) - half of width (20+64+110)/2
	cube.position.y = 52/2;	// half of height
	cube.position.z = -77 + -6/2;	// offset 77 + half of depth 6/2
	scene.add( cube );
	// right leg
    cube = new THREE.Mesh( 
		new THREE.CubeGeometry( 64, 334+52, 6 ), cubeMaterial );
	cube.position.x = 0;	// centered on origin along X
	cube.position.y = (334+52)/2;
	cube.position.z = -77 + -6/2;	// offset 77 + half of depth 6/2
	scene.add( cube );
}

// Body of the bird - body and the connector of body and head
function createBody() {
   var sphereMaterial = new THREE.MeshLambertMaterial( { color: 0xA00000 } );
   var cylinderMaterial = new THREE.MeshLambertMaterial( { color: 0x0000D0 } );
    
    //Create two balls 
   var sphere;
   sphere = new THREE.Mesh( new THREE.SphereGeometry( 116/2, 32, 16 ), sphereMaterial );
	sphere.position.x = 0;	
	sphere.position.y = 160;	
	sphere.position.z = 0;	
	scene.add( sphere );
    
    sphere = new THREE.Mesh( new THREE.SphereGeometry( 104/2, 32, 16 ), sphereMaterial );
	sphere.position.x = 0;	
	sphere.position.y = 390+160;	
	sphere.position.z = 0;	
	scene.add( sphere );
    
    //Create a stick
    var cylinder;
    cylinder=new THREE.Mesh(new THREE.CylinderGeometry( 12, 12, 390, 32 ), cylinderMaterial);
    cylinder.position.x = 0;	
	cylinder.position.y = 160+390/2;	
	cylinder.position.z = 0;	
	scene.add( cylinder );
}

// Head of the bird - head + hat
function createHead() {
   var sphereMaterial = new THREE.MeshLambertMaterial( { color: 0xA00000 } );
   var cylinderMaterial = new THREE.MeshLambertMaterial( { color: 0x0000D0 } );
    //Create cap
   var cylinder;
    cylinder=new THREE.Mesh(new THREE.CylinderGeometry( 142/2, 142/2, 10, 32 ), cylinderMaterial);
    cylinder.position.x = 0;	
	cylinder.position.y = 160+390+40+5;	
	cylinder.position.z = 0;	
	scene.add( cylinder );
    
    cylinder=new THREE.Mesh(new THREE.CylinderGeometry( 80/2, 80/2, 70, 32 ), cylinderMaterial);
    cylinder.position.x = 0;	
	cylinder.position.y = 160+390+40+10+70/2;	
	cylinder.position.z = 0;	
	scene.add( cylinder );
}

function createDrinkingBird() {

	// MODELS
	// base + legs + feet
	createSupport();
	
	// body + body/head connector
	createBody();

	// head + hat
	createHead();
}

function fillScene() {
	// SCENE
	scene = new THREE.Scene();
	scene.fog = new THREE.Fog( 0x808080, 3000, 6000 );
	// 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( -400, 200, -300 );

	scene.add(ambientLight);
	scene.add(light);
	scene.add(light2);

	scene.add(camera);

	if (ground) {
		Coordinates.drawGround({size:1000});		
	}
	if (gridX) {
		Coordinates.drawGrid({size:1000,scale:0.01});
	}
	if (gridY) {
		Coordinates.drawGrid({size:1000,scale:0.01, orientation:"y"});
	}
	if (gridZ) {
		Coordinates.drawGrid({size:1000,scale:0.01, orientation:"z"});	
	}
	if (axes) {
		Coordinates.drawAllAxes({axisLength:300,axisRadius:2,axisTess:50});
	}
	createDrinkingBird();
}
//
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 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,

		dummy: function() {
		}
	};

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

init();
addToDOM();
setupGui();
animate();

运行效果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值