diff --git a/README.md b/README.md index eed7d41..ccb16f5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ photon ====== -CSS 3D Lighting Engine \ No newline at end of file +CSS 3D Lighting Engine + +http://photon.attasi.com \ No newline at end of file diff --git a/css/.DS_Store b/css/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/css/.DS_Store differ diff --git a/css/base.css b/css/base.css new file mode 100644 index 0000000..b0dfa9c --- /dev/null +++ b/css/base.css @@ -0,0 +1,737 @@ +@charset "UTF-8"; +/* CSS Document */ + + +html, body, .scene { + height: 100%; + min-height: 600px; +} + +body { + font-family: 'museo-sans-1','museo-sans-2', sans-serif; + font-weight: 500; + font-size: 15px; + line-height: 22px; + color: #fff; + background: #000; + overflow-x: hidden; +} + +a { + text-decoration: none; +} + + + + + +/*--------------------------------- + + Primary Nav + +---------------------------------*/ + +.primary-menu { + position: fixed; + top: 30px; + left: 30px; + z-index: 9999; +} + +h1 { + margin-bottom: 3px; + font-weight: 900; + font-size: 26px; + color: #ff0; + text-transform: uppercase; +} + +h2 { + position: relative; + padding-bottom: 6px; + margin-bottom: 20px; + font-weight: 900; + text-transform: uppercase; +} + +h2:after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 50px; + height: 1px; + background: #fff; +} + +.primary-menu a { + display: block; + float: left; + clear: both; + color: #999; + -webkit-transition: color .2s; +} + +.primary-menu .download-btn { + margin-top: 20px; + padding: 3px 6px; + background: #ff0; + color: #000; + border-radius: 2px; +} + +.primary-menu .download-btn:hover { + color: #000; +} + +.primary-menu a:hover { + color: #fff; +} + +.primary-menu a.current { + color: #fff; +} + +.attasi { + position: fixed; + bottom: 30px; + left: 30px; + z-index: 9999; + font-size: 11px; + color: #fff; +} + +.attasi a { + color: #fff; +} + + + + + + + +/*--------------------------------- + + Light Toggle + +---------------------------------*/ + +.toggle { + position: absolute; + top: 50%; + left: 50%; + z-index: 9999; + margin-top: 200px; + margin-left: -115px; + width: 270px; + height: 70px; +} + +.toggle a { + display: block; + float: left; + color: #464646; + line-height: 70px; +} + +.toggle .label-on.current { + color: #ff0; +} + +.toggle .label-off.current { + color: #7f7f7f; +} + +.toggle-btn { + width: 70px; + height: 70px; + margin: 0 10px; + background: url(../images/toggle-button.png) no-repeat; + background-position: 0 0; + text-indent: 100%; + overflow: hidden; +} + +.toggle-btn.on { + background-position: 0 -70px; +} + + + + + + + +/*--------------------------------- + + Example Menu + +---------------------------------*/ + +.example-menu { + position: absolute; + top: 30px; + right: 30px; + z-index: 9999; +} + +.example-menu li { + float: left; + margin-left: 10px; +} + +.example-menu a { + display: block; + width: 132px; + height: 87px; + background: url(../images/example-thumbs.png) no-repeat rgba(0, 0, 0, .7); + text-indent: 100%; + overflow: hidden; + border: 1px solid #555; + -webkit-transition: border-color .2s; +} + +.example-menu a:hover { + border-color: #fff; +} + +.example-menu a.current { + background: url(../images/example-thumbs.png) no-repeat rgba(128, 128, 128, .4); + background-position-y: -87px; + border-color: #ff0; +} + +.example-menu a.current:hover { + border-color: #ff0; +} + +.example-menu a.crane-thumb { + background-position-x: 0; +} + +.example-menu a.coverflow-thumb { + background-position-x: -132px; +} + +.example-menu a.map-thumb { + background-position-x: -264px; +} + + + + + + + +/*--------------------------------- + + Scene + +---------------------------------*/ + +.scene { + position: absolute; + top: 0; + left: 0; + z-index: 0; + width: 100%; + height: 100%; + -webkit-perspective: 1000; + -webkit-transform-style: preserve-3d; +} + +.coverflow, +.map { + display: none; +} + + + + + + + + + + +/*--------------------------------- + + Crane + +---------------------------------*/ + +.crane { + position: absolute; + top: 50%; + left: 50%; + margin-top: 50px; + -webkit-transform-style: preserve-3d; + -webkit-transform: rotateX(-15deg) rotateY(-42deg); +} + + +.crane .face { + position: absolute; + background: url(../images/texture-2.png) #ff0; + /*background: #eee;*/ + /*background: #009ddc;*/ +} + + +.crane .wing-1a { + width: 132px; + height: 346px; + -webkit-mask: url(../images/crane/wing-a.svg) no-repeat; + -webkit-transform-origin: bottom right; + -webkit-transform: translate3d(-131px, -346px, -60px) rotateX(50deg) rotateY(10deg); +} + +.crane .wing-1b { + width: 132px; + height: 346px; + -webkit-mask: url(../images/crane/wing-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(0, -346px, -60px) rotateX(50deg) rotateY(-10deg); +} + +.crane .wing-1c { + width: 132px; + height: 105px; + -webkit-mask: url(../images/crane/wing-c.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-128px, -22px, -34px) rotateY(6deg) rotateX(9deg); +} + +.crane .wing-1d { + width: 132px; + height: 105px; + -webkit-mask: url(../images/crane/wing-d.svg) no-repeat; + -webkit-transform-origin: bottom right; + -webkit-transform: translate3d(-1px, -22px, -34px) rotateY(-6deg) rotateX(9deg); +} + +.crane .wing-2a { + width: 132px; + height: 346px; + -webkit-mask: url(../images/crane/wing-a.svg) no-repeat; + -webkit-transform-origin: bottom right; + -webkit-transform: translate3d(-131px, -346px, 60px) rotateX(-50deg) rotateY(-10deg); +} + +.crane .wing-2b { + width: 132px; + height: 346px; + -webkit-mask: url(../images/crane/wing-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(0, -346px, 60px) rotateX(-50deg) rotateY(10deg); +} + +.crane .wing-2c { + width: 132px; + height: 105px; + -webkit-mask: url(../images/crane/wing-c.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-128px, -22px, 34px) rotateY(-6deg) rotateX(-9deg); +} + +.crane .wing-2d { + width: 132px; + height: 105px; + -webkit-mask: url(../images/crane/wing-d.svg) no-repeat; + -webkit-transform-origin: bottom right; + -webkit-transform: translate3d(-1px, -22px, 34px) rotateY(6deg) rotateX(-9deg); +} + +.crane .body-1a { + width: 132px; + height: 246px; + -webkit-mask: url(../images/crane/body-a.svg) no-repeat; + -webkit-transform-origin: bottom right; + -webkit-transform: translate3d(-130px, -163px, 0) rotateY(15deg); +} + +.crane .body-1b { + width: 132px; + height: 246px; + -webkit-mask: url(../images/crane/body-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(0, -163px, 0) rotateY(-15deg); +} + +.crane .body-1c { + width: 132px; + height: 246px; + -webkit-mask: url(../images/crane/body-a.svg) no-repeat; + -webkit-transform-origin: bottom right; + -webkit-transform: translate3d(-130px, -163px, 0) rotateY(-15deg); +} + +.crane .body-1d { + width: 132px; + height: 246px; + -webkit-mask: url(../images/crane/body-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(0, -163px, 0) rotateY(15deg); +} + +.crane .neck-a { + width: 230px; + height: 277px; + -webkit-mask: url(../images/crane/neck-a.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-1px, -194px, 7px) rotateY(-12deg) rotateX(11deg); +} + +.crane .neck-b { + width: 230px; + height: 277px; + -webkit-mask: url(../images/crane/neck-a.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-1px, -194px, -7px) rotateY(12deg) rotateX(-11deg); +} + +.crane .head-a { + width: 95px; + height: 35px; + -webkit-mask: url(../images/crane/head-a.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(208px, -188px, -4px) rotateX(-8.5deg) rotateY(-2deg) rotateY(-1deg); +} + +.crane .head-b { + width: 95px; + height: 35px; + -webkit-mask: url(../images/crane/head-a.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(208px, -188px, 2px) rotateX(8.5deg) rotateY(1deg); +} + +.crane .tail-a { + width: 127px; + height: 397px; + -webkit-mask: url(../images/crane/tail-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-90px, -269px, 33px) rotateY(12.5deg) rotateX(9.45deg) rotateZ(-37deg); +} + +.crane .tail-b { + width: 127px; + height: 397px; + -webkit-mask: url(../images/crane/tail-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-90px, -269px, -34px) rotateY(-12.5deg) rotateX(-9.45deg) rotateZ(-37deg); +} + +.crane .base-a { + width: 172px; + height: 61px; + -webkit-mask: url(../images/crane/base-a.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-2px, -8px, 1px) rotateX(90deg) rotateY(12deg); +} + +.crane .base-b { + width: 172px; + height: 61px; + -webkit-mask: url(../images/crane/base-a.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-2px, -8px, -1px) rotateX(90deg) rotateY(12deg) rotateX(180deg); +} + +.crane .base-c { + width: 172px; + height: 61px; + -webkit-mask: url(../images/crane/base-a.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-2px, -8px, 1px) rotateX(90deg) rotateY(12deg) rotateY(180deg); +} + +.crane .base-d { + width: 172px; + height: 61px; + -webkit-mask: url(../images/crane/base-a.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-2px, -8px, 1px) rotateX(90deg) rotateY(12deg) rotateY(180deg) rotateX(180deg); +} + +.crane .base-e { + width: 22px; + height: 107px; + -webkit-mask: url(../images/crane/base-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(130px, -23px, 52px) rotateY(90deg) rotateX(5deg); +} + +.crane .base-f { + width: 22px; + height: 107px; + -webkit-mask: url(../images/crane/base-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(130px, -23px, -52px) rotateY(-90deg) rotateX(-5deg); +} + +.crane .base-g { + width: 22px; + height: 107px; + -webkit-mask: url(../images/crane/base-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-128px, -23px, 52px) rotateY(90deg) rotateX(-5deg); +} + +.crane .base-h { + width: 22px; + height: 107px; + -webkit-mask: url(../images/crane/base-b.svg) no-repeat; + -webkit-transform-origin: bottom left; + -webkit-transform: translate3d(-128px, -23px, -52px) rotateY(-90deg) rotateX(5deg); +} + + + + + + + + + +/*--------------------------------- + + Coverflow + +---------------------------------*/ + +.coverflow { + position: absolute; + top: 0; + left: 0; + z-index: 0; + width: 100%; + height: 100%; + -webkit-perspective: 1000; + -webkit-transform-style: preserve-3d; +} + +.coverflow li { + position: absolute; + left: 50%; + top: 50%; + z-index: 100; + width: 400px; + height: 400px; + margin-left: -200px; + margin-top: -250px; + -webkit-transition: -webkit-transform .4s; + pointer-events: none; +} + + + + + + + + + +/*--------------------------------- + + Map + +---------------------------------*/ + +.map { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform-style: preserve-3d; + -webkit-transform: rotateX(10deg) rotateY(30deg) rotateZ(0); +} + +.panel-1, +.panel-2, +.panel-3 { + position: absolute; + top: -230px; + width: 240px; + height: 400px; + background: url(../images/map-2.png) no-repeat; +} + +.panel-1 { + left: -360px; + background-position: 0 0; + -webkit-transform-origin: right; + -webkit-transform: rotateY(178deg); +} + +.map.is-open .panel-1 { + -webkit-transform: rotateY(60deg); +} + +.panel-2 { + left: -120px; + background-position: -240px 0; +} + +.panel-3 { + left: 120px; + background-position: -480px 0; + -webkit-transform-origin: left; + -webkit-transform: rotateY(178deg); +} + +.map.is-open .panel-3 { + -webkit-transform: rotateY(60deg); +} + + + + + + + + + + +/*--------------------------------- + + Docs + +---------------------------------*/ + +.docs-wrapper { + width: 600px; + margin: 30px 30px 30px 300px; + padding-bottom: 60px; +} + +.docs-wrapper > section { + margin-bottom: 88px; +} + +.docs-wrapper > section > section { + margin-bottom: 60px; +} + +h3 { + margin: 0 0 16px -20px; + font-weight: 900; + font-size: 25px; + color: #ff0; +} + +h4 { + margin: 24px 0 16px 0; + padding-bottom: 3px; + font-weight: 900; + font-size: 16px; + color: #fff; + text-transform: uppercase; + border-bottom: 2px solid #fff; +} + +pre { + margin: 16px 0; + padding: 10px; + border-radius: 2px; + background: #333; +} + +pre .comment { + color: #777; +} + +pre .var { + color: #8de3fc; +} + +pre .keyword { + color: #dd668d; +} + +pre .num, +pre .boolean { + color: #b370ff; +} + +pre .string { + color: #84d041; +} + +code { + padding: 1px 4px; + border-radius: 2px; + font-family: Monaco, monospace; + font-size: 14px; + color: #fff; + background: #333; +} + +pre code { + background: none; +} + +dt { + margin-bottom: 10px; +} + +dt code { + font-size: 15px; +} + +dt em { + font-size: 15px; + color: #666; +} + +dd { + margin-bottom: 48px; +} + +.library dt code { + background: #ff0; + color: #000; +} + +.property-list { + margin: 24px 0 0 48px; + font-size: 13px; +} + +.property-list dd { + margin: 0 0 24px 16px; + line-height: 18px; +} + +.property-list dt { + clear: both; + margin: 0 16px 0 0; +} + +.property-list dt em { + font-size: 13px; +} + +.property-list dt code { + margin-right: 3px; + background: #333; + font-size: 13px; + color: #ff0; +} + +.property-list dd code { + font-size: 13px; +} + + + + + + + + + + + + + diff --git a/css/reset.css b/css/reset.css new file mode 100644 index 0000000..a5c42b1 --- /dev/null +++ b/css/reset.css @@ -0,0 +1,49 @@ +@charset "UTF-8"; +/* CSS Document */ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} +/* remember to define focus styles! */ +:focus { + outline: 0; +} +body { + line-height: 1; + color: black; + background: white; +} +ol, ul { + list-style: none; +} +/* tables still need 'cellspacing="0"' in the markup */ +table { + border-collapse: separate; + border-spacing: 0; +} +caption, th, td { + text-align: left; + font-weight: normal; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; +} +blockquote, q { + quotes: "" ""; +} diff --git a/docs.html b/docs.html new file mode 100644 index 0000000..337506f --- /dev/null +++ b/docs.html @@ -0,0 +1,225 @@ + + + + + Photon | CSS 3D Lighting Engine + + + + + + + + + + + +
+ attasi.com
tom made this
+
+ +
+ +
+

