• No results found

When we discussed the ShapeGeometry, we mentioned that SVG and canvas follow pretty much the same approach to drawing shapes. SVG especially has a very close match with how Three.js handles shapes. In this section we'll look at how you can use a small library from https://github.com/asutherland/d3-threeD to convert SVG paths to a Three.js shape.

As an example, I've taken an SVG drawing of the Batman logo and used the ExtrudeGeometry to convert it to 3D. An example you can experiment with can be found in the sources for this chapter, 05-extrude-svg.html:

Chapter 6

[ 163 ]

First let's look at what the original SVG looks like (you can also see this for yourself when looking at the source code for this example):

<svg version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1152px" height="1152px" xml:space="preserve">

<g>

<path id="batman-path" style="fill:rgb(0,0,0);" d="M 261.135 114.535 C 254.906 116.662 247.491 118.825 244.659 119.344 C 229.433 122.131 177.907 142.565 151.973 156.101 C 111.417 177.269 78.9808 203.399 49.2992 238.815 C 41.0479 248.66 26.5057 277.248 21.0148 294.418 C 14.873 313.624 15.3588 357.341 21.9304 376.806 C 29.244 398.469 39.6107 416.935 52.0865 430.524 C 58.2431 437.23 63.3085 443.321 63.3431 444.06 ... 261.135 114.535 "/> </g> </svg>

Unless you're an SVG guru, this will probably mean nothing to you. Basically

though, what you see here, are a set of drawing instructions. For instance: C 277.987 119.348 279.673 116.786 279.673 115.867 tells the browser to draw a cubic Bezier curve and the L 489.242 111.787 tells us that we should draw a line on

that specific position. Luckily, though, we won't have to write the code to interpret

this ourselves. With the d3-threeD library, we can convert this automatically. This library was originally created for use together with the excellent D3.js library, but

with some small adaptions we can also use this specific functionality standalone.

SVG stands for Scalable Vector Graphics. This is an XML-based standard that can be used to create vector-based 2D images for the web. This is an open standard that is supported by all of the modern browsers. Directly working with SVG and manipulating it from JavaScript, however, isn't very straightforward. Luckily there are a couple of open source JavaScript libraries that make working with SVG a lot easier. D3.js and Raphael.js are two of the best. The following code fragment shows how you can load in the SVG you saw earlier convert it to an ExtrudeGeometry and show it on screen:

function drawShape() {

var svgString = $("#batman-path").attr("d"); var shape = transformSVGPathExposed(svgString); return shape;

}

var options = { amount: 10,

Using Advanced Geometries and Binary Operations [ 164 ] bevelThickness: 2, bevelSize: 1, bevelSegments: 3, bevelEnabled: true, curveSegments: 12, steps: 1 };

shape = createMesh(new THREE.ExtrudeGeometry(drawShape(), options));

In this code fragment you'll see a call to the transformSVGPathExposed function. This function is provided by the d3-ThreeD library and takes as argument an SVG string. We get this SVG string directly from the SVG element with the expression: $("#batman-path").attr("d"). In SVG the d attribute contains the path statements used to draw a shape. Add a nice-looking, shiny material, a spotlight and you've recreated this example.

The last geometry we'll discuss in this section is the ParametricGeometry. With this geometry, you can specify a couple of functions that are used to programmatically create geometries.

ParametricGeometry

With the ParametricGeometry you can create a geometry based on an equation. Before we dive into our own example, a good starting point is looking at the examples already provided by Three.js. When you download the Three.js

distribution you get the following file: examples/js/ParametricGeometries.js.

In this file you can find a couple of examples of equations you can use together with

the ParametricGeometry. The most basic example is the function to create a plane:

function plane(u, v) { var x = u * width;

var y = 0;

var z = v * depth;

return new THREE.Vector3(x, y, z); }

This function is called by the ParametricGeometry. The u and v values will range from 0 to 1 and will be called a large number of times for all the values from 0 to 1. In this example the u value is used to determine the x coordinate of the vector and the v value is used to determine the z coordinate. When this is run, you'll have a basic plane with a width of width and depth of depth.

Chapter 6

[ 165 ]

In our example we do something similar. But instead of creating a flat plane, we create

a wave-like pattern, as you can see in example 06-parametric-geometries.html:

To create this shape we've passed the following function into the ParametricGeometry:

radialWave = function (u, v) { var r = 50;

var x = Math.sin(u) * r;

var z = Math.sin(v / 2) * 2 * r; var y = (Math.sin(u * 4 * Math.PI) + Math.cos(v * 2 * Math.PI)) * 2.8;

return new THREE.Vector3(x, y, z); }

var mesh = createMesh(new THREE.ParametricGeometry(radialWave, 120, 120, false));

Using Advanced Geometries and Binary Operations

[ 166 ]

As you can see in this example, with a couple of lines of code, we can create really interesting geometries. In this example you can also see the arguments we can pass into the ParametricGeometry. These are explained in the following table:

Property Mandatory Description

function Yes The THREE.SplineCurve3 that describes the path this tube

should follow.

slices Yes Defines into how many parts the u value should be

divided.

stacks Yes Defines into how many parts the v value should be

divided.

useTris No Default is false. If set to true, the geometry will be created using triangle faces. If set to false quads will be used.

I'd like to make a final note on how to use the slices and stacks property, before moving on to the final part of this chapter. We mentioned that the u and v properties are passed into the provided function and that the values of these two properties range from 0 to 1. With the slices and stacks property we can define how often the

passed in function is called. If, for instance, we set slices to 5 and stacks to 4, the function will be called with the following values:

u:0/5, v:0/4 u:1/5, v:0/4 u:2/5, v:0/4 u:3/5, v:0/4 u:4/5, v:0/4 u:5/5, v:0/4 u:0/5, v:1/4 u:1/5, v:1/4 ... u:5/5, v:3/4 u:5/5, v:4/4

So the higher this value, the more vertices you get to specify, and the more smooth your created geometry will look.

For more examples you can look at examples/js/ParametricGeometries.js in the

Three.js distribution. This file contains functions to create the following geometries: • Klein bottle

• Plane

Chapter 6 [ 167 ] • 3d Mobius strip • Tube • Torus knot • Sphere

The last part of this chapter deals with creating 3D text objects.