Introduction

+ +

Photon is a JavaScript library that adds simple lighting effects to DOM elements in 3D space.

+ +

Requirements

+

WebKit is the only browser engine currently supported. Photon relies on the WebKitCSSMatrix object. At the time, no other browsers have an equivalent.

+
+ +
+

Quick Start

+ +
+

Create a Light

+

The Light object represents a point in 3D space from which faces are lit.

+
// creates a light at x: 0, y: 0, z: 100
+var light = new Photon.Light();
+
+ +
+

Define Faces

+

Face objects specify which DOM elements should be shaded or tinted by the light.

+ +
// create a face with a max shade of .5
+var face = new Photon.Face( $('.face-1') );
+
+ +
+

Render

+

Call the render method on your faces to shade or tint them based on their angle from the specified light.

+ +
// shade face by its relation to light
+face.render(light, true);
+
+
+ +
+

Library Reference

+ +
+

Light

+ +
+
Photon.Light( x = 0, y = 0, z = 100 )
constructor
+

Creates a new Light object. The default coordinates position the light straight towards the viewport.

+ +
moveTo( x, y, z )
method
+

Moves the light to a new set of coordinates.

+
+
+ +
+

Face

+ +
+
Photon.Face( element, maxShade = .5, maxTint = 0, isBackfaced = false )
constructor
+
+

Creates a new Face object. By default, the light will subtly shade each element.

+ +
+
element:jQuery Object
+
+

The DOM object to which shading should be applied.

+
+ +
maxShade:float
+
+

The maximum amount of black that can be added to an element: 0–1.

+
+ +
maxTint:float
+
+

The maximum amount of white that can be added to an element: 0–1.

+
+ +
isBackfaced:Boolean
+
+

Determines if the backface of the element should be shaded as if it were its own face. Rule of thumb: If the opposite side the element is visible, you probably want to set this to true.

+
+
+
+ +
render( light, getNewRotations, parentRotations )
method
+
+

Shades or tints the element based on its angle relative to the Light object. Shades and tints are applied to an empty div within the element with a class of photon-shader.

+ +
+
light :Light
+
The Light object to use to calculate shading or tinting.
+ +
getNewRotations :Boolean
+
If true, a new rotation vector is calculated before shading is applied. Use this when the element's transform property has changed.
+ +
parentRotations :Object
+
The parent object's rotations (x, y and z in radians). These are used primarily for FaceGroup objects.
+
+
+ +
setMaxShade( value )
method
+
+

Sets the maximum shade value: 0–1.

+ +
+
value :float
+
+
+ +
setMaxTint( value )
method
+
+

Sets the maximum tint value: 0–1.

+ +
+
value :float
+
+
+
+
+ +
+

FaceGroup

+
+
Photon.FaceGroup( parent, faces = parent.children(), maxShade = .5, maxTint = 0, isBackfaced = false )
constructor
+
+

Creates a new FaceGroup object, which allows one call of render to shade multiple faces. It also calculates the rotations of nested elements (i.e., if the parent element is rotated, the calculated rotations of the elements within it will be adjusted accordingly).

+ +
+
parent:jQuery Object
+
+

The DOM object containing the faces to be shaded. Note: this element, itself, will not be shaded.

+
+ +
faces:jQuery Object
+
+

The DOM elements to shade. Defaults to parent.children() but an explicit selector is recommended.

+
+ +
maxShade:float
+
+

The maximum amount of black that can be added to the faces: 0–1.

+
+ +
maxTint:float
+
+

The maximum amount of white that can be added to the faces: 0–1.

+
+ +
isBackfaced:Boolean
+
+

Determines if the backface of the faces should be shaded as if it were its own face. Rule of thumb: If the opposite side the element is visible, you probably want to set this to true.

+
+
+
+ +
render( light, getNewGroupRotations, getNewFaceRotations )
method
+
+

Shades or tints the element based on its angle relative to the Light object. Shades and tints are applied to an empty div within the element with a class of photon-shader.

+ +
+
light :Light
+
The Light object to use to calculate shading or tinting.
+ +
getNewGroupRotations :Boolean
+
If true, a new rotation vector is calculated for the parent element before shading is applied. The new vector will affect the rotations of all faces. Use this when the parent's transform property has changed.
+ +
getNewFaceRotations :Boolean
+
If true, new rotation vectors are calculated for all of the faces. Use this when the transform properties of thefaces have changed.
+
+
+ +
setMaxShade( value )
method
+
+

Sets the maximum shade value: 0–1.

+ +
+
value :float
+
+
+ +
setMaxTint( value )
method
+
+

Sets the maximum tint value: 0–1.

+ +
+
value :float
+
+
+
+
+ +
+
+ + + \ No newline at end of file diff --git a/images/.DS_Store b/images/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/images/.DS_Store differ diff --git a/images/attasi-logo.png b/images/attasi-logo.png new file mode 100644 index 0000000..4cd3efc Binary files /dev/null and b/images/attasi-logo.png differ diff --git a/images/black-left-panel.svg b/images/black-left-panel.svg new file mode 100644 index 0000000..5da2b6a --- /dev/null +++ b/images/black-left-panel.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/images/cover-1.png b/images/cover-1.png new file mode 100644 index 0000000..2deb8bd Binary files /dev/null and b/images/cover-1.png differ diff --git a/images/cover-2.png b/images/cover-2.png new file mode 100644 index 0000000..19b59b7 Binary files /dev/null and b/images/cover-2.png differ diff --git a/images/cover-3.png b/images/cover-3.png new file mode 100644 index 0000000..05dabdf Binary files /dev/null and b/images/cover-3.png differ diff --git a/images/cover-4.png b/images/cover-4.png new file mode 100644 index 0000000..ef20ea9 Binary files /dev/null and b/images/cover-4.png differ diff --git a/images/cover-5.png b/images/cover-5.png new file mode 100644 index 0000000..b5305b2 Binary files /dev/null and b/images/cover-5.png differ diff --git a/images/cover-6.png b/images/cover-6.png new file mode 100644 index 0000000..317eb62 Binary files /dev/null and b/images/cover-6.png differ diff --git a/images/crane/.DS_Store b/images/crane/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/images/crane/.DS_Store differ diff --git a/images/crane/base-a.svg b/images/crane/base-a.svg new file mode 100644 index 0000000..3ea0353 --- /dev/null +++ b/images/crane/base-a.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/images/crane/base-b.svg b/images/crane/base-b.svg new file mode 100644 index 0000000..323e60d --- /dev/null +++ b/images/crane/base-b.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/images/crane/body-a.svg b/images/crane/body-a.svg new file mode 100644 index 0000000..3414165 --- /dev/null +++ b/images/crane/body-a.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/images/crane/body-b.svg b/images/crane/body-b.svg new file mode 100644 index 0000000..199ce6b --- /dev/null +++ b/images/crane/body-b.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/images/crane/head-a.svg b/images/crane/head-a.svg new file mode 100644 index 0000000..216994b --- /dev/null +++ b/images/crane/head-a.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/images/crane/neck-a.svg b/images/crane/neck-a.svg new file mode 100644 index 0000000..cec3189 --- /dev/null +++ b/images/crane/neck-a.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/images/crane/tail-a.svg b/images/crane/tail-a.svg new file mode 100644 index 0000000..0a741e8 --- /dev/null +++ b/images/crane/tail-a.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/images/crane/tail-b.svg b/images/crane/tail-b.svg new file mode 100644 index 0000000..cc34a5b --- /dev/null +++ b/images/crane/tail-b.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/images/crane/wing-a.svg b/images/crane/wing-a.svg new file mode 100644 index 0000000..649d450 --- /dev/null +++ b/images/crane/wing-a.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/images/crane/wing-b.svg b/images/crane/wing-b.svg new file mode 100644 index 0000000..9a60ee2 --- /dev/null +++ b/images/crane/wing-b.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/images/crane/wing-c.svg b/images/crane/wing-c.svg new file mode 100644 index 0000000..f09a4a7 --- /dev/null +++ b/images/crane/wing-c.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/images/crane/wing-d.svg b/images/crane/wing-d.svg new file mode 100644 index 0000000..574434d --- /dev/null +++ b/images/crane/wing-d.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/images/example-thumbs.png b/images/example-thumbs.png new file mode 100644 index 0000000..885f110 Binary files /dev/null and b/images/example-thumbs.png differ diff --git a/images/map-2.png b/images/map-2.png new file mode 100644 index 0000000..34d257d Binary files /dev/null and b/images/map-2.png differ diff --git a/images/map.png b/images/map.png new file mode 100644 index 0000000..522106a Binary files /dev/null and b/images/map.png differ diff --git a/images/texture-2.png b/images/texture-2.png new file mode 100644 index 0000000..d5d5bcc Binary files /dev/null and b/images/texture-2.png differ diff --git a/images/texture.png b/images/texture.png new file mode 100644 index 0000000..df5e149 Binary files /dev/null and b/images/texture.png differ diff --git a/images/toggle-button.png b/images/toggle-button.png new file mode 100644 index 0000000..d3b61c4 Binary files /dev/null and b/images/toggle-button.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..d665c6b --- /dev/null +++ b/index.html @@ -0,0 +1,94 @@ + + + + + Photon | CSS 3D Lighting Engine + + + + + + + + + + + + +
+ attasi.com
tom made this
+
+ + + +
+ photon on + toggle + photon off +
+ +
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ + + +
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/js/.DS_Store b/js/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/js/.DS_Store differ diff --git a/js/base.js b/js/base.js new file mode 100644 index 0000000..78279b6 --- /dev/null +++ b/js/base.js @@ -0,0 +1,351 @@ +var $body, + $demos, + $crane, + $map, + $mapPanel1, + $mapPanel2, + $mapPanel3, + $coverflow, + $toggleBtn, + $toggleOn, + $toggleOff, + crane, + craneFaces, + cubeFaces, + map, + diamondFaces, + coverflowFaces, + shadeAmount, + tintAmount, + light, + currentCover, + renderTimer, + isLit; + + + + + + +$(document).ready(function() { + $body = $('body'), + $demos = $('.demo'), + light = new Photon.Light(), + shadeAmount = .5, + tintAmount = 0, + coverflowFaces = [], + cubeFaces = [], + diamondFaces = [], + currentCover = 0, + renderCurrent = renderCrane, + $toggleBtn = $('.toggle-btn'), + $toggleOn = $('.toggle .label-on'), + $toggleOff = $('.toggle .label-off'), + isLit = true; + + setupLightControls(); + setupCoverflow(); + setupCrane(); + setupMap(); + // showMap(); + showCrane(); + + // demo menu + $('.example-menu a').bind('click', onDemoNav); +}); + + + + + + + +/*--------------------------------- + + Light Controls + +---------------------------------*/ + +function setupLightControls() { + $('.toggle a').bind('click', toggleLight); +} + +function toggleLight(e) { + e.preventDefault(); + + switch($(e.target).attr('id')) { + case 'label-on': + isLit = true; + $toggleBtn.addClass('on'); + $toggleOn.addClass('current'); + $toggleOff.removeClass('current'); + $('.photon-shader').show(); + break; + case 'label-off': + isLit = false; + $toggleBtn.removeClass('on'); + $toggleOn.removeClass('current'); + $toggleOff.addClass('current'); + $('.photon-shader').hide(); + break; + case 'toggle-btn': + isLit = !isLit; + $toggleBtn.toggleClass('on'); + $toggleOn.toggleClass('current'); + $toggleOff.toggleClass('current'); + $('.photon-shader').toggle(); + break; + } +} + + + + + + + + +/*--------------------------------- + + Menus + +---------------------------------*/ + +function onDemoNav(e) { + e.preventDefault(); + + var demo = $(e.target).attr('data-demo'); + + $('.example-menu .current').removeClass('current'); + $(this).addClass('current'); + + switch(demo) { + case 'coverflow': + hideCrane(); + hideMap(); + showCoverflow(); + renderCurrent = renderCoverflow; + break; + case 'crane': + hideCoverflow(); + hideMap(); + showCrane(); + renderCurrent = renderCrane; + break; + case 'map': + hideCoverflow(); + hideCrane(); + showMap(); + renderCurrent = renderMap; + break; + } + + renderCurrent(); + if(!isLit) { + $('.photon-shader').hide(); + } +} + + + + + + + + + +/*--------------------------------- + + Crane + +---------------------------------*/ + +function setupCrane() { + $crane = $('.crane'); + // crane = new Photon.FaceGroup($('.crane'), $('.face'), .6, .1, true); + crane = new Photon.FaceGroup($('.crane')[0], $('.crane .face'), .6, .1, true); + renderCrane(); +} + +function renderCrane() { + crane.render(light, true); +} + +function showCrane() { + $body.bind('mousemove', rotateCrane); + $crane.show(); +} + +function hideCrane() { + $body.unbind('mousemove', rotateCrane); + $crane.hide(); +} + +function rotateCrane(e) { + var xPer = e.pageX / $body.width(); + + $(crane.element).css('-webkit-transform', 'rotateX(-15deg) rotateY(' + (-180 + (xPer * 360)) + 'deg)'); + renderCrane(); +} + + + + + + + + + +/*--------------------------------- + + Map + +---------------------------------*/ + +function setupMap() { + $map = $('.map'); + $mapPanel1 = $('.panel-1'); + $mapPanel2 = $('.panel-2'); + $mapPanel3 = $('.panel-3'); + $map.bind('click', toggleMap); + + map = new Photon.FaceGroup($('.map')[0], $('.map .face'), 1.5, .2, true); + renderMap(); +} + +function toggleMap() { + $map.toggleClass('is-open'); + + $map.unbind(); + $map.bind('webkitTransitionEnd', stopRenderTimer); + + if(!renderTimer) { + renderTimer = setInterval(renderMap, 34); + } +} + +function renderMap() { + map.render(light, true, true); +} + +function showMap() { + $body.bind('mousemove', rotateMap); + $map.show(); +} + +function hideMap() { + $body.unbind('mousemove', rotateMap); + $map.hide(); +} + +function rotateMap(e) { + var xPer = e.pageX / $body.width(); + var yPer = e.pageY / $body.height(); + + $mapPanel1.css('-webkit-transform', 'rotateY(' + (178 - (138 * xPer)) + 'deg)'); + $mapPanel3.css('-webkit-transform', 'rotateY(' + (178 - (138 * xPer)) + 'deg)'); + $map.css('-webkit-transform', 'rotateX(' + (40 - (yPer * 70)) + 'deg) rotateY(' + (20 - (xPer * 60)) + 'deg) rotateZ(0)'); + + renderMap(); +} + + + + + + + + + +/*--------------------------------- + + Coverflow + +---------------------------------*/ + +function setupCoverflow() { + $coverflow = $('.coverflow'); + var $coverflowItems = $coverflow.find('li'); + + $coverflowItems.each(function(i) { + coverflowFaces[i] = new Photon.Face($(this)[0], shadeAmount); + }); + + $coverflowItems.eq(1).bind('webkitTransitionEnd', stopRenderTimer); + + $coverflow.bind('click', changeCover); + + setCoverTransforms(); +} + +function changeCover() { + currentCover = currentCover < coverflowFaces.length - 1 ? currentCover + 1 : 0; + setCoverTransforms(true); +} + +function setCoverTransforms(animate) { + if(!renderTimer && animate) { + renderTimer = setInterval(renderCoverflow, 34); + } + for(var i = 0; i < coverflowFaces.length; i++) { + var element = coverflowFaces[i].element; + var offset = Math.abs(currentCover - i); + var x = i == currentCover ? 0 : (150 + (100 * offset)) * (i < currentCover ? -1 : 1); + var z = i == currentCover ? 0 : -200; + // var rotationY = i == currentCover ? 0 : 80 * (i < currentCover ? 1 : -1); + + var rotationY = i == currentCover ? 0 : (80 + (offset * -5)) * (i < currentCover ? 1 : -1); + + $(element).css('-webkit-transform', 'translateX(' + x +'px) translateZ(' + z + 'px) rotateY(' + rotationY + 'deg)'); + } +} + +function stopRenderTimer() { + if(renderTimer) { + clearInterval(renderTimer); + renderTimer = null; + } +} + +function renderCoverflow() { + console.log(coverflowFaces[1].rotations); + for(var i = 0; i < coverflowFaces.length; i++) { + coverflowFaces[i].render(light, true); + } +} + +function hideCoverflow() { + $coverflow.hide(); +} + +function showCoverflow() { + $coverflow.show(); +} + + + + + + + + + +/*--------------------------------- + + Utilities + +---------------------------------*/ + +function degToRad(deg) { + return deg * Math.PI / 180; +} + +function radToDeg(rad) { + return rad * 180 / Math.PI; +} + +function clamp(val, min, max) { + if(val > max) return max; + if(val < min) return min; + return val; +} diff --git a/js/jquery-1.7.1.min.js b/js/jquery-1.7.1.min.js new file mode 100755 index 0000000..198b3ff --- /dev/null +++ b/js/jquery-1.7.1.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.1 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
"+""+"
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; +f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() +{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/js/photon.js b/js/photon.js new file mode 100644 index 0000000..49e0808 --- /dev/null +++ b/js/photon.js @@ -0,0 +1,854 @@ +/* + * Photon + * http://photon.attasi.com + * + * Licensed under the MIT license. + * Copyright 2012 Tom Giannattasio + */ + + + +var Photon = { + version: '0.0.1', + + degToRad: function(deg) { + return deg * Math.PI / 180; + }, + + radToDeg: function(rad) { + return rad * 180 / Math.PI; + }, + + getRotationVector: function(originVector, rotations) { + var xVector = originVector.rotate(rotations.x, Line.create([0, 0, 0], [1, 0, 0])); + var yVector = xVector.rotate(rotations.y, Line.create([0, 0, 0], [0, 1, 0])); + var zVector = yVector.rotate(rotations.z, Line.create([0, 0, 0], [0, 0, 1])); + return zVector; + }, + + // converts transform matrix into a WebKitCSSMatrix object. + // multiplies values to avoid whackification + buildMatrix: function(faceTransform) { + var matrix = new WebKitCSSMatrix(faceTransform); + + matrix.m11 = matrix.m11 * 10000000000000000; + matrix.m12 = matrix.m12 * 10000000000000000; + matrix.m13 = matrix.m13 * 10000000000000000; + matrix.m14 = matrix.m14 * 10000000000000000; + + matrix.m21 = matrix.m21 * 10000000000000000; + matrix.m22 = matrix.m22 * 10000000000000000; + matrix.m23 = matrix.m23 * 10000000000000000; + matrix.m24 = matrix.m24 * 10000000000000000; + + matrix.m31 = matrix.m31 * 10000000000000000; + matrix.m32 = matrix.m32 * 10000000000000000; + matrix.m33 = matrix.m33 * 10000000000000000; + matrix.m34 = matrix.m34 * 10000000000000000; + + matrix.m41 = matrix.m41 * 10000000000000000; + matrix.m42 = matrix.m42 * 10000000000000000; + matrix.m43 = matrix.m43 * 10000000000000000; + matrix.m44 = matrix.m44 * 10000000000000000; + + return matrix; + } +}; + + + +Photon.Light = function(xVal, yVal, zVal) { + this.moveTo(xVal || 0, yVal || 0, zVal || 100); + this.calculateVector(); +} + +Photon.Light.prototype = { + moveTo: function(x, y, z) { + this.x = x; + this.y = y; + this.z = z; + this.calculateVector(); + }, + + // covert the light coordinates into a vector + calculateVector: function() { + this.magnitude = Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z)); + this.vector = $V([this.x / this.magnitude, this.y / this.magnitude, this.z / this.magnitude]); + } +} + + + +Photon.Face = function(element, maxShade, maxTint, isBackfaced) { + // set properties + this.element = element; + this.maxShade = maxShade || .5; + this.maxTint = maxTint || 0; + this.isBackfaced = isBackfaced || false; + + // create shader element + this.shaderElement = new Photon.ShaderElement(this.element); + this.element.insertBefore(this.shaderElement, this.element.firstChild); + + // calculate absolute rotations + this.getRotations(); +} + +Photon.Face.prototype = { + getRotations: function() { + // pull the transform property + var faceTransform = window.getComputedStyle(this.element).webkitTransform || 'matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)'; + + // convert the transform data into a matrix + this.matrix = Photon.buildMatrix(faceTransform); + + // extract the individual transform values + var faceDecomp = this.matrix.decompose(); + this.rotations = { + x: faceDecomp.rotate.x, + y: faceDecomp.rotate.y, + z: faceDecomp.rotate.z + }; + + // set the face's vector + this.vector = Photon.getRotationVector($V([0, 0, 1]), this.rotations); + }, + + render: function(light, getNewRotations, parentRotations) { + if(getNewRotations) { + this.getRotations(); + } + + // calculate the absolute vector + var fullVector; + if(parentRotations) { + fullVector = Photon.getRotationVector(this.vector, parentRotations); + } else { + fullVector = this.vector; + } + + // calculate the anglar distance from the light + this.angleFrom = radToDeg(light.vector.angleFrom(fullVector)); + + // determine the background color of the shader element + var background; + + // var anglePercentage = this.angleFrom / 180; + var anglePercentage = this.isBackfaced ? this.angleFrom / 180 : this.angleFrom / 90; + if(this.isBackfaced && anglePercentage > .5) { + anglePercentage = 1 - anglePercentage; + } + var range = Math.abs(this.maxShade + this.maxTint); + var rangedPercentage = range * anglePercentage; + this.rangedPercentage = rangedPercentage; + + // determine whether to shade or tint + if(rangedPercentage <= this.maxTint) { + background = 'rgba(255, 255, 255, ' + Math.abs(this.maxTint - rangedPercentage) + ')'; + } else { + background = 'rgba(0, 0, 0, ' + Math.abs(rangedPercentage - this.maxTint) + ')'; + } + + // apply the shading + this.shaderElement.style.background = background; + }, + + setMaxShade: function(value) { + this.maxShade = value; + }, + + setMaxTint: function(value) { + this.maxTint = value; + } +}; + + +// create the element to used for shading and tinting +Photon.ShaderElement = function(parent) { + var shaderElement = document.createElement('div'); + shaderElement.className = 'photon-shader'; + shaderElement.style.position = 'absolute'; + shaderElement.style.top = '0'; + shaderElement.style.left = '0'; + shaderElement.style.width = window.getComputedStyle(parent).width; + shaderElement.style.height = window.getComputedStyle(parent).height; + + return shaderElement; +} + + +// a group of faces within a single parent object +Photon.FaceGroup = function(parent, faces, maxShade, maxTint, isBackfaced) { + this.element = parent; + this.faces = []; + + var childFaces; + + if(faces) { + childFaces = faces; + } else { + childFaces = parent.children(); + } + + for(var i = 0; i < childFaces.length; i++) { + this.faces[i] = new Photon.Face(childFaces[i], maxShade, maxTint, isBackfaced); + } +} + +Photon.FaceGroup.prototype = { + getRotations: function() { + var faceTransform = window.getComputedStyle(this.element).webkitTransform || 'matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)'; + + this.matrix = Photon.buildMatrix(faceTransform); + var faceDecomp = this.matrix.decompose(); + + this.rotations = { + x: faceDecomp.rotate.x, + y: faceDecomp.rotate.y, + z: faceDecomp.rotate.z + }; + + this.vector = Photon.getRotationVector($V([0, 0, 1]), this.rotations); + }, + + render: function(light, getNewGroupRotations, getNewFaceRotations) { + if(getNewGroupRotations) { + this.getRotations(); + } + + this.angleFrom = radToDeg(light.vector.angleFrom(this.vector)); + + for(var i = 0, length = this.faces.length; i < length; i++) { + this.faces[i].render(light, getNewFaceRotations, this.rotations); + } + }, + + setMaxShade: function(value) { + for(var i = 0; i < this.faces.length; i++) { + this.faces[i].setMaxShade(value); + } + }, + + setMaxTint: function(value) { + for(var i = 0; i < this.faces.length; i++) { + this.faces[i].setMaxTint(value); + } + } +}; + + + + + + + + + + + + +// === Sylvester === +// Vector and Matrix mathematics modules for JavaScript +// Copyright (c) 2007 James Coglan +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + + +var Sylvester = { + version: '0.1.3', + precision: 1e-6 +}; + + + +function Vector() {} +Vector.prototype = { + + // Returns the modulus ('length') of the vector + modulus: function() { + return Math.sqrt(this.dot(this)); + }, + + // Returns a copy of the vector + dup: function() { + return Vector.create(this.elements); + }, + + // Calls the iterator for each element of the vector in turn + each: function(fn) { + var n = this.elements.length, k = n, i; + do { i = k - n; + fn(this.elements[i], i+1); + } while (--n); + }, + + // Returns the angle between the vector and the argument (also a vector) + angleFrom: function(vector) { + var V = vector.elements || vector; + var n = this.elements.length, k = n, i; + if (n != V.length) { return null; } + var dot = 0, mod1 = 0, mod2 = 0; + // Work things out in parallel to save time + this.each(function(x, i) { + dot += x * V[i-1]; + mod1 += x * x; + mod2 += V[i-1] * V[i-1]; + }); + mod1 = Math.sqrt(mod1); mod2 = Math.sqrt(mod2); + if (mod1*mod2 === 0) { return null; } + var theta = dot / (mod1*mod2); + if (theta < -1) { theta = -1; } + if (theta > 1) { theta = 1; } + return Math.acos(theta); + }, + + // Returns the scalar product of the vector with the argument + // Both vectors must have equal dimensionality + dot: function(vector) { + var V = vector.elements || vector; + var i, product = 0, n = this.elements.length; + if (n != V.length) { return null; } + do { product += this.elements[n-1] * V[n-1]; } while (--n); + return product; + }, + + // Rotates the vector about the given object. The object should be a + // point if the vector is 2D, and a line if it is 3D. Be careful with line directions! + rotate: function(t, obj) { + var V, R, x, y, z; + switch (this.elements.length) { + case 2: + V = obj.elements || obj; + if (V.length != 2) { return null; } + R = Matrix.Rotation(t).elements; + x = this.elements[0] - V[0]; + y = this.elements[1] - V[1]; + return Vector.create([ + V[0] + R[0][0] * x + R[0][1] * y, + V[1] + R[1][0] * x + R[1][1] * y + ]); + break; + case 3: + if (!obj.direction) { return null; } + var C = obj.pointClosestTo(this).elements; + R = Matrix.Rotation(t, obj.direction).elements; + x = this.elements[0] - C[0]; + y = this.elements[1] - C[1]; + z = this.elements[2] - C[2]; + return Vector.create([ + C[0] + R[0][0] * x + R[0][1] * y + R[0][2] * z, + C[1] + R[1][0] * x + R[1][1] * y + R[1][2] * z, + C[2] + R[2][0] * x + R[2][1] * y + R[2][2] * z + ]); + break; + default: + return null; + } + }, + + // Set vector's elements from an array + setElements: function(els) { + this.elements = (els.elements || els).slice(); + return this; + } +}; + +// Constructor function +Vector.create = function(elements) { + var V = new Vector(); + return V.setElements(elements); +}; + +var $V = Vector.create; + + + +function Line() {} +Line.prototype = { + + // Returns the line's perpendicular distance from the argument, + // which can be a point, a line or a plane + distanceFrom: function(obj) { + if (obj.normal) { return obj.distanceFrom(this); } + if (obj.direction) { + // obj is a line + if (this.isParallelTo(obj)) { return this.distanceFrom(obj.anchor); } + var N = this.direction.cross(obj.direction).toUnitVector().elements; + var A = this.anchor.elements, B = obj.anchor.elements; + return Math.abs((A[0] - B[0]) * N[0] + (A[1] - B[1]) * N[1] + (A[2] - B[2]) * N[2]); + } else { + // obj is a point + var P = obj.elements || obj; + var A = this.anchor.elements, D = this.direction.elements; + var PA1 = P[0] - A[0], PA2 = P[1] - A[1], PA3 = (P[2] || 0) - A[2]; + var modPA = Math.sqrt(PA1*PA1 + PA2*PA2 + PA3*PA3); + if (modPA === 0) return 0; + // Assumes direction vector is normalized + var cosTheta = (PA1 * D[0] + PA2 * D[1] + PA3 * D[2]) / modPA; + var sin2 = 1 - cosTheta*cosTheta; + return Math.abs(modPA * Math.sqrt(sin2 < 0 ? 0 : sin2)); + } + }, + + // Returns true iff the argument is a point on the line + contains: function(point) { + var dist = this.distanceFrom(point); + return (dist !== null && dist <= Sylvester.precision); + }, + + // Returns the point on the line that is closest to the given point or line + pointClosestTo: function(obj) { + if (obj.direction) { + // obj is a line + if (this.intersects(obj)) { return this.intersectionWith(obj); } + if (this.isParallelTo(obj)) { return null; } + var D = this.direction.elements, E = obj.direction.elements; + var D1 = D[0], D2 = D[1], D3 = D[2], E1 = E[0], E2 = E[1], E3 = E[2]; + // Create plane containing obj and the shared normal and intersect this with it + // Thank you: http://www.cgafaq.info/wiki/Line-line_distance + var x = (D3 * E1 - D1 * E3), y = (D1 * E2 - D2 * E1), z = (D2 * E3 - D3 * E2); + var N = Vector.create([x * E3 - y * E2, y * E1 - z * E3, z * E2 - x * E1]); + var P = Plane.create(obj.anchor, N); + return P.intersectionWith(this); + } else { + // obj is a point + var P = obj.elements || obj; + if (this.contains(P)) { return Vector.create(P); } + var A = this.anchor.elements, D = this.direction.elements; + var D1 = D[0], D2 = D[1], D3 = D[2], A1 = A[0], A2 = A[1], A3 = A[2]; + var x = D1 * (P[1]-A2) - D2 * (P[0]-A1), y = D2 * ((P[2] || 0) - A3) - D3 * (P[1]-A2), + z = D3 * (P[0]-A1) - D1 * ((P[2] || 0) - A3); + var V = Vector.create([D2 * x - D3 * z, D3 * y - D1 * x, D1 * z - D2 * y]); + var k = this.distanceFrom(P) / V.modulus(); + return Vector.create([ + P[0] + V.elements[0] * k, + P[1] + V.elements[1] * k, + (P[2] || 0) + V.elements[2] * k + ]); + } + }, + + // Returns a copy of the line rotated by t radians about the given line. Works by + // finding the argument's closest point to this line's anchor point (call this C) and + // rotating the anchor about C. Also rotates the line's direction about the argument's. + // Be careful with this - the rotation axis' direction affects the outcome! + rotate: function(t, line) { + // If we're working in 2D + if (typeof(line.direction) == 'undefined') { line = Line.create(line.to3D(), Vector.k); } + var R = Matrix.Rotation(t, line.direction).elements; + var C = line.pointClosestTo(this.anchor).elements; + var A = this.anchor.elements, D = this.direction.elements; + var C1 = C[0], C2 = C[1], C3 = C[2], A1 = A[0], A2 = A[1], A3 = A[2]; + var x = A1 - C1, y = A2 - C2, z = A3 - C3; + return Line.create([ + C1 + R[0][0] * x + R[0][1] * y + R[0][2] * z, + C2 + R[1][0] * x + R[1][1] * y + R[1][2] * z, + C3 + R[2][0] * x + R[2][1] * y + R[2][2] * z + ], [ + R[0][0] * D[0] + R[0][1] * D[1] + R[0][2] * D[2], + R[1][0] * D[0] + R[1][1] * D[1] + R[1][2] * D[2], + R[2][0] * D[0] + R[2][1] * D[1] + R[2][2] * D[2] + ]); + }, + + // Set the line's anchor point and direction. + setVectors: function(anchor, direction) { + // Need to do this so that line's properties are not + // references to the arguments passed in + anchor = Vector.create(anchor); + direction = Vector.create(direction); + if (anchor.elements.length == 2) {anchor.elements.push(0); } + if (direction.elements.length == 2) { direction.elements.push(0); } + if (anchor.elements.length > 3 || direction.elements.length > 3) { return null; } + var mod = direction.modulus(); + if (mod === 0) { return null; } + this.anchor = anchor; + this.direction = Vector.create([ + direction.elements[0] / mod, + direction.elements[1] / mod, + direction.elements[2] / mod + ]); + return this; + } +}; + +// Constructor function +Line.create = function(anchor, direction) { + var L = new Line(); + return L.setVectors(anchor, direction); +}; + + + +function Matrix() {} +Matrix.prototype = { + // Set the matrix's elements from an array. If the argument passed + // is a vector, the resulting matrix will be a single column. + setElements: function(els) { + var i, elements = els.elements || els; + if (typeof(elements[0][0]) != 'undefined') { + var ni = elements.length, ki = ni, nj, kj, j; + this.elements = []; + do { i = ki - ni; + nj = elements[i].length; kj = nj; + this.elements[i] = []; + do { j = kj - nj; + this.elements[i][j] = elements[i][j]; + } while (--nj); + } while(--ni); + return this; + } + var n = elements.length, k = n; + this.elements = []; + do { i = k - n; + this.elements.push([elements[i]]); + } while (--n); + return this; + } +}; + +// Constructor function +Matrix.create = function(elements) { + var M = new Matrix(); + return M.setElements(elements); +}; + +Matrix.Rotation = function(theta, a) { + if (!a) { + return Matrix.create([ + [Math.cos(theta), -Math.sin(theta)], + [Math.sin(theta), Math.cos(theta)] + ]); + } + var axis = a.dup(); + if (axis.elements.length != 3) { return null; } + var mod = axis.modulus(); + var x = axis.elements[0]/mod, y = axis.elements[1]/mod, z = axis.elements[2]/mod; + var s = Math.sin(theta), c = Math.cos(theta), t = 1 - c; + // Formula derived here: http://www.gamedev.net/reference/articles/article1199.asp + // That proof rotates the co-ordinate system so theta + // becomes -theta and sin becomes -sin here. + return Matrix.create([ + [ t*x*x + c, t*x*y - s*z, t*x*z + s*y ], + [ t*x*y + s*z, t*y*y + c, t*y*z - s*x ], + [ t*x*z - s*y, t*y*z + s*x, t*z*z + c ] + ]); +}; + + + + + + + + + + + + +/* + * @preserve Morf v0.1.5 + * http://www.joelambert.co.uk/morf + * + * Copyright 2011, Joe Lambert. + * Free to use under the MIT license. + * http://www.opensource.org/licenses/mit-license.php + */ + +var CSSMatrixDecomposed = function(obj) { + obj === undefined ? obj = {} : null; + var components = {perspective: null, translate: null, skew: null, scale: null, rotate: null}; + + for(var i in components) + this[i] = obj[i] ? obj[i] : new Vector4(); + + /** + * Tween between two decomposed matrices + * @param {CSSMatrixDecomposed} dm The destination decomposed matrix + * @param {float} progress A float value between 0-1, representing the percentage of completion + * @param {function} fn An easing function following the prototype function(pos){} + * @author Joe Lambert + * @returns {WebKitCSSMatrix} A new matrix for the tweened state + */ + + this.tween = function(dm, progress, fn) { + if(fn === undefined) + fn = function(pos) {return pos;}; // Default to a linear easing + + if(!dm) + dm = new CSSMatrixDecomposed(new WebKitCSSMatrix().decompose()); + + var r = new CSSMatrixDecomposed(), + i = index = null, + trans = ''; + + progress = fn(progress); + + for(index in components) + for(i in {x:'x', y:'y', z:'z', w:'w'}) + r[index][i] = (this[index][i] + (dm[index][i] - this[index][i]) * progress ).toFixed(5); + + trans = 'matrix3d(1,0,0,0, 0,1,0,0, 0,0,1,0, '+r.perspective.x+', '+r.perspective.y+', '+r.perspective.z+', '+r.perspective.w+') ' + + 'translate3d('+r.translate.x+'px, '+r.translate.y+'px, '+r.translate.y+'px) ' + + 'rotateX('+r.rotate.x+'rad) rotateY('+r.rotate.y+'rad) rotateZ('+r.rotate.z+'rad) ' + + 'matrix3d(1,0,0,0, 0,1,0,0, 0,'+r.skew.z+',1,0, 0,0,0,1) ' + + 'matrix3d(1,0,0,0, 0,1,0,0, '+r.skew.y+',0,1,0, 0,0,0,1) ' + + 'matrix3d(1,0,0,0, '+r.skew.x+',1,0,0, 0,0,1,0, 0,0,0,1) ' + + 'scale3d('+r.scale.x+', '+r.scale.y+', '+r.scale.z+')'; + + try { r = new WebKitCSSMatrix(trans); return r; } + catch(e) { console.error('Invalid matrix string: '+trans); return '' }; + }; +}; + +var Vector4 = function(x, y, z, w) +{ + this.x = x ? x : 0; + this.y = y ? y : 0; + this.z = z ? z : 0; + this.w = w ? w : 0; + + + /** + * Ensure that values are not undefined + * @author Joe Lambert + * @returns null + */ + + this.checkValues = function() { + this.x = this.x ? this.x : 0; + this.y = this.y ? this.y : 0; + this.z = this.z ? this.z : 0; + this.w = this.w ? this.w : 0; + }; + + + /** + * Get the length of the vector + * @author Joe Lambert + * @returns {float} + */ + + this.length = function() { + this.checkValues(); + return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); + }; + + + /** + * Get a normalised representation of the vector + * @author Joe Lambert + * @returns {Vector4} + */ + + this.normalise = function() { + var len = this.length(), + v = new Vector4(this.x / len, this.y / len, this.z / len); + + return v; + }; + + + /** + * Vector Dot-Product + * @param {Vector4} v The second vector to apply the product to + * @author Joe Lambert + * @returns {float} The Dot-Product of this and v. + */ + + this.dot = function(v) { + return this.x*v.x + this.y*v.y + this.z*v.z + this.w*v.w; + }; + + + /** + * Vector Cross-Product + * @param {Vector4} v The second vector to apply the product to + * @author Joe Lambert + * @returns {Vector4} The Cross-Product of this and v. + */ + + this.cross = function(v) { + return new Vector4(this.y*v.z - this.z*v.y, this.z*v.x - this.x*v.z, this.x*v.y - this.y*v.x); + }; + + + /** + * Helper function required for matrix decomposition + * A Javascript implementation of pseudo code available from http://www.w3.org/TR/css3-2d-transforms/#matrix-decomposition + * @param {Vector4} aPoint A 3D point + * @param {float} ascl + * @param {float} bscl + * @author Joe Lambert + * @returns {Vector4} + */ + + this.combine = function(aPoint, ascl, bscl) { + return new Vector4( (ascl * this.x) + (bscl * aPoint.x), + (ascl * this.y) + (bscl * aPoint.y), + (ascl * this.z) + (bscl * aPoint.z) ); + } +}; + +WebKitCSSMatrix.prototype.determinant = function() { + return this.m14 * this.m23 * this.m32 * this.m41-this.m13 * this.m24 * this.m32 * this.m41 - + this.m14 * this.m22 * this.m33 * this.m41+this.m12 * this.m24 * this.m33 * this.m41 + + this.m13 * this.m22 * this.m34 * this.m41-this.m12 * this.m23 * this.m34 * this.m41 - + this.m14 * this.m23 * this.m31 * this.m42+this.m13 * this.m24 * this.m31 * this.m42 + + this.m14 * this.m21 * this.m33 * this.m42-this.m11 * this.m24 * this.m33 * this.m42 - + this.m13 * this.m21 * this.m34 * this.m42+this.m11 * this.m23 * this.m34 * this.m42 + + this.m14 * this.m22 * this.m31 * this.m43-this.m12 * this.m24 * this.m31 * this.m43 - + this.m14 * this.m21 * this.m32 * this.m43+this.m11 * this.m24 * this.m32 * this.m43 + + this.m12 * this.m21 * this.m34 * this.m43-this.m11 * this.m22 * this.m34 * this.m43 - + this.m13 * this.m22 * this.m31 * this.m44+this.m12 * this.m23 * this.m31 * this.m44 + + this.m13 * this.m21 * this.m32 * this.m44-this.m11 * this.m23 * this.m32 * this.m44 - + this.m12 * this.m21 * this.m33 * this.m44+this.m11 * this.m22 * this.m33 * this.m44; +}; + +WebKitCSSMatrix.prototype.decompose = function() { + var matrix = new WebKitCSSMatrix(this.toString()), + perspectiveMatrix = rightHandSide = inversePerspectiveMatrix = transposedInversePerspectiveMatrix = + perspective = translate = row = i = scale = skew = pdum3 = rotate = null; + + if (matrix.m33 == 0) + return new CSSMatrixDecomposed(new WebKitCSSMatrix().decompose()); // Return the identity matrix + + // Normalize the matrix. + for (i = 1; i <= 4; i++) + for (j = 1; j <= 4; j++) + matrix['m'+i+j] /= matrix.m44; + + // perspectiveMatrix is used to solve for perspective, but it also provides + // an easy way to test for singularity of the upper 3x3 component. + perspectiveMatrix = matrix; + + for (i = 1; i <= 3; i++) + perspectiveMatrix['m'+i+'4'] = 0; + + perspectiveMatrix.m44 = 1; + + if (perspectiveMatrix.determinant() == 0) + return new CSSMatrixDecomposed(new WebKitCSSMatrix().decompose()); // Return the identity matrix + + // First, isolate perspective. + if (matrix.m14 != 0 || matrix.m24 != 0 || matrix.m34 != 0) + { + // rightHandSide is the right hand side of the equation. + rightHandSide = new Vector4(matrix.m14, matrix.m24, matrix.m34, matrix.m44); + + // Solve the equation by inverting perspectiveMatrix and multiplying + // rightHandSide by the inverse. + inversePerspectiveMatrix = perspectiveMatrix.inverse(); + transposedInversePerspectiveMatrix = inversePerspectiveMatrix.transpose(); + perspective = transposedInversePerspectiveMatrix.transformVector(rightHandSide); + + // Clear the perspective partition + matrix.m14 = matrix.m24 = matrix.m34 = 0; + matrix.m44 = 1; + } + else + { + // No perspective. + perspective = new Vector4(0,0,0,1); + } + + // Next take care of translation + translate = new Vector4(matrix.m41, matrix.m42, matrix.m43); + + matrix.m41 = 0; + matrix.m42 = 0; + matrix.m43 = 0; + + // Now get scale and shear. 'row' is a 3 element array of 3 component vectors + row = [ + new Vector4(), new Vector4(), new Vector4() + ]; + + for (i = 1; i <= 3; i++) + { + row[i-1].x = matrix['m'+i+'1']; + row[i-1].y = matrix['m'+i+'2']; + row[i-1].z = matrix['m'+i+'3']; + } + + // Compute X scale factor and normalize first row. + scale = new Vector4(); + skew = new Vector4(); + + scale.x = row[0].length(); + row[0] = row[0].normalise(); + + // Compute XY shear factor and make 2nd row orthogonal to 1st. + skew.x = row[0].dot(row[1]); + row[1] = row[1].combine(row[0], 1.0, -skew.x); + + // Now, compute Y scale and normalize 2nd row. + scale.y = row[1].length(); + row[1] = row[1].normalise(); + skew.x /= scale.y; + + // Compute XZ and YZ shears, orthogonalize 3rd row + skew.y = row[0].dot(row[2]); + row[2] = row[2].combine(row[0], 1.0, -skew.y); + skew.z = row[1].dot(row[2]); + row[2] = row[2].combine(row[1], 1.0, -skew.z); + + // Next, get Z scale and normalize 3rd row. + scale.z = row[2].length(); + row[2] = row[2].normalise(); + skew.y /= scale.z; + skew.y /= scale.z; + + // At this point, the matrix (in rows) is orthonormal. + // Check for a coordinate system flip. If the determinant + // is -1, then negate the matrix and the scaling factors. + pdum3 = row[1].cross(row[2]) + if (row[0].dot(pdum3) < 0) + { + for (i = 0; i < 3; i++) + { + scale.x *= -1; + row[i].x *= -1; + row[i].y *= -1; + row[i].z *= -1; + } + } + + // Now, get the rotations out + rotate = new Vector4(); + rotate.y = Math.asin(-row[0].z); + if (Math.cos(rotate.y) != 0) + { + rotate.x = Math.atan2(row[1].z, row[2].z); + rotate.z = Math.atan2(row[0].y, row[0].x); + } + else + { + rotate.x = Math.atan2(-row[2].x, row[1].y); + rotate.z = 0; + } + + return new CSSMatrixDecomposed({ + perspective: perspective, + translate: translate, + skew: skew, + scale: scale, + rotate: rotate + }); +}; \ No newline at end of file diff --git a/js/photon.min.js b/js/photon.min.js new file mode 100644 index 0000000..8c715a6 --- /dev/null +++ b/js/photon.min.js @@ -0,0 +1,9 @@ +/* + * Photon + * http://photon.attasi.com + * + * Licensed under the MIT license. + * Copyright 2012 Tom Giannattasio + */ + +var Photon={version:"0.0.1",degToRad:function(a){return a*Math.PI/180},radToDeg:function(a){return a*180/Math.PI},getRotationVector:function(b,a){var e=b.rotate(a.x,Line.create([0,0,0],[1,0,0]));var c=e.rotate(a.y,Line.create([0,0,0],[0,1,0]));var d=c.rotate(a.z,Line.create([0,0,0],[0,0,1]));return d},buildMatrix:function(b){var a=new WebKitCSSMatrix(b);a.m11=a.m11*10000000000000000;a.m12=a.m12*10000000000000000;a.m13=a.m13*10000000000000000;a.m14=a.m14*10000000000000000;a.m21=a.m21*10000000000000000;a.m22=a.m22*10000000000000000;a.m23=a.m23*10000000000000000;a.m24=a.m24*10000000000000000;a.m31=a.m31*10000000000000000;a.m32=a.m32*10000000000000000;a.m33=a.m33*10000000000000000;a.m34=a.m34*10000000000000000;a.m41=a.m41*10000000000000000;a.m42=a.m42*10000000000000000;a.m43=a.m43*10000000000000000;a.m44=a.m44*10000000000000000;return a}};Photon.Light=function(c,b,a){this.moveTo(c||0,b||0,a||100);this.calculateVector()};Photon.Light.prototype={moveTo:function(a,c,b){this.x=a;this.y=c;this.z=b;this.calculateVector()},calculateVector:function(){this.magnitude=Math.sqrt((this.x*this.x)+(this.y*this.y)+(this.z*this.z));this.vector=$V([this.x/this.magnitude,this.y/this.magnitude,this.z/this.magnitude])}};Photon.Face=function(d,b,a,c){this.element=d;this.maxShade=b||0.5;this.maxTint=a||0;this.isBackfaced=c||false;this.shaderElement=new Photon.ShaderElement(this.element);this.element.insertBefore(this.shaderElement,this.element.firstChild);this.getRotations()};Photon.Face.prototype={getRotations:function(){var b=window.getComputedStyle(this.element).webkitTransform||"matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)";this.matrix=Photon.buildMatrix(b);var a=this.matrix.decompose();this.rotations={x:a.rotate.x,y:a.rotate.y,z:a.rotate.z};this.vector=Photon.getRotationVector($V([0,0,1]),this.rotations)},render:function(b,h,g){if(h){this.getRotations()}var e;if(g){e=Photon.getRotationVector(this.vector,g)}else{e=this.vector}this.angleFrom=radToDeg(b.vector.angleFrom(e));var f;var d=this.isBackfaced?this.angleFrom/180:this.angleFrom/90;if(this.isBackfaced&&d>0.5){d=1-d}var c=Math.abs(this.maxShade+this.maxTint);var a=c*d;this.rangedPercentage=a;if(a<=this.maxTint){f="rgba(255, 255, 255, "+Math.abs(this.maxTint-a)+")"}else{f="rgba(0, 0, 0, "+Math.abs(a-this.maxTint)+")"}this.shaderElement.style.background=f},setMaxShade:function(a){this.maxShade=a},setMaxTint:function(a){this.maxTint=a}};Photon.ShaderElement=function(a){var b=document.createElement("div");b.className="photon-shader";b.style.position="absolute";b.style.top="0";b.style.left="0";b.style.width=window.getComputedStyle(a).width;b.style.height=window.getComputedStyle(a).height;return b};Photon.FaceGroup=function(f,a,c,b,d){this.element=f;this.faces=[];var g;if(a){g=a}else{g=f.children()}for(var e=0;e1){b=1}return Math.acos(b)},dot:function(b){var a=b.elements||b;var c,d=0,e=this.elements.length;if(e!=a.length){return null}do{d+=this.elements[e-1]*a[e-1]}while(--e);return d},rotate:function(c,e){var b,d,a,h,g;switch(this.elements.length){case 2:b=e.elements||e;if(b.length!=2){return null}d=Matrix.Rotation(c).elements;a=this.elements[0]-b[0];h=this.elements[1]-b[1];return Vector.create([b[0]+d[0][0]*a+d[0][1]*h,b[1]+d[1][0]*a+d[1][1]*h]);break;case 3:if(!e.direction){return null}var f=e.pointClosestTo(this).elements;d=Matrix.Rotation(c,e.direction).elements;a=this.elements[0]-f[0];h=this.elements[1]-f[1];g=this.elements[2]-f[2];return Vector.create([f[0]+d[0][0]*a+d[0][1]*h+d[0][2]*g,f[1]+d[1][0]*a+d[1][1]*h+d[1][2]*g,f[2]+d[2][0]*a+d[2][1]*h+d[2][2]*g]);break;default:return null}},setElements:function(a){this.elements=(a.elements||a).slice();return this}};Vector.create=function(b){var a=new Vector();return a.setElements(b)};var $V=Vector.create;function Line(){}Line.prototype={distanceFrom:function(e){if(e.normal){return e.distanceFrom(this)}if(e.direction){if(this.isParallelTo(e)){return this.distanceFrom(e.anchor)}var k=this.direction.cross(e.direction).toUnitVector().elements;var c=this.anchor.elements,b=e.anchor.elements;return Math.abs((c[0]-b[0])*k[0]+(c[1]-b[1])*k[1]+(c[2]-b[2])*k[2])}else{var f=e.elements||e;var c=this.anchor.elements,a=this.direction.elements;var n=f[0]-c[0],l=f[1]-c[1],g=(f[2]||0)-c[2];var m=Math.sqrt(n*n+l*l+g*g);if(m===0){return 0}var h=(n*a[0]+l*a[1]+g*a[2])/m;var d=1-h*h;return Math.abs(m*Math.sqrt(d<0?0:d))}},contains:function(a){var b=this.distanceFrom(a);return(b!==null&&b<=Sylvester.precision)},pointClosestTo:function(s){if(s.direction){if(this.intersects(s)){return this.intersectionWith(s)}if(this.isParallelTo(s)){return null}var u=this.direction.elements,t=s.direction.elements;var f=u[0],e=u[1],c=u[2],q=t[0],o=t[1],m=t[2];var r=(c*q-f*m),p=(f*o-e*q),n=(e*m-c*o);var l=Vector.create([r*m-p*o,p*q-n*m,n*o-r*q]);var h=Plane.create(s.anchor,l);return h.intersectionWith(this)}else{var h=s.elements||s;if(this.contains(h)){return Vector.create(h)}var v=this.anchor.elements,u=this.direction.elements;var f=u[0],e=u[1],c=u[2],d=v[0],b=v[1],a=v[2];var r=f*(h[1]-b)-e*(h[0]-d),p=e*((h[2]||0)-a)-c*(h[1]-b),n=c*(h[0]-d)-f*((h[2]||0)-a);var g=Vector.create([e*r-c*n,c*p-f*r,f*n-e*p]);var w=this.distanceFrom(h)/g.modulus();return Vector.create([h[0]+g.elements[0]*w,h[1]+g.elements[1]*w,(h[2]||0)+g.elements[2]*w])}},rotate:function(p,q){if(typeof(q.direction)=="undefined"){q=Line.create(q.to3D(),Vector.k)}var g=Matrix.Rotation(p,q.direction).elements;var b=q.pointClosestTo(this.anchor).elements;var d=this.anchor.elements,a=this.direction.elements;var l=b[0],k=b[1],h=b[2],f=d[0],e=d[1],c=d[2];var o=f-l,n=e-k,m=c-h;return Line.create([l+g[0][0]*o+g[0][1]*n+g[0][2]*m,k+g[1][0]*o+g[1][1]*n+g[1][2]*m,h+g[2][0]*o+g[2][1]*n+g[2][2]*m],[g[0][0]*a[0]+g[0][1]*a[1]+g[0][2]*a[2],g[1][0]*a[0]+g[1][1]*a[1]+g[1][2]*a[2],g[2][0]*a[0]+g[2][1]*a[1]+g[2][2]*a[2]])},setVectors:function(a,c){a=Vector.create(a);c=Vector.create(c);if(a.elements.length==2){a.elements.push(0)}if(c.elements.length==2){c.elements.push(0)}if(a.elements.length>3||c.elements.length>3){return null}var b=c.modulus();if(b===0){return null}this.anchor=a;this.direction=Vector.create([c.elements[0]/b,c.elements[1]/b,c.elements[2]/b]);return this}};Line.create=function(b,c){var a=new Line();return a.setVectors(b,c)};function Matrix(){}Matrix.prototype={setElements:function(h){var m,a=h.elements||h;if(typeof(a[0][0])!="undefined"){var d=a.length,f=d,b,c,l;this.elements=[];do{m=f-d;b=a[m].length;c=b;this.elements[m]=[];do{l=c-b;this.elements[m][l]=a[m][l]}while(--b)}while(--d);return this}var e=a.length,g=e;this.elements=[];do{m=g-e;this.elements.push([a[m]])}while(--e);return this}};Matrix.create=function(a){var b=new Matrix();return b.setElements(a)};Matrix.Rotation=function(b,k){if(!k){return Matrix.create([[Math.cos(b),-Math.sin(b)],[Math.sin(b),Math.cos(b)]])}var d=k.dup();if(d.elements.length!=3){return null}var h=d.modulus();var l=d.elements[0]/h,g=d.elements[1]/h,f=d.elements[2]/h;var n=Math.sin(b),e=Math.cos(b),m=1-e;return Matrix.create([[m*l*l+e,m*l*g-n*f,m*l*f+n*g],[m*l*g+n*f,m*g*g+e,m*g*f-n*l],[m*l*f-n*g,m*g*f+n*l,m*f*f+e]])};var CSSMatrixDecomposed=function(c){c===undefined?c={}:null;var b={perspective:null,translate:null,skew:null,scale:null,rotate:null};for(var a in b){this[a]=c[a]?c[a]:new Vector4()}this.tween=function(d,f,k){if(k===undefined){k=function(e){return e}}if(!d){d=new CSSMatrixDecomposed(new WebKitCSSMatrix().decompose())}var l=new CSSMatrixDecomposed(),h=index=null,g="";f=k(f);for(index in b){for(h in {x:"x",y:"y",z:"z",w:"w"}){l[index][h]=(this[index][h]+(d[index][h]-this[index][h])*f).toFixed(5)}}g="matrix3d(1,0,0,0, 0,1,0,0, 0,0,1,0, "+l.perspective.x+", "+l.perspective.y+", "+l.perspective.z+", "+l.perspective.w+") translate3d("+l.translate.x+"px, "+l.translate.y+"px, "+l.translate.y+"px) rotateX("+l.rotate.x+"rad) rotateY("+l.rotate.y+"rad) rotateZ("+l.rotate.z+"rad) matrix3d(1,0,0,0, 0,1,0,0, 0,"+l.skew.z+",1,0, 0,0,0,1) matrix3d(1,0,0,0, 0,1,0,0, "+l.skew.y+",0,1,0, 0,0,0,1) matrix3d(1,0,0,0, "+l.skew.x+",1,0,0, 0,0,1,0, 0,0,0,1) scale3d("+l.scale.x+", "+l.scale.y+", "+l.scale.z+")";try{l=new WebKitCSSMatrix(g);return l}catch(m){console.error("Invalid matrix string: "+g);return""}}};var Vector4=function(a,d,c,b){this.x=a?a:0;this.y=d?d:0;this.z=c?c:0;this.w=b?b:0;this.checkValues=function(){this.x=this.x?this.x:0;this.y=this.y?this.y:0;this.z=this.z?this.z:0;this.w=this.w?this.w:0};this.length=function(){this.checkValues();return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)};this.normalise=function(){var e=this.length(),f=new Vector4(this.x/e,this.y/e,this.z/e);return f};this.dot=function(e){return this.x*e.x+this.y*e.y+this.z*e.z+this.w*e.w};this.cross=function(e){return new Vector4(this.y*e.z-this.z*e.y,this.z*e.x-this.x*e.z,this.x*e.y-this.y*e.x)};this.combine=function(g,f,e){return new Vector4((f*this.x)+(e*g.x),(f*this.y)+(e*g.y),(f*this.z)+(e*g.z))}};WebKitCSSMatrix.prototype.determinant=function(){return this.m14*this.m23*this.m32*this.m41-this.m13*this.m24*this.m32*this.m41-this.m14*this.m22*this.m33*this.m41+this.m12*this.m24*this.m33*this.m41+this.m13*this.m22*this.m34*this.m41-this.m12*this.m23*this.m34*this.m41-this.m14*this.m23*this.m31*this.m42+this.m13*this.m24*this.m31*this.m42+this.m14*this.m21*this.m33*this.m42-this.m11*this.m24*this.m33*this.m42-this.m13*this.m21*this.m34*this.m42+this.m11*this.m23*this.m34*this.m42+this.m14*this.m22*this.m31*this.m43-this.m12*this.m24*this.m31*this.m43-this.m14*this.m21*this.m32*this.m43+this.m11*this.m24*this.m32*this.m43+this.m12*this.m21*this.m34*this.m43-this.m11*this.m22*this.m34*this.m43-this.m13*this.m22*this.m31*this.m44+this.m12*this.m23*this.m31*this.m44+this.m13*this.m21*this.m32*this.m44-this.m11*this.m23*this.m32*this.m44-this.m12*this.m21*this.m33*this.m44+this.m11*this.m22*this.m33*this.m44};WebKitCSSMatrix.prototype.decompose=function(){var a=new WebKitCSSMatrix(this.toString()),b=rightHandSide=inversePerspectiveMatrix=transposedInversePerspectiveMatrix=perspective=translate=row=i=scale=skew=pdum3=rotate=null;if(a.m33==0){return new CSSMatrixDecomposed(new WebKitCSSMatrix().decompose())}for(i=1;i<=4;i++){for(j=1;j<=4;j++){a["m"+i+j]/=a.m44}}b=a;for(i=1;i<=3;i++){b["m"+i+"4"]=0}b.m44=1;if(b.determinant()==0){return new CSSMatrixDecomposed(new WebKitCSSMatrix().decompose())}if(a.m14!=0||a.m24!=0||a.m34!=0){rightHandSide=new Vector4(a.m14,a.m24,a.m34,a.m44);inversePerspectiveMatrix=b.inverse();transposedInversePerspectiveMatrix=inversePerspectiveMatrix.transpose();perspective=transposedInversePerspectiveMatrix.transformVector(rightHandSide);a.m14=a.m24=a.m34=0;a.m44=1}else{perspective=new Vector4(0,0,0,1)}translate=new Vector4(a.m41,a.m42,a.m43);a.m41=0;a.m42=0;a.m43=0;row=[new Vector4(),new Vector4(),new Vector4()];for(i=1;i<=3;i++){row[i-1].x=a["m"+i+"1"];row[i-1].y=a["m"+i+"2"];row[i-1].z=a["m"+i+"3"]}scale=new Vector4();skew=new Vector4();scale.x=row[0].length();row[0]=row[0].normalise();skew.x=row[0].dot(row[1]);row[1]=row[1].combine(row[0],1,-skew.x);scale.y=row[1].length();row[1]=row[1].normalise();skew.x/=scale.y;skew.y=row[0].dot(row[2]);row[2]=row[2].combine(row[0],1,-skew.y);skew.z=row[1].dot(row[2]);row[2]=row[2].combine(row[1],1,-skew.z);scale.z=row[2].length();row[2]=row[2].normalise();skew.y/=scale.z;skew.y/=scale.z;pdum3=row[1].cross(row[2]);if(row[0].dot(pdum3)<0){for(i=0;i<3;i++){scale.x*=-1;row[i].x*=-1;row[i].y*=-1;row[i].z*=-1}}rotate=new Vector4();rotate.y=Math.asin(-row[0].z);if(Math.cos(rotate.y)!=0){rotate.x=Math.atan2(row[1].z,row[2].z);rotate.z=Math.atan2(row[0].y,row[0].x)}else{rotate.x=Math.atan2(-row[2].x,row[1].y);rotate.z=0}return new CSSMatrixDecomposed({perspective:perspective,translate:translate,skew:skew,scale:scale,rotate:rotate})}; \ No newline at end of file