├── Image2Surface.html ├── Image2Surface.manifest ├── Image2Surface.py ├── LICENSE.md ├── README.md ├── Resources ├── ConvertMeshToTSpline.png ├── ConvertMoonMeshToTSpline.png ├── CreateBaseFeature.png ├── Fusion360AddinsFolder.png ├── GitHubDownloadZIP.png ├── Image2SurfacePalette.png ├── MoonCAMToolpaths.png ├── MoonHeightmap.jpg ├── MoonMesh.png ├── MoonTSpline.png ├── ParametersDialog.png ├── Penny_CNC_Size_-_IMG_3813-sm.jpg ├── Penny_F360CAMAdaptive3D.jpg ├── Penny_F360CAMMorphedSpiral3D.jpg ├── ScriptsAndAdd-Ins.png ├── ShowImage2SurfacePalette.png ├── image2surface │ ├── .gitignore │ ├── 16x16-disabled.png │ ├── 16x16-disabled@2x.png │ ├── 16x16-pressed.png │ ├── 16x16-pressed@2x.png │ ├── 16x16.png │ ├── 16x16@2x.png │ ├── 32x32-disabled.png │ ├── 32x32-disabled@2x.png │ ├── 32x32-pressed.png │ ├── 32x32-pressed@2x.png │ ├── 32x32.png │ ├── 32x32@2x.png │ └── image2surface-tooltip.png └── samples │ ├── Grid 100x100.png │ ├── Hairy Dog.jpg │ ├── mona-lisa-twin.jpeg │ ├── moonsurfcontrast.jpg │ ├── penny_depthmap_500-sm.jpg │ └── penny_depthmap_500.jpg ├── css └── style.css └── js ├── DAT.GUI.min.js ├── Detector.js ├── RequestAnimationFrame.js ├── Stats.js ├── TrackballControls.js ├── Utils.js ├── image2surface.js ├── jquery.min.js ├── jquery.mousewheel.min.js ├── three.js └── three.min.js /Image2Surface.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Image 2 Surface 5 | 6 | 7 | 8 |
9 |
10 | Drop Image Here 11 |
12 |
13 |
14 |

Image 2 Surface

15 |

16 |

Load an image by Dragging & Dropping onto view. Or load from file:

17 | 18 |

19 |

Image Information

20 | 24 |

Surface Information

25 | 28 |

Generate a surface and send to Fusion 360:

29 | 30 |

Clear current image:

31 | 32 |

Help

33 | 39 |
https://github.com/hanskellner/Fusion360Image2Surface
40 |
41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 74 | -------------------------------------------------------------------------------- /Image2Surface.manifest: -------------------------------------------------------------------------------- 1 | { 2 | "autodeskProduct": "Fusion360", 3 | "type": "addin", 4 | "id": "8292ed75-c934-42d6-a7b3-65ac1c3a4102", 5 | "author": "Hans Kellner", 6 | "description": { 7 | "": "This is an Autodesk Fusion 360 script that's used for generating surfaces from images." 8 | }, 9 | "version": "2.0", 10 | "runOnStartup": false, 11 | "supportedOS": "windows|mac", 12 | "editEnabled": true 13 | } -------------------------------------------------------------------------------- /Image2Surface.py: -------------------------------------------------------------------------------- 1 | #Author-Hans Kellner 2 | #Description-This is an Autodesk Fusion 360 script that's used for generating surfaces from images. 3 | #Copyright (C) 2015-2018 Hans Kellner: https://github.com/hanskellner/Fusion360Image2Surface 4 | #MIT License: See https://github.com/hanskellner/Fusion360Image2Surface/LICENSE.md 5 | 6 | import adsk.core, adsk.fusion, adsk.cam, traceback 7 | import json, tempfile, platform 8 | 9 | # global set of event handlers to keep them referenced for the duration of the command 10 | handlers = [] 11 | _app = adsk.core.Application.cast(None) 12 | _ui = adsk.core.UserInterface.cast(None) 13 | 14 | # Event handler for the commandExecuted event. 15 | class ShowPaletteCommandExecuteHandler(adsk.core.CommandEventHandler): 16 | def __init__(self): 17 | super().__init__() 18 | def notify(self, args): 19 | try: 20 | 21 | global _app, _ui 22 | 23 | # Verify that in parametric design mode 24 | design = _app.activeProduct 25 | if design.designType != adsk.fusion.DesignTypes.ParametricDesignType: 26 | _ui.messageBox('The "Image2Surface" command must be run in parametric modeling mode.\n\nPlease enable "Capture design history" for your document.') 27 | return 28 | 29 | # Create and display the palette. 30 | palette = _ui.palettes.itemById('Image2SurfacePalette') 31 | if not palette: 32 | palette = _ui.palettes.add('Image2SurfacePalette', 'Image2Surface', 'image2surface.html', True, True, True, 1200, 800) 33 | 34 | # Float the palette. 35 | palette.dockingState = adsk.core.PaletteDockingStates.PaletteDockStateFloating 36 | 37 | # Add handler to HTMLEvent of the palette. 38 | onHTMLEvent = MyHTMLEventHandler() 39 | palette.incomingFromHTML.add(onHTMLEvent) 40 | handlers.append(onHTMLEvent) 41 | 42 | # Add handler to CloseEvent of the palette. 43 | onClosed = MyCloseEventHandler() 44 | palette.closed.add(onClosed) 45 | handlers.append(onClosed) 46 | else: 47 | palette.isVisible = True 48 | except: 49 | _ui.messageBox('Command executed failed: {}'.format(traceback.format_exc())) 50 | 51 | 52 | # Event handler for the commandCreated event. 53 | class ShowPaletteCommandCreatedHandler(adsk.core.CommandCreatedEventHandler): 54 | def __init__(self): 55 | super().__init__() 56 | def notify(self, args): 57 | try: 58 | command = args.command 59 | onExecute = ShowPaletteCommandExecuteHandler() 60 | command.execute.add(onExecute) 61 | handlers.append(onExecute) 62 | except: 63 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 64 | 65 | 66 | # Event handler for the commandExecuted event. 67 | class SendInfoCommandExecuteHandler(adsk.core.CommandEventHandler): 68 | def __init__(self): 69 | super().__init__() 70 | def notify(self, args): 71 | try: 72 | # Send information to the palette. This will trigger an event in the javascript 73 | # within the html so that it can be handled. 74 | palette = _ui.palettes.itemById('Image2SurfacePalette') 75 | if palette: 76 | palette.sendInfoToHTML('send', 'This is a message sent to the palette from Fusion.') 77 | except: 78 | _ui.messageBox('Command executed failed: {}'.format(traceback.format_exc())) 79 | 80 | 81 | # Event handler for the commandCreated event. 82 | class SendInfoCommandCreatedHandler(adsk.core.CommandCreatedEventHandler): 83 | def __init__(self): 84 | super().__init__() 85 | def notify(self, args): 86 | try: 87 | command = args.command 88 | onExecute = SendInfoCommandExecuteHandler() 89 | command.execute.add(onExecute) 90 | handlers.append(onExecute) 91 | except: 92 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 93 | 94 | 95 | # Event handler for the palette close event. 96 | class MyCloseEventHandler(adsk.core.UserInterfaceGeneralEventHandler): 97 | def __init__(self): 98 | super().__init__() 99 | def notify(self, args): 100 | try: 101 | # _ui.messageBox('Close button is clicked.') 102 | foo = 1 103 | if foo == 2: 104 | foo = 2 105 | except: 106 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 107 | 108 | 109 | # Event handler for the palette HTML event. 110 | class MyHTMLEventHandler(adsk.core.HTMLEventHandler): 111 | def __init__(self): 112 | super().__init__() 113 | def notify(self, args): 114 | try: 115 | htmlArgs = adsk.core.HTMLEventArgs.cast(args) 116 | data = json.loads(htmlArgs.data) 117 | 118 | objStr = data['obj'] 119 | objStrLen = len(data['obj']) 120 | 121 | if objStrLen > 0: 122 | 123 | fp = tempfile.NamedTemporaryFile(mode='w', suffix='.obj', delete=False) 124 | fp.writelines(objStr) 125 | fp.close() 126 | objFilePath = fp.name 127 | print ("Generated OBJ File: " + objFilePath) 128 | 129 | global _app 130 | 131 | # Get the current document, otherwise create a new one. 132 | doc = _app.activeDocument 133 | if not doc: 134 | doc = _app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) 135 | 136 | design = _app.activeProduct 137 | 138 | # Get the root component of the active design. 139 | rootComp = design.rootComponent 140 | 141 | # Need to place the mesh in a BaseFeature (non-parametric) 142 | baseFeats = rootComp.features.baseFeatures 143 | baseFeat = baseFeats.add() 144 | baseFeat.startEdit() 145 | 146 | # Add a mesh body by importing this data (OBJ) file. 147 | meshList = rootComp.meshBodies.add(objFilePath, adsk.fusion.MeshUnits.MillimeterMeshUnit, baseFeat) 148 | 149 | # Need to finish the base feature edit 150 | baseFeat.finishEdit() 151 | 152 | if meshList.count > 0: 153 | # Success - close palette 154 | palette = _ui.palettes.itemById('Image2SurfacePalette') 155 | if palette: 156 | palette.isVisible = False 157 | 158 | # HACK: bug causes mesh to be placed away from origin 159 | # therefore zoom to fit so mesh appears to user 160 | vp = _app.activeViewport 161 | vp.fit() 162 | else: 163 | _ui.messageBox('Failed to generate mesh body from file: {}'.format(objFilePath)) 164 | 165 | else: 166 | _ui.messageBox('Failed to generate mesh OBJ') 167 | 168 | except: 169 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 170 | 171 | 172 | def run(context): 173 | try: 174 | global _ui, _app 175 | _app = adsk.core.Application.get() 176 | _ui = _app.userInterface 177 | 178 | # Add a command that displays the panel. 179 | showPaletteCmdDef = _ui.commandDefinitions.itemById('showImage2SurfacePalette') 180 | if not showPaletteCmdDef: 181 | #strTooltip = '
Image 2 Surface
Use this add-in to convert an image into a surface (mesh).' 182 | showPaletteCmdDef = _ui.commandDefinitions.addButtonDefinition('showImage2SurfacePalette', 'Show Image 2 Surface', '', './/Resources//image2surface') 183 | showPaletteCmdDef.toolClipFilename = './/Resources//image2surface//image2surface-tooltip.png' 184 | 185 | # Connect to Command Created event. 186 | onCommandCreated = ShowPaletteCommandCreatedHandler() 187 | showPaletteCmdDef.commandCreated.add(onCommandCreated) 188 | handlers.append(onCommandCreated) 189 | 190 | # Add the command to the toolbar. 191 | panel = _ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel') 192 | cntrl = panel.controls.itemById('showImage2SurfacePalette') 193 | if not cntrl: 194 | panel.controls.addCommand(showPaletteCmdDef) 195 | 196 | if context['IsApplicationStartup'] is False: 197 | _ui.messageBox('The "Image2Surface" command has been added\nto the ADD-INS panel dropdown of the MODEL workspace.\n\nTo run the command, select the ADD-INS dropdown\nthen select "Show Image 2 Surface".') 198 | except: 199 | if _ui: 200 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 201 | 202 | 203 | def stop(context): 204 | try: 205 | # Delete the palette created by this add-in. 206 | palette = _ui.palettes.itemById('Image2SurfacePalette') 207 | if palette: 208 | palette.deleteMe() 209 | 210 | # Delete controls and associated command definitions created by this add-ins 211 | panel = _ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel') 212 | cmd = panel.controls.itemById('showImage2SurfacePalette') 213 | if cmd: 214 | cmd.deleteMe() 215 | cmdDef = _ui.commandDefinitions.itemById('showImage2SurfacePalette') 216 | if cmdDef: 217 | cmdDef.deleteMe() 218 | except: 219 | if _ui: 220 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (C) 2015-2018 Hans Kellner 2 | https://github.com/hanskellner/Fusion360Image2Surface 3 | 4 | Licensed under The MIT License 5 | http://en.wikipedia.org/wiki/MIT_License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![](./Resources/image2surface/32x32.png) Fusion 360 Image 2 Surface Add-In 2 | 3 | This is an [Autodesk Fusion 360](http://fusion360.autodesk.com/) add-in that's used for generating surfaces from images. 4 | 5 | ![Image2Surface](./Resources/image2surface/image2surface-tooltip.png) 6 | 7 | ## ![Moon - Height map](./Resources/MoonHeightmap.jpg) Moon Surface Example 8 | 9 | This surface was created from a small height map of a crater on Earth's moon. The first image is the mesh created from the script. The second is the T-Spline surface created from the mesh. 10 | 11 | ![Moon - Mesh generated from Image2Surface](./Resources/MoonMesh.png) 12 | 13 | ![Moon - T-Spline created from mesh](./Resources/MoonTSpline.png) 14 | 15 | ## ![Penny - Height map](./Resources/samples/penny_depthmap_500-sm.jpg) Milled Penny Example 16 | 17 | This is a penny that was milled out of a 4"x4" block of 6061 Aluminum. The surface was created from a height map of a penny. The mesh was then converted to a T-Spline then merged onto a cube. That model was brought into the CAM environment where the various milling operations were defined. Finally, it was milled on a Haas CNC vertical milling machine. 18 | 19 | ![Penny - Milled from 4"x4" block of 6061 Aluminum](./Resources/Penny_CNC_Size_-_IMG_3813-sm.jpg) 20 | 21 | ![Penny - Adaptive clearing of surface](./Resources/Penny_F360CAMAdaptive3D.jpg) 22 | 23 | ![Penny - Morphed spiral milling](./Resources/Penny_F360CAMMorphedSpiral3D.jpg) 24 | 25 | ## How to install a Fusion 360 Add-In 26 | 27 | Please see the most recent add-in install instructions here: 28 | 29 | https://knowledge.autodesk.com/support/fusion-360/troubleshooting/caas/sfdcarticles/sfdcarticles/How-to-install-an-ADD-IN-and-Script-in-Fusion-360.html 30 | 31 | Download the archive file (ZIP) from Github by clicking on the "Clone or download" button and then selecting "Download ZIP": 32 | 33 | ![Github Download ZIP](./Resources/GitHubDownloadZIP.png) 34 | 35 | Unarchive this file into the Addins folder and once created, rename the folder created from the Zip archive name "Fusion360Image2Surface-master.zip" to "Image2Surface": 36 | 37 | ![Fusion 360 Addins Folder](./Resources/Fusion360AddinsFolder.png) 38 | 39 | You will then be able to use the Fusion 360 Scripts and Addins Manager to add this folder, and thus the addin, to Fusion. Note, select the "Run on Startup" checkbox if you would like the add-in automatically started when Fusion 360 starts up. This is useful if you will be using the add-in often. 40 | 41 | The first time you run the Image2Surface add-in, it will add itself to the Add-ins panel dropdown of the Model environment. It should appear as an entry with the label "Show Image 2 Surface". 42 | 43 | ## Usage 44 | 45 | **Important: This add-in requires the document to be in parametric modeling mode (i.e. Capturing design history).** 46 | 47 | 1. Enter the Model environment 48 | 2. Run the Image2Surface add-in from the Scripts and Add-Ins Manager. Note, select the "Run on Startup" checkbox if you would like the add-in automatically started when Fusion 360 starts up and avoid having to manually run each time. 49 | 50 | ![Run Add-In](./Resources/ScriptsAndAdd-Ins.png) 51 | 52 | 3. Display the Image 2 Surface Palette. 53 | 54 | ![Display Image 2 Surface Palette](./Resources/ShowImage2SurfacePalette.png) 55 | 56 | - Click on the ADD-INS dropdown and then click on the "Image 2 Surface" menu item. This should display the palette. 57 | - If the menu item isn't there then there might have been a problem running the add-in. Go back to step 2 and try again. 58 | 59 | ![Image 2 Surface Palette](./Resources/Image2SurfacePalette.png) 60 | 61 | - This palette window contains a preview of the surface mesh that will be generated as well as controls for adjusting the mesh. 62 | 4. Select an image file 63 | - Drag and Drop an image file onto the palette window. It should be displaying the text "Drop Image Here". If not, click the "Clear Image" button. 64 | - *TODO: Alternatively, click the "Open Image File" button and then select the file in the fial dialog.* 65 | - WARNING: overly large images may cause problems (even crash the app). Please work with images under 1000x1000 at first. If you would like to try larger images, please save your work first in case loading the large image causes a crash. 66 | 5. Preview the surface mesh 67 | - If the image is loaded correctly, it we be converted to a prelimary mesh and displayed in the view. 68 | - Adjust View 69 | - Left mouse button to rotate the view 70 | - Middle mouse button to pan the view 71 | - Mousewheel to zoom in/out 72 | 6. Adjust the mesh parameters 73 | 74 | ![Image of Parameters](./Resources/ParametersDialog.png) 75 | 76 | - In the upper right of the view is small dialog containing parameters that control the mesh: 77 | - Pixels to Skip: 78 | - This is the number of pixels to skip over for each row and column on the source image 79 | - Stepover (mm): 80 | - This is the distance in millimeters between each mesh grid line. 81 | - Max Height (mm): 82 | - This is the max height in millimeters of each grid node. Each node's height is based on the color of the associate image pixel. Black maps to zero (0) and pure white to the "Max Height" value. Or the inverse if Invert checked. 83 | - Invert Heights: 84 | - If checked then black maps to "Max Height" and pure white to zero (0). 85 | - Smooth: 86 | - Apply a smoothing to the values to help reduce sharp ridges. 87 | - Absolute (B&W): 88 | - If checked then the height is based on the average of the pixel RGB value. Otherwise, it takes into account the human perceptual bias of the RGB individual values. 89 | 7. Generate a surface/mesh 90 | - When ready to generate a mesh within the active document, click the "Generate Surface" button. 91 | 92 | Once the mesh generated it will be added to the active drawing. You might have to "fit" the view to see it. 93 | 94 | If you have created a mesh then it's useful to convert it to a T-Spline or BREP for further modification. Note, Fusion has a limitation on the size of the mesh that can be converted to a BREP (around 10K faces). With a T-Spline or BREP surface it's possible to CNC or 3D print. 95 | 96 | - Convert the Mesh to a T-Spline 97 | 98 | 1. Click on the "Create Form" button on the toolbar to enter the "Sculpt" environment 99 | 2. Click on the "Utilities" button and then the "Convert" item to display the dialog: 100 | 101 | ![Convert Mesh Dialog](./Resources/ConvertMeshToTSpline.png) 102 | 103 | 3. In the dialog, select the "Quad Mesh to T-Spline" type 104 | 4. For the "Selection", select the mesh in the drawing then click OK 105 | 106 | - Convert the Mesh to a BREP 107 | 108 | 1. Enter the Model environment 109 | 2. Select the Create->Create a Base Feature item from the toolbar 110 | 3. Right-click/Ctrl-click on the mesh and in the context menu, select Mesh to BRep. 111 | 4. In the dialog displayed, the mesh should already be selected. Click OK. 112 | 113 | Here's the heightmap image of the moon's surface that was used to generate the mesh and t-spline shown at the top of the page. 114 | 115 | ![Moon Heightmap](./Resources/MoonHeightmap.jpg) 116 | 117 | And here's the t-spline in the CAM environment being used to create toolpaths for milling: 118 | 119 | ![Moon CAM Toolpaths](./Resources/MoonCAMToolpaths.png) 120 | 121 | More examples posted on my [Fusion 360 project gallery](https://fusion360.autodesk.com/users/hans-kellner). 122 | 123 | ## Trouble Shooting 124 | 125 | - Add-in fails to load. Verify that the add-in has been placed in its own folder within the Addins folder. If the files are not placed in their own folder then Fusion 360 will tend to fail loadin the add-in. 126 | - Large images can create large meshes which can cause Fusion 360 to take a very long time to process. Or the app may just fail. Try using a smaller resolution image. 127 | 128 | ## Issues 129 | 130 | - 2016.02 : Fusion 360 has a 10K limitation on mesh size when converting to a BREP. Any larger and it fails. 131 | -------------------------------------------------------------------------------- /Resources/ConvertMeshToTSpline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/ConvertMeshToTSpline.png -------------------------------------------------------------------------------- /Resources/ConvertMoonMeshToTSpline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/ConvertMoonMeshToTSpline.png -------------------------------------------------------------------------------- /Resources/CreateBaseFeature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/CreateBaseFeature.png -------------------------------------------------------------------------------- /Resources/Fusion360AddinsFolder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/Fusion360AddinsFolder.png -------------------------------------------------------------------------------- /Resources/GitHubDownloadZIP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/GitHubDownloadZIP.png -------------------------------------------------------------------------------- /Resources/Image2SurfacePalette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/Image2SurfacePalette.png -------------------------------------------------------------------------------- /Resources/MoonCAMToolpaths.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/MoonCAMToolpaths.png -------------------------------------------------------------------------------- /Resources/MoonHeightmap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/MoonHeightmap.jpg -------------------------------------------------------------------------------- /Resources/MoonMesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/MoonMesh.png -------------------------------------------------------------------------------- /Resources/MoonTSpline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/MoonTSpline.png -------------------------------------------------------------------------------- /Resources/ParametersDialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/ParametersDialog.png -------------------------------------------------------------------------------- /Resources/Penny_CNC_Size_-_IMG_3813-sm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/Penny_CNC_Size_-_IMG_3813-sm.jpg -------------------------------------------------------------------------------- /Resources/Penny_F360CAMAdaptive3D.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/Penny_F360CAMAdaptive3D.jpg -------------------------------------------------------------------------------- /Resources/Penny_F360CAMMorphedSpiral3D.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/Penny_F360CAMMorphedSpiral3D.jpg -------------------------------------------------------------------------------- /Resources/ScriptsAndAdd-Ins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/ScriptsAndAdd-Ins.png -------------------------------------------------------------------------------- /Resources/ShowImage2SurfacePalette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/ShowImage2SurfacePalette.png -------------------------------------------------------------------------------- /Resources/image2surface/.gitignore: -------------------------------------------------------------------------------- 1 | *.psd 2 | 3 | -------------------------------------------------------------------------------- /Resources/image2surface/16x16-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/16x16-disabled.png -------------------------------------------------------------------------------- /Resources/image2surface/16x16-disabled@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/16x16-disabled@2x.png -------------------------------------------------------------------------------- /Resources/image2surface/16x16-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/16x16-pressed.png -------------------------------------------------------------------------------- /Resources/image2surface/16x16-pressed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/16x16-pressed@2x.png -------------------------------------------------------------------------------- /Resources/image2surface/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/16x16.png -------------------------------------------------------------------------------- /Resources/image2surface/16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/16x16@2x.png -------------------------------------------------------------------------------- /Resources/image2surface/32x32-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/32x32-disabled.png -------------------------------------------------------------------------------- /Resources/image2surface/32x32-disabled@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/32x32-disabled@2x.png -------------------------------------------------------------------------------- /Resources/image2surface/32x32-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/32x32-pressed.png -------------------------------------------------------------------------------- /Resources/image2surface/32x32-pressed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/32x32-pressed@2x.png -------------------------------------------------------------------------------- /Resources/image2surface/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/32x32.png -------------------------------------------------------------------------------- /Resources/image2surface/32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/32x32@2x.png -------------------------------------------------------------------------------- /Resources/image2surface/image2surface-tooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/image2surface/image2surface-tooltip.png -------------------------------------------------------------------------------- /Resources/samples/Grid 100x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/samples/Grid 100x100.png -------------------------------------------------------------------------------- /Resources/samples/Hairy Dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/samples/Hairy Dog.jpg -------------------------------------------------------------------------------- /Resources/samples/mona-lisa-twin.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/samples/mona-lisa-twin.jpeg -------------------------------------------------------------------------------- /Resources/samples/moonsurfcontrast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/samples/moonsurfcontrast.jpg -------------------------------------------------------------------------------- /Resources/samples/penny_depthmap_500-sm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/samples/penny_depthmap_500-sm.jpg -------------------------------------------------------------------------------- /Resources/samples/penny_depthmap_500.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360Image2Surface/e54a567ce123b1365f6a253e9df91f54e561aea6/Resources/samples/penny_depthmap_500.jpg -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | height: 100%; 4 | background-color: rgb(102, 255, 0); 5 | margin: 0px; 6 | overflow: hidden; 7 | font-family: Helvetica Neue, Arial, sans-serif; 8 | font-size: 12px; 9 | line-height: 1.5em; 10 | color: #ccc; 11 | } 12 | a { 13 | color: #fff; 14 | text-decoration: none; 15 | } 16 | #controls { 17 | position: fixed; 18 | top: 10px; 19 | left: 10px; 20 | width: 250px; 21 | background-color:rgb(0, 32, 70); 22 | padding:10px; 23 | margin:0; 24 | border: 2px solid rgb(80, 80, 80, 0.5); 25 | border-radius: 4px; 26 | -moz-box-shadow: 0 0 15px rgba(0, 0, 0, .6); 27 | -webkit-box-shadow: 0 0 15px rgba(0, 0, 0, .6); 28 | box-shadow: 0 0 15px rgba(0, 0, 0, .6); 29 | } 30 | #content { 31 | height: 100%; 32 | width: 100%; 33 | background-color: rgb(0, 0, 0); 34 | -moz-box-shadow: 0 0 15px rgba(0, 0, 0, .6); 35 | -webkit-box-shadow: 0 0 15px rgba(0, 0, 0, .6); 36 | box-shadow: 0 0 15px rgba(0, 0, 0, .6); 37 | } 38 | #dropzone { 39 | position: fixed; 40 | display: none; 41 | width: 400; 42 | height: 200; 43 | top: 0; 44 | left: 0; 45 | right: 0; 46 | bottom: 0; 47 | background-color: rgb(0, 0, 0, 0.8); /* Black background with opacity */ 48 | } 49 | #dropzone span { 50 | position: absolute; 51 | top: 50%; 52 | left: 50%; 53 | font-size: 50px; 54 | color: white; 55 | transform: translate(-50%,-50%); 56 | -ms-transform: translate(-50%,-50%); 57 | font-family: Helvetica Neue, Arial, sans-serif; 58 | } 59 | -------------------------------------------------------------------------------- /js/DAT.GUI.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * dat-gui JavaScript Controller Library 3 | * http://code.google.com/p/dat-gui 4 | * 5 | * Copyright 2011 Data Arts Team, Google Creative Lab 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | */ 13 | var dat=dat||{};dat.gui=dat.gui||{};dat.utils=dat.utils||{};dat.controllers=dat.controllers||{};dat.dom=dat.dom||{};dat.color=dat.color||{};dat.utils.css=function(){return{load:function(e,a){var a=a||document,c=a.createElement("link");c.type="text/css";c.rel="stylesheet";c.href=e;a.getElementsByTagName("head")[0].appendChild(c)},inject:function(e,a){var a=a||document,c=document.createElement("style");c.type="text/css";c.innerHTML=e;a.getElementsByTagName("head")[0].appendChild(c)}}}(); 14 | dat.utils.common=function(){var e=Array.prototype.forEach,a=Array.prototype.slice;return{BREAK:{},extend:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(a[f])||(c[f]=a[f])},this);return c},defaults:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(c[f])&&(c[f]=a[f])},this);return c},compose:function(){var c=a.call(arguments);return function(){for(var d=a.call(arguments),f=c.length-1;f>=0;f--)d=[c[f].apply(this,d)];return d[0]}}, 15 | each:function(a,d,f){if(e&&a.forEach===e)a.forEach(d,f);else if(a.length===a.length+0)for(var b=0,n=a.length;b-1?d.length-d.indexOf(".")-1:0};c.superclass=e;a.extend(c.prototype,e.prototype,{setValue:function(a){if(this.__min!==void 0&&athis.__max)a=this.__max;this.__step!==void 0&&a%this.__step!=0&&(a=Math.round(a/this.__step)*this.__step);return c.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__step=a;return this}});return c}(dat.controllers.Controller,dat.utils.common); 29 | dat.controllers.NumberControllerBox=function(e,a,c){var d=function(f,b,e){function h(){var a=parseFloat(l.__input.value);c.isNaN(a)||l.setValue(a)}function j(a){var b=o-a.clientY;l.setValue(l.getValue()+b*l.__impliedStep);o=a.clientY}function m(){a.unbind(window,"mousemove",j);a.unbind(window,"mouseup",m)}this.__truncationSuspended=false;d.superclass.call(this,f,b,e);var l=this,o;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",h); 30 | a.bind(this.__input,"blur",function(){h();l.__onFinishChange&&l.__onFinishChange.call(l,l.getValue())});a.bind(this.__input,"mousedown",function(b){a.bind(window,"mousemove",j);a.bind(window,"mouseup",m);o=b.clientY});a.bind(this.__input,"keydown",function(a){if(a.keyCode===13)l.__truncationSuspended=true,this.blur(),l.__truncationSuspended=false});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype,e.prototype,{updateDisplay:function(){var a=this.__input, 31 | b;if(this.__truncationSuspended)b=this.getValue();else{b=this.getValue();var c=Math.pow(10,this.__precision);b=Math.round(b*c)/c}a.value=b;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common); 32 | dat.controllers.NumberControllerSlider=function(e,a,c,d,f){var b=function(d,c,f,e,l){function o(b){b.preventDefault();var d=a.getOffset(g.__background),c=a.getWidth(g.__background);g.setValue(g.__min+(g.__max-g.__min)*((b.clientX-d.left)/(d.left+c-d.left)));return false}function y(){a.unbind(window,"mousemove",o);a.unbind(window,"mouseup",y);g.__onFinishChange&&g.__onFinishChange.call(g,g.getValue())}b.superclass.call(this,d,c,{min:f,max:e,step:l});var g=this;this.__background=document.createElement("div"); 33 | this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(b){a.bind(window,"mousemove",o);a.bind(window,"mouseup",y);o(b)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};b.superclass=e;b.useDefaultStyles=function(){c.inject(f)};d.extend(b.prototype,e.prototype,{updateDisplay:function(){this.__foreground.style.width= 34 | (this.getValue()-this.__min)/(this.__max-this.__min)*100+"%";return b.superclass.prototype.updateDisplay.call(this)}});return b}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,".slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}"); 35 | dat.controllers.FunctionController=function(e,a,c){var d=function(c,b,e){d.superclass.call(this,c,b);var h=this;this.__button=document.createElement("div");this.__button.innerHTML=e===void 0?"Fire":e;a.bind(this.__button,"click",function(a){a.preventDefault();h.fire();return false});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};d.superclass=e;c.extend(d.prototype,e.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.__onFinishChange&&this.__onFinishChange.call(this, 36 | this.getValue());this.getValue().call(this.object)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); 37 | dat.controllers.BooleanController=function(e,a,c){var d=function(c,b){d.superclass.call(this,c,b);var e=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){e.setValue(!e.__prev)},false);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};d.superclass=e;c.extend(d.prototype,e.prototype,{setValue:function(a){a=d.superclass.prototype.setValue.call(this,a);this.__onFinishChange&& 38 | this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){this.getValue()===true?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=true):this.__checkbox.checked=false;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); 39 | dat.color.toString=function(e){return function(a){if(a.a==1||e.isUndefined(a.a)){for(a=a.hex.toString(16);a.length<6;)a="0"+a;return"#"+a}else return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common); 40 | dat.color.interpret=function(e,a){var c,d,f=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:e},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:e},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); 41 | return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:e},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:e}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return a.length!= 42 | 3?false:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return a.length!=4?false:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(b){return a.isNumber(b.r)&&a.isNumber(b.g)&&a.isNumber(b.b)&&a.isNumber(b.a)?{space:"RGB",r:b.r,g:b.g,b:b.b,a:b.a}:false},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(b){return a.isNumber(b.r)&& 43 | a.isNumber(b.g)&&a.isNumber(b.b)?{space:"RGB",r:b.r,g:b.g,b:b.b}:false},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)&&a.isNumber(b.a)?{space:"HSV",h:b.h,s:b.s,v:b.v,a:b.a}:false},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)?{space:"HSV",h:b.h,s:b.s,v:b.v}:false},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){d= 44 | false;var b=arguments.length>1?a.toArray(arguments):arguments[0];a.each(f,function(e){if(e.litmus(b))return a.each(e.conversions,function(e,f){c=e.read(b);if(d===false&&c!==false)return d=c,c.conversionName=f,c.conversion=e,a.BREAK}),a.BREAK});return d}}(dat.color.toString,dat.utils.common); 45 | dat.GUI=dat.gui.GUI=function(e,a,c,d,f,b,n,h,j,m,l,o,y,g,i){function q(a,b,r,c){if(b[r]===void 0)throw Error("Object "+b+' has no property "'+r+'"');c.color?b=new l(b,r):(b=[b,r].concat(c.factoryArgs),b=d.apply(a,b));if(c.before instanceof f)c.before=c.before.__li;t(a,b);g.addClass(b.domElement,"c");r=document.createElement("span");g.addClass(r,"property-name");r.innerHTML=b.property;var e=document.createElement("div");e.appendChild(r);e.appendChild(b.domElement);c=s(a,e,c.before);g.addClass(c,k.CLASS_CONTROLLER_ROW); 46 | g.addClass(c,typeof b.getValue());p(a,c,b);a.__controllers.push(b);return b}function s(a,b,d){var c=document.createElement("li");b&&c.appendChild(b);d?a.__ul.insertBefore(c,params.before):a.__ul.appendChild(c);a.onResize();return c}function p(a,d,c){c.__li=d;c.__gui=a;i.extend(c,{options:function(b){if(arguments.length>1)return c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[i.toArray(arguments)]});if(i.isArray(b)||i.isObject(b))return c.remove(),q(a,c.object,c.property, 47 | {before:c.__li.nextElementSibling,factoryArgs:[b]})},name:function(a){c.__li.firstElementChild.firstElementChild.innerHTML=a;return c},listen:function(){c.__gui.listen(c);return c},remove:function(){c.__gui.remove(c);return c}});if(c instanceof j){var e=new h(c.object,c.property,{min:c.__min,max:c.__max,step:c.__step});i.each(["updateDisplay","onChange","onFinishChange"],function(a){var b=c[a],H=e[a];c[a]=e[a]=function(){var a=Array.prototype.slice.call(arguments);b.apply(c,a);return H.apply(e,a)}}); 48 | g.addClass(d,"has-slider");c.domElement.insertBefore(e.domElement,c.domElement.firstElementChild)}else if(c instanceof h){var f=function(b){return i.isNumber(c.__min)&&i.isNumber(c.__max)?(c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[c.__min,c.__max,c.__step]})):b};c.min=i.compose(f,c.min);c.max=i.compose(f,c.max)}else if(c instanceof b)g.bind(d,"click",function(){g.fakeEvent(c.__checkbox,"click")}),g.bind(c.__checkbox,"click",function(a){a.stopPropagation()}); 49 | else if(c instanceof n)g.bind(d,"click",function(){g.fakeEvent(c.__button,"click")}),g.bind(d,"mouseover",function(){g.addClass(c.__button,"hover")}),g.bind(d,"mouseout",function(){g.removeClass(c.__button,"hover")});else if(c instanceof l)g.addClass(d,"color"),c.updateDisplay=i.compose(function(a){d.style.borderLeftColor=c.__color.toString();return a},c.updateDisplay),c.updateDisplay();c.setValue=i.compose(function(b){a.getRoot().__preset_select&&c.isModified()&&B(a.getRoot(),true);return b},c.setValue)} 50 | function t(a,b){var c=a.getRoot(),d=c.__rememberedObjects.indexOf(b.object);if(d!=-1){var e=c.__rememberedObjectIndecesToControllers[d];e===void 0&&(e={},c.__rememberedObjectIndecesToControllers[d]=e);e[b.property]=b;if(c.load&&c.load.remembered){c=c.load.remembered;if(c[a.preset])c=c[a.preset];else if(c[w])c=c[w];else return;if(c[d]&&c[d][b.property]!==void 0)d=c[d][b.property],b.initialValue=d,b.setValue(d)}}}function I(a){var b=a.__save_row=document.createElement("li");g.addClass(a.domElement, 51 | "has-save");a.__ul.insertBefore(b,a.__ul.firstChild);g.addClass(b,"save-row");var c=document.createElement("span");c.innerHTML=" ";g.addClass(c,"button gears");var d=document.createElement("span");d.innerHTML="Save";g.addClass(d,"button");g.addClass(d,"save");var e=document.createElement("span");e.innerHTML="New";g.addClass(e,"button");g.addClass(e,"save-as");var f=document.createElement("span");f.innerHTML="Revert";g.addClass(f,"button");g.addClass(f,"revert");var m=a.__preset_select=document.createElement("select"); 52 | a.load&&a.load.remembered?i.each(a.load.remembered,function(b,c){C(a,c,c==a.preset)}):C(a,w,false);g.bind(m,"change",function(){for(var b=0;b0){a.preset=this.preset;if(!a.remembered)a.remembered={};a.remembered[this.preset]=z(this)}a.folders={};i.each(this.__folders,function(b, 69 | c){a.folders[c]=b.getSaveObject()});return a},save:function(){if(!this.load.remembered)this.load.remembered={};this.load.remembered[this.preset]=z(this);B(this,false)},saveAs:function(a){if(!this.load.remembered)this.load.remembered={},this.load.remembered[w]=z(this,true);this.load.remembered[a]=z(this);this.preset=a;C(this,a,true)},revert:function(a){i.each(this.__controllers,function(b){this.getRoot().load.remembered?t(a||this.getRoot(),b):b.setValue(b.initialValue)},this);i.each(this.__folders, 70 | function(a){a.revert(a)});a||B(this.getRoot(),false)},listen:function(a){var b=this.__listening.length==0;this.__listening.push(a);b&&E(this.__listening)}});return k}(dat.utils.css,'
\n\n Here\'s the new load parameter for your GUI\'s constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
\n \n
\n\n
', 71 | ".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear;border:0;position:absolute;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-x:hidden}.dg.a.has-save ul{margin-top:27px}.dg.a.has-save ul.closed{margin-top:0}.dg.a .save-row{position:fixed;top:0;z-index:1002}.dg li{-webkit-transition:height 0.1s ease-out;-o-transition:height 0.1s ease-out;-moz-transition:height 0.1s ease-out;transition:height 0.1s ease-out}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;overflow:hidden;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li > *{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:9px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2fa1d6}.dg .cr.number input[type=text]{color:#2fa1d6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2fa1d6}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n", 72 | dat.controllers.factory=function(e,a,c,d,f,b,n){return function(h,j,m,l){var o=h[j];if(n.isArray(m)||n.isObject(m))return new e(h,j,m);if(n.isNumber(o))return n.isNumber(m)&&n.isNumber(l)?new c(h,j,m,l):new a(h,j,{min:m,max:l});if(n.isString(o))return new d(h,j);if(n.isFunction(o))return new f(h,j,"");if(n.isBoolean(o))return new b(h,j)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(e,a,c){var d= 73 | function(c,b){function e(){h.setValue(h.__input.value)}d.superclass.call(this,c,b);var h=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",e);a.bind(this.__input,"change",e);a.bind(this.__input,"blur",function(){h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())});a.bind(this.__input,"keydown",function(a){a.keyCode===13&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype, 74 | e.prototype,{updateDisplay:function(){if(!a.isActive(this.__input))this.__input.value=this.getValue();return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController, 75 | dat.controllers.ColorController=function(e,a,c,d,f){function b(a,b,c,d){a.style.background="";f.each(j,function(e){a.style.cssText+="background: "+e+"linear-gradient("+b+", "+c+" 0%, "+d+" 100%); "})}function n(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"; 76 | a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var h=function(e,l){function o(b){q(b);a.bind(window,"mousemove",q);a.bind(window, 77 | "mouseup",j)}function j(){a.unbind(window,"mousemove",q);a.unbind(window,"mouseup",j)}function g(){var a=d(this.value);a!==false?(p.__color.__state=a,p.setValue(p.__color.toOriginal())):this.value=p.__color.toString()}function i(){a.unbind(window,"mousemove",s);a.unbind(window,"mouseup",i)}function q(b){b.preventDefault();var c=a.getWidth(p.__saturation_field),d=a.getOffset(p.__saturation_field),e=(b.clientX-d.left+document.body.scrollLeft)/c,b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b= 78 | 1:b<0&&(b=0);e>1?e=1:e<0&&(e=0);p.__color.v=b;p.__color.s=e;p.setValue(p.__color.toOriginal());return false}function s(b){b.preventDefault();var c=a.getHeight(p.__hue_field),d=a.getOffset(p.__hue_field),b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b=1:b<0&&(b=0);p.__color.h=b*360;p.setValue(p.__color.toOriginal());return false}h.superclass.call(this,e,l);this.__color=new c(this.getValue());this.__temp=new c(0);var p=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement, 79 | false);this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input= 80 | document.createElement("input");this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){a.keyCode===13&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(){a.addClass(this,"drag").bind(window,"mouseup",function(){a.removeClass(p.__selector,"drag")})});var t=document.createElement("div");f.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"}); 81 | f.extend(this.__field_knob.style,{position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(this.__color.v<0.5?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});f.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});f.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});f.extend(t.style, 82 | {width:"100%",height:"100%",background:"none"});b(t,"top","rgba(0,0,0,0)","#000");f.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});n(this.__hue_field);f.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",o);a.bind(this.__field_knob,"mousedown",o);a.bind(this.__hue_field,"mousedown", 83 | function(b){s(b);a.bind(window,"mousemove",s);a.bind(window,"mouseup",i)});this.__saturation_field.appendChild(t);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};h.superclass=e;f.extend(h.prototype,e.prototype,{updateDisplay:function(){var a=d(this.getValue()); 84 | if(a!==false){var e=false;f.each(c.COMPONENTS,function(b){if(!f.isUndefined(a[b])&&!f.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return e=true,{}},this);e&&f.extend(this.__color.__state,a)}f.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var h=this.__color.v<0.5||this.__color.s>0.5?255:0,j=255-h;f.extend(this.__field_knob.style,{marginLeft:100*this.__color.s-7+"px",marginTop:100*(1-this.__color.v)-7+"px",backgroundColor:this.__temp.toString(),border:this.__field_knob_border+ 85 | "rgb("+h+","+h+","+h+")"});this.__hue_knob.style.marginTop=(1-this.__color.h/360)*100+"px";this.__temp.s=1;this.__temp.v=1;b(this.__saturation_field,"left","#fff",this.__temp.toString());f.extend(this.__input.style,{backgroundColor:this.__input.value=this.__color.toString(),color:"rgb("+h+","+h+","+h+")",textShadow:this.__input_textShadow+"rgba("+j+","+j+","+j+",.7)"})}});var j=["-moz-","-o-","-webkit-","-ms-",""];return h}(dat.controllers.Controller,dat.dom.dom,dat.color.Color=function(e,a,c,d){function f(a, 86 | b,c){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="RGB")return this.__state[b];n(this,b,c);return this.__state[b]},set:function(a){if(this.__state.space!=="RGB")n(this,b,c),this.__state.space="RGB";this.__state[b]=a}})}function b(a,b){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="HSV")return this.__state[b];h(this);return this.__state[b]},set:function(a){if(this.__state.space!=="HSV")h(this),this.__state.space="HSV";this.__state[b]=a}})}function n(b,c,e){if(b.__state.space=== 87 | "HEX")b.__state[c]=a.component_from_hex(b.__state.hex,e);else if(b.__state.space==="HSV")d.extend(b.__state,a.hsv_to_rgb(b.__state.h,b.__state.s,b.__state.v));else throw"Corrupted color state";}function h(b){var c=a.rgb_to_hsv(b.r,b.g,b.b);d.extend(b.__state,{s:c.s,v:c.v});if(d.isNaN(c.h)){if(d.isUndefined(b.__state.h))b.__state.h=0}else b.__state.h=c.h}var j=function(){this.__state=e.apply(this,arguments);if(this.__state===false)throw"Failed to interpret color arguments";this.__state.a=this.__state.a|| 88 | 1};j.COMPONENTS="r,g,b,h,s,v,hex,a".split(",");d.extend(j.prototype,{toString:function(){return c(this)},toOriginal:function(){return this.__state.conversion.write(this)}});f(j.prototype,"r",2);f(j.prototype,"g",1);f(j.prototype,"b",0);b(j.prototype,"h");b(j.prototype,"s");b(j.prototype,"v");Object.defineProperty(j.prototype,"a",{get:function(){return this.__state.a},set:function(a){this.__state.a=a}});Object.defineProperty(j.prototype,"hex",{get:function(){if(!this.__state.space!=="HEX")this.__state.hex= 89 | a.rgb_to_hex(this.r,this.g,this.b);return this.__state.hex},set:function(a){this.__state.space="HEX";this.__state.hex=a}});return j}(dat.color.interpret,dat.color.math=function(){var e;return{hsv_to_rgb:function(a,c,d){var e=a/60-Math.floor(a/60),b=d*(1-c),n=d*(1-e*c),c=d*(1-(1-e)*c),a=[[d,c,b],[n,d,b],[b,d,c],[b,n,d],[c,b,d],[d,b,n]][Math.floor(a/60)%6];return{r:a[0]*255,g:a[1]*255,b:a[2]*255}},rgb_to_hsv:function(a,c,d){var e=Math.min(a,c,d),b=Math.max(a,c,d),e=b-e;if(b==0)return{h:NaN,s:0,v:0}; 90 | a=a==b?(c-d)/e:c==b?2+(d-a)/e:4+(a-c)/e;a/=6;a<0&&(a+=1);return{h:a*360,s:e/b,v:b/255}},rgb_to_hex:function(a,c,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,c);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,c){return a>>c*8&255},hex_with_component:function(a,c,d){return d<<(e=c*8)|a&~(255<WebGL.
', 31 | 'Find out how to get it here.' 32 | ].join( '\n' ) : [ 33 | 'Your browser does not seem to support WebGL.
', 34 | 'Find out how to get it here.' 35 | ].join( '\n' ); 36 | 37 | } 38 | 39 | return element; 40 | 41 | }, 42 | 43 | addGetWebGLMessage: function ( parameters ) { 44 | 45 | var parent, id, element; 46 | 47 | parameters = parameters || {}; 48 | 49 | parent = parameters.parent !== undefined ? parameters.parent : document.body; 50 | id = parameters.id !== undefined ? parameters.id : 'oldie'; 51 | 52 | element = Detector.getWebGLErrorMessage(); 53 | element.id = id; 54 | 55 | parent.appendChild( element ); 56 | 57 | } 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /js/RequestAnimationFrame.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides requestAnimationFrame in a cross browser way. 3 | * http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 4 | */ 5 | 6 | if ( !window.requestAnimationFrame ) { 7 | 8 | window.requestAnimationFrame = ( function() { 9 | 10 | return window.webkitRequestAnimationFrame || 11 | window.mozRequestAnimationFrame || 12 | window.oRequestAnimationFrame || 13 | window.msRequestAnimationFrame || 14 | function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) { 15 | 16 | window.setTimeout( callback, 1000 / 60 ); 17 | 18 | }; 19 | 20 | } )(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /js/Stats.js: -------------------------------------------------------------------------------- 1 | // stats.js r8 - http://github.com/mrdoob/stats.js 2 | var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= 3 | "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= 4 | "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= 5 | "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"), 6 | a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/ 7 | 100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}}; 8 | 9 | -------------------------------------------------------------------------------- /js/TrackballControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Eberhard Graether / http://egraether.com/ 3 | * @author Mark Lundin / http://mark-lundin.com 4 | * @author Simone Manini / http://daron1337.github.io 5 | * @author Luca Antiga / http://lantiga.github.io 6 | */ 7 | 8 | THREE.TrackballControls = function ( object, domElement ) { 9 | 10 | var _this = this; 11 | var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 }; 12 | 13 | this.object = object; 14 | this.domElement = ( domElement !== undefined ) ? domElement : document; 15 | 16 | // API 17 | 18 | this.enabled = true; 19 | 20 | this.screen = { left: 0, top: 0, width: 0, height: 0 }; 21 | 22 | this.rotateSpeed = 1.0; 23 | this.zoomSpeed = 1.2; 24 | this.panSpeed = 0.3; 25 | 26 | this.noRotate = false; 27 | this.noZoom = false; 28 | this.noPan = false; 29 | 30 | this.staticMoving = false; 31 | this.dynamicDampingFactor = 0.2; 32 | 33 | this.minDistance = 0; 34 | this.maxDistance = Infinity; 35 | 36 | this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ]; 37 | 38 | // internals 39 | 40 | this.target = new THREE.Vector3(); 41 | 42 | var EPS = 0.000001; 43 | 44 | var lastPosition = new THREE.Vector3(); 45 | 46 | var _state = STATE.NONE, 47 | _prevState = STATE.NONE, 48 | 49 | _eye = new THREE.Vector3(), 50 | 51 | _movePrev = new THREE.Vector2(), 52 | _moveCurr = new THREE.Vector2(), 53 | 54 | _lastAxis = new THREE.Vector3(), 55 | _lastAngle = 0, 56 | 57 | _zoomStart = new THREE.Vector2(), 58 | _zoomEnd = new THREE.Vector2(), 59 | 60 | _touchZoomDistanceStart = 0, 61 | _touchZoomDistanceEnd = 0, 62 | 63 | _panStart = new THREE.Vector2(), 64 | _panEnd = new THREE.Vector2(); 65 | 66 | // for reset 67 | 68 | this.target0 = this.target.clone(); 69 | this.position0 = this.object.position.clone(); 70 | this.up0 = this.object.up.clone(); 71 | 72 | // events 73 | 74 | var changeEvent = { type: 'change' }; 75 | var startEvent = { type: 'start' }; 76 | var endEvent = { type: 'end' }; 77 | 78 | 79 | // methods 80 | 81 | this.handleResize = function () { 82 | 83 | if ( this.domElement === document ) { 84 | 85 | this.screen.left = 0; 86 | this.screen.top = 0; 87 | this.screen.width = window.innerWidth; 88 | this.screen.height = window.innerHeight; 89 | 90 | } else { 91 | 92 | var box = this.domElement.getBoundingClientRect(); 93 | // adjustments come from similar code in the jquery offset() function 94 | var d = this.domElement.ownerDocument.documentElement; 95 | this.screen.left = box.left + window.pageXOffset - d.clientLeft; 96 | this.screen.top = box.top + window.pageYOffset - d.clientTop; 97 | this.screen.width = box.width; 98 | this.screen.height = box.height; 99 | 100 | } 101 | 102 | }; 103 | 104 | this.handleEvent = function ( event ) { 105 | 106 | if ( typeof this[ event.type ] == 'function' ) { 107 | 108 | this[ event.type ]( event ); 109 | 110 | } 111 | 112 | }; 113 | 114 | var getMouseOnScreen = ( function () { 115 | 116 | var vector = new THREE.Vector2(); 117 | 118 | return function getMouseOnScreen( pageX, pageY ) { 119 | 120 | vector.set( 121 | ( pageX - _this.screen.left ) / _this.screen.width, 122 | ( pageY - _this.screen.top ) / _this.screen.height 123 | ); 124 | 125 | return vector; 126 | 127 | }; 128 | 129 | }() ); 130 | 131 | var getMouseOnCircle = ( function () { 132 | 133 | var vector = new THREE.Vector2(); 134 | 135 | return function getMouseOnCircle( pageX, pageY ) { 136 | 137 | vector.set( 138 | ( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ), 139 | ( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional 140 | ); 141 | 142 | return vector; 143 | 144 | }; 145 | 146 | }() ); 147 | 148 | this.rotateCamera = ( function() { 149 | 150 | var axis = new THREE.Vector3(), 151 | quaternion = new THREE.Quaternion(), 152 | eyeDirection = new THREE.Vector3(), 153 | objectUpDirection = new THREE.Vector3(), 154 | objectSidewaysDirection = new THREE.Vector3(), 155 | moveDirection = new THREE.Vector3(), 156 | angle; 157 | 158 | return function rotateCamera() { 159 | 160 | moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 ); 161 | angle = moveDirection.length(); 162 | 163 | if ( angle ) { 164 | 165 | _eye.copy( _this.object.position ).sub( _this.target ); 166 | 167 | eyeDirection.copy( _eye ).normalize(); 168 | objectUpDirection.copy( _this.object.up ).normalize(); 169 | objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize(); 170 | 171 | objectUpDirection.setLength( _moveCurr.y - _movePrev.y ); 172 | objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x ); 173 | 174 | moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) ); 175 | 176 | axis.crossVectors( moveDirection, _eye ).normalize(); 177 | 178 | angle *= _this.rotateSpeed; 179 | quaternion.setFromAxisAngle( axis, angle ); 180 | 181 | _eye.applyQuaternion( quaternion ); 182 | _this.object.up.applyQuaternion( quaternion ); 183 | 184 | _lastAxis.copy( axis ); 185 | _lastAngle = angle; 186 | 187 | } else if ( ! _this.staticMoving && _lastAngle ) { 188 | 189 | _lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor ); 190 | _eye.copy( _this.object.position ).sub( _this.target ); 191 | quaternion.setFromAxisAngle( _lastAxis, _lastAngle ); 192 | _eye.applyQuaternion( quaternion ); 193 | _this.object.up.applyQuaternion( quaternion ); 194 | 195 | } 196 | 197 | _movePrev.copy( _moveCurr ); 198 | 199 | }; 200 | 201 | }() ); 202 | 203 | 204 | this.zoomCamera = function () { 205 | 206 | var factor; 207 | 208 | if ( _state === STATE.TOUCH_ZOOM_PAN ) { 209 | 210 | factor = _touchZoomDistanceStart / _touchZoomDistanceEnd; 211 | _touchZoomDistanceStart = _touchZoomDistanceEnd; 212 | _eye.multiplyScalar( factor ); 213 | 214 | } else { 215 | 216 | factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed; 217 | 218 | if ( factor !== 1.0 && factor > 0.0 ) { 219 | 220 | _eye.multiplyScalar( factor ); 221 | 222 | } 223 | 224 | if ( _this.staticMoving ) { 225 | 226 | _zoomStart.copy( _zoomEnd ); 227 | 228 | } else { 229 | 230 | _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor; 231 | 232 | } 233 | 234 | } 235 | 236 | }; 237 | 238 | this.panCamera = ( function() { 239 | 240 | var mouseChange = new THREE.Vector2(), 241 | objectUp = new THREE.Vector3(), 242 | pan = new THREE.Vector3(); 243 | 244 | return function panCamera() { 245 | 246 | mouseChange.copy( _panEnd ).sub( _panStart ); 247 | 248 | if ( mouseChange.lengthSq() ) { 249 | 250 | mouseChange.multiplyScalar( _eye.length() * _this.panSpeed ); 251 | 252 | pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x ); 253 | pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) ); 254 | 255 | _this.object.position.add( pan ); 256 | _this.target.add( pan ); 257 | 258 | if ( _this.staticMoving ) { 259 | 260 | _panStart.copy( _panEnd ); 261 | 262 | } else { 263 | 264 | _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) ); 265 | 266 | } 267 | 268 | } 269 | 270 | }; 271 | 272 | }() ); 273 | 274 | this.checkDistances = function () { 275 | 276 | if ( ! _this.noZoom || ! _this.noPan ) { 277 | 278 | if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) { 279 | 280 | _this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) ); 281 | _zoomStart.copy( _zoomEnd ); 282 | 283 | } 284 | 285 | if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) { 286 | 287 | _this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) ); 288 | _zoomStart.copy( _zoomEnd ); 289 | 290 | } 291 | 292 | } 293 | 294 | }; 295 | 296 | this.update = function () { 297 | 298 | _eye.subVectors( _this.object.position, _this.target ); 299 | 300 | if ( ! _this.noRotate ) { 301 | 302 | _this.rotateCamera(); 303 | 304 | } 305 | 306 | if ( ! _this.noZoom ) { 307 | 308 | _this.zoomCamera(); 309 | 310 | } 311 | 312 | if ( ! _this.noPan ) { 313 | 314 | _this.panCamera(); 315 | 316 | } 317 | 318 | _this.object.position.addVectors( _this.target, _eye ); 319 | 320 | _this.checkDistances(); 321 | 322 | _this.object.lookAt( _this.target ); 323 | 324 | if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) { 325 | 326 | _this.dispatchEvent( changeEvent ); 327 | 328 | lastPosition.copy( _this.object.position ); 329 | 330 | } 331 | 332 | }; 333 | 334 | this.reset = function () { 335 | 336 | _state = STATE.NONE; 337 | _prevState = STATE.NONE; 338 | 339 | _this.target.copy( _this.target0 ); 340 | _this.object.position.copy( _this.position0 ); 341 | _this.object.up.copy( _this.up0 ); 342 | 343 | _eye.subVectors( _this.object.position, _this.target ); 344 | 345 | _this.object.lookAt( _this.target ); 346 | 347 | _this.dispatchEvent( changeEvent ); 348 | 349 | lastPosition.copy( _this.object.position ); 350 | 351 | }; 352 | 353 | // listeners 354 | 355 | function keydown( event ) { 356 | 357 | if ( _this.enabled === false ) return; 358 | 359 | window.removeEventListener( 'keydown', keydown ); 360 | 361 | _prevState = _state; 362 | 363 | if ( _state !== STATE.NONE ) { 364 | 365 | return; 366 | 367 | } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) { 368 | 369 | _state = STATE.ROTATE; 370 | 371 | } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) { 372 | 373 | _state = STATE.ZOOM; 374 | 375 | } else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) { 376 | 377 | _state = STATE.PAN; 378 | 379 | } 380 | 381 | } 382 | 383 | function keyup( event ) { 384 | 385 | if ( _this.enabled === false ) return; 386 | 387 | _state = _prevState; 388 | 389 | window.addEventListener( 'keydown', keydown, false ); 390 | 391 | } 392 | 393 | function mousedown( event ) { 394 | 395 | if ( _this.enabled === false ) return; 396 | 397 | event.preventDefault(); 398 | event.stopPropagation(); 399 | 400 | if ( _state === STATE.NONE ) { 401 | 402 | // HK: Replace default mapping so pan == mbutton, zoom == rbutton 403 | //_state = event.button; 404 | if (event.button == 0) 405 | _state = STATE.ROTATE; 406 | else if (event.button == 1) 407 | _state = STATE.PAN; 408 | else if (event.button == 2) 409 | _state = STATE.ZOOM; 410 | } 411 | 412 | if ( _state === STATE.ROTATE && ! _this.noRotate ) { 413 | 414 | _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); 415 | _movePrev.copy( _moveCurr ); 416 | 417 | } else if ( _state === STATE.ZOOM && ! _this.noZoom ) { 418 | 419 | _zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); 420 | _zoomEnd.copy( _zoomStart ); 421 | 422 | } else if ( _state === STATE.PAN && ! _this.noPan ) { 423 | 424 | _panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); 425 | _panEnd.copy( _panStart ); 426 | 427 | } 428 | 429 | document.addEventListener( 'mousemove', mousemove, false ); 430 | document.addEventListener( 'mouseup', mouseup, false ); 431 | 432 | _this.dispatchEvent( startEvent ); 433 | 434 | } 435 | 436 | function mousemove( event ) { 437 | 438 | if ( _this.enabled === false ) return; 439 | 440 | event.preventDefault(); 441 | event.stopPropagation(); 442 | 443 | if ( _state === STATE.ROTATE && ! _this.noRotate ) { 444 | 445 | _movePrev.copy( _moveCurr ); 446 | _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); 447 | 448 | } else if ( _state === STATE.ZOOM && ! _this.noZoom ) { 449 | 450 | _zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); 451 | 452 | } else if ( _state === STATE.PAN && ! _this.noPan ) { 453 | 454 | _panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); 455 | 456 | } 457 | 458 | } 459 | 460 | function mouseup( event ) { 461 | 462 | if ( _this.enabled === false ) return; 463 | 464 | event.preventDefault(); 465 | event.stopPropagation(); 466 | 467 | _state = STATE.NONE; 468 | 469 | document.removeEventListener( 'mousemove', mousemove ); 470 | document.removeEventListener( 'mouseup', mouseup ); 471 | _this.dispatchEvent( endEvent ); 472 | 473 | } 474 | 475 | function mousewheel( event ) { 476 | 477 | if ( _this.enabled === false ) return; 478 | 479 | if ( _this.noZoom === true ) return; 480 | 481 | event.preventDefault(); 482 | event.stopPropagation(); 483 | 484 | switch ( event.deltaMode ) { 485 | 486 | case 2: 487 | // Zoom in pages 488 | _zoomStart.y -= event.deltaY * 0.025; 489 | break; 490 | 491 | case 1: 492 | // Zoom in lines 493 | _zoomStart.y -= event.deltaY * 0.01; 494 | break; 495 | 496 | default: 497 | // undefined, 0, assume pixels 498 | _zoomStart.y -= event.deltaY * 0.00025; 499 | break; 500 | 501 | } 502 | 503 | _this.dispatchEvent( startEvent ); 504 | _this.dispatchEvent( endEvent ); 505 | 506 | } 507 | 508 | function touchstart( event ) { 509 | 510 | if ( _this.enabled === false ) return; 511 | 512 | switch ( event.touches.length ) { 513 | 514 | case 1: 515 | _state = STATE.TOUCH_ROTATE; 516 | _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); 517 | _movePrev.copy( _moveCurr ); 518 | break; 519 | 520 | default: // 2 or more 521 | _state = STATE.TOUCH_ZOOM_PAN; 522 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 523 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 524 | _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy ); 525 | 526 | var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; 527 | var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; 528 | _panStart.copy( getMouseOnScreen( x, y ) ); 529 | _panEnd.copy( _panStart ); 530 | break; 531 | 532 | } 533 | 534 | _this.dispatchEvent( startEvent ); 535 | 536 | } 537 | 538 | function touchmove( event ) { 539 | 540 | if ( _this.enabled === false ) return; 541 | 542 | event.preventDefault(); 543 | event.stopPropagation(); 544 | 545 | switch ( event.touches.length ) { 546 | 547 | case 1: 548 | _movePrev.copy( _moveCurr ); 549 | _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); 550 | break; 551 | 552 | default: // 2 or more 553 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 554 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 555 | _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy ); 556 | 557 | var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; 558 | var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; 559 | _panEnd.copy( getMouseOnScreen( x, y ) ); 560 | break; 561 | 562 | } 563 | 564 | } 565 | 566 | function touchend( event ) { 567 | 568 | if ( _this.enabled === false ) return; 569 | 570 | switch ( event.touches.length ) { 571 | 572 | case 0: 573 | _state = STATE.NONE; 574 | break; 575 | 576 | case 1: 577 | _state = STATE.TOUCH_ROTATE; 578 | _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); 579 | _movePrev.copy( _moveCurr ); 580 | break; 581 | 582 | } 583 | 584 | _this.dispatchEvent( endEvent ); 585 | 586 | } 587 | 588 | function contextmenu( event ) { 589 | 590 | if ( _this.enabled === false ) return; 591 | 592 | event.preventDefault(); 593 | 594 | } 595 | 596 | this.dispose = function() { 597 | 598 | this.domElement.removeEventListener( 'contextmenu', contextmenu, false ); 599 | this.domElement.removeEventListener( 'mousedown', mousedown, false ); 600 | this.domElement.removeEventListener( 'wheel', mousewheel, false ); 601 | 602 | this.domElement.removeEventListener( 'touchstart', touchstart, false ); 603 | this.domElement.removeEventListener( 'touchend', touchend, false ); 604 | this.domElement.removeEventListener( 'touchmove', touchmove, false ); 605 | 606 | document.removeEventListener( 'mousemove', mousemove, false ); 607 | document.removeEventListener( 'mouseup', mouseup, false ); 608 | 609 | window.removeEventListener( 'keydown', keydown, false ); 610 | window.removeEventListener( 'keyup', keyup, false ); 611 | 612 | }; 613 | 614 | this.domElement.addEventListener( 'contextmenu', contextmenu, false ); 615 | this.domElement.addEventListener( 'mousedown', mousedown, false ); 616 | this.domElement.addEventListener( 'wheel', mousewheel, false ); 617 | 618 | this.domElement.addEventListener( 'touchstart', touchstart, false ); 619 | this.domElement.addEventListener( 'touchend', touchend, false ); 620 | this.domElement.addEventListener( 'touchmove', touchmove, false ); 621 | 622 | window.addEventListener( 'keydown', keydown, false ); 623 | window.addEventListener( 'keyup', keyup, false ); 624 | 625 | this.handleResize(); 626 | 627 | // force an update at start 628 | this.update(); 629 | 630 | }; 631 | 632 | THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype ); 633 | THREE.TrackballControls.prototype.constructor = THREE.TrackballControls; -------------------------------------------------------------------------------- /js/Utils.js: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.js 3 | // 4 | // Author-Hans Kellner 5 | // Description-Utility functions. 6 | 7 | /*! 8 | Copyright (C) 2015 Hans Kellner: https://github.com/hanskellner/Fusion360Image2Surface 9 | MIT License: See https://github.com/hanskellner/Fusion360Image2Surface/LICENSE.md 10 | */ 11 | 12 | var Utils = (function(my) { 13 | 14 | my.Vector3 = function ( x, y, z ) { 15 | this.x = x || 0; 16 | this.y = y || 0; 17 | this.z = z || 0; 18 | }; 19 | 20 | my.Vector3.subtractVectors = function(v1, v2) { 21 | var vx = v1.x - v2.x; 22 | var vy = v1.y - v2.y; 23 | var vz = v1.z - v2.z; 24 | 25 | return new my.Vector3(vx, vy, vz); 26 | }; 27 | 28 | my.Vector3.crossVectors = function(v1, v2) { 29 | var vx = v1.y * v2.z - v1.z * v2.y; 30 | var vy = v1.z * v2.x - v1.x * v2.z; 31 | var vz = v1.x * v2.y - v1.y * v2.x; 32 | 33 | return new my.Vector3(vx, vy, vz); 34 | }; 35 | 36 | my.Vector3.prototype = { 37 | 38 | constructor: my.Vector3, 39 | 40 | add: function ( v ) { 41 | 42 | var x = this.x, y = this.y, z = this.z; 43 | 44 | this.x = x + v.x; 45 | this.y = y + v.y; 46 | this.z = z + v.z; 47 | 48 | return this; 49 | }, 50 | 51 | subtract: function ( v ) { 52 | 53 | var x = this.x, y = this.y, z = this.z; 54 | 55 | this.x = x - v.x; 56 | this.y = y - v.y; 57 | this.z = z - v.z; 58 | 59 | return this; 60 | }, 61 | 62 | cross: function ( v ) { 63 | 64 | var x = this.x, y = this.y, z = this.z; 65 | 66 | this.x = y * v.z - z * v.y; 67 | this.y = z * v.x - x * v.z; 68 | this.z = x * v.y - y * v.x; 69 | 70 | return this; 71 | }, 72 | 73 | length: function () { 74 | return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); 75 | }, 76 | 77 | normalize: function() { 78 | var len = this.length(); 79 | if (len !== 0) { 80 | var inv = 1 / len; 81 | this.x *= inv; 82 | this.y *= inv; 83 | this.z *= inv; 84 | } 85 | else { 86 | this.x = this.y = this.z = 0; 87 | } 88 | 89 | return this; 90 | } 91 | }; 92 | 93 | my.Mesh = function (width, length) { 94 | this.width = width; 95 | this.length = length; 96 | this.vertices = []; 97 | this.vertNormals = []; 98 | this.faces = []; 99 | }; 100 | 101 | my.Mesh.prototype = { 102 | 103 | constructor: my.Mesh, 104 | 105 | do: function ( ) { 106 | 107 | return this; 108 | } 109 | }; 110 | 111 | function stringifyVector(vec) 112 | { 113 | return "" + vec.x.toFixed(6) + " " + vec.y.toFixed(6) + " " + vec.z.toFixed(6); 114 | }; 115 | 116 | function stringifyVertexSTL(vec) 117 | { 118 | return "vertex "+stringifyVector(vec)+" \n"; 119 | }; 120 | 121 | function stringifyVertexOBJ(vec) 122 | { 123 | return "v "+stringifyVector(vec)+" \n"; 124 | }; 125 | 126 | function stringifyVertexNormalOBJ(vec) 127 | { 128 | return "vn "+stringifyVector(vec)+" \n"; 129 | }; 130 | 131 | function normalForFace(p1, p2, p3) { 132 | // vector from point 1 to point 2 133 | var p1p2x = p2.x - p1.x; 134 | var p1p2y = p2.y - p1.y; 135 | var p1p2z = p2.z - p1.z; 136 | 137 | // vector from point 1 to point 3 138 | var p1p3x = p3.x - p1.x; 139 | var p1p3y = p3.y - p1.y; 140 | var p1p3z = p3.z - p1.z; 141 | 142 | // normal vector from plane at point 1 143 | var nx = p1p2y*p1p3z - p1p2z*p1p3y; 144 | var ny = p1p2z*p1p3x - p1p2x*p1p3z; 145 | var nz = p1p2x*p1p3y - p1p2y*p1p3x; 146 | 147 | return new Utils.Vector3(nx, ny, nz); 148 | }; 149 | 150 | // Create a Mesh for the height data. 151 | my.createMesh = function(heightData, width, length, step, isQuad) { 152 | 153 | var mesh = new Utils.Mesh(width, length); 154 | 155 | // Generate array of vertices and empty vertex normals. 156 | for (var y0 = 0; y0 < length; ++y0) { 157 | for (var x0 = 0; x0 < width; ++x0) { 158 | mesh.vertices.push( new Utils.Vector3(x0*step, y0*step, heightData[x0 + y0*width]) ); 159 | mesh.vertNormals.push( new Utils.Vector3() ); 160 | } 161 | } 162 | 163 | // Calculate vertex normals. 164 | // Use an area weighted normalized mesh 165 | // From: http://www.iquilezles.org/www/articles/normals/normals.htm 166 | for (var y1 = 0; y1 < length - 1; ++y1) { 167 | for (var x1 = 0; x1 < width - 1; ++x1) { 168 | 169 | // Calc the values for the two triangles that form a quad 170 | 171 | var iTL = x1 + y1 * width; 172 | var iTR = (x1 + 1) + y1 * width; 173 | var iBL = x1 + (y1 + 1) * width; 174 | var iBR = (x1 + 1) + (y1 + 1) * width; 175 | 176 | // Tri face 1 (a->b a->c) 177 | var v1ba = Utils.Vector3.subtractVectors(mesh.vertices[iTR], mesh.vertices[iTL]); 178 | var v1ca = Utils.Vector3.subtractVectors(mesh.vertices[iBL], mesh.vertices[iTL]); 179 | var vnorm1 = Utils.Vector3.crossVectors( v1ba, v1ca ); 180 | 181 | mesh.vertNormals[iTL].add(vnorm1); 182 | mesh.vertNormals[iTR].add(vnorm1); 183 | mesh.vertNormals[iBL].add(vnorm1); 184 | 185 | // Tri face 2 (a->b a->c) 186 | var v2ba = Utils.Vector3.subtractVectors(mesh.vertices[iTR], mesh.vertices[iBR]); 187 | var v2ca = Utils.Vector3.subtractVectors(mesh.vertices[iBL], mesh.vertices[iBR]); 188 | var vnorm2 = Utils.Vector3.crossVectors( v2ba, v2ca ); 189 | 190 | mesh.vertNormals[iBR].add(vnorm2); 191 | mesh.vertNormals[iTR].add(vnorm2); 192 | mesh.vertNormals[iBL].add(vnorm2); 193 | 194 | if (isQuad) { 195 | mesh.faces.push([iTL,iTR,iBR,iBL]); 196 | } 197 | else { 198 | mesh.faces.push([iTL,iTR,iBL]); 199 | mesh.faces.push([iBR,iBL,iTR]); 200 | } 201 | } 202 | } 203 | 204 | // Now normalize all the vertex normals. 205 | for ( iv = 0, ivlen = width * length; iv < ivlen; ++iv ) { 206 | mesh.vertNormals[iv].normalize(); 207 | } 208 | 209 | return mesh; 210 | }; 211 | 212 | // Create a string formatted as an OBJ file 213 | my.createOBJString = function(name, mesh) { 214 | 215 | var objStr = "# Generated by image2surface for " + name + " \n\n"; 216 | objStr += "# Units = Centimeters \n"; 217 | objStr += "# Face count = " + mesh.faces.length + " \n"; 218 | objStr += "# Vertext count = " + mesh.vertices.length + " \n\n"; 219 | 220 | if (mesh && mesh.width > 2 && mesh.length > 2) { 221 | 222 | var vCount = mesh.width * mesh.length; 223 | 224 | // Generate the vertex and normal entries 225 | for (var iv = 0; iv < vCount; ++iv) { 226 | objStr += stringifyVertexOBJ( mesh.vertices[iv] ); 227 | objStr += stringifyVertexNormalOBJ( mesh.vertNormals[iv] ); 228 | } 229 | 230 | // Now generate the face entries 231 | for (var iface = 0; iface < mesh.faces.length; ++iface) { 232 | 233 | objStr += "f"; 234 | 235 | var idxs = mesh.faces[iface]; // array of indicies of vertex/normals 236 | 237 | for (var i = 0; i < idxs.length; ++i) { 238 | 239 | var idx = idxs[i] + 1; // 1 based index 240 | 241 | objStr += " " + idx + "//" + idx; 242 | } 243 | 244 | objStr += "\n"; 245 | } 246 | } 247 | 248 | objStr += ("\n# End " + name + " \n"); 249 | 250 | return objStr; 251 | }; 252 | 253 | // Create a simple OBJ file 254 | my.createOBJSimple = function(heightData, width, length, step) { 255 | 256 | var objStr = "# Generated by image2surface \n"; 257 | 258 | var p1 = { x: 0, y: 0, z: 0}; 259 | var p2 = { x: 0, y: 0, z: 0}; 260 | var p3 = { x: 0, y: 0, z: 0}; 261 | var p4 = { x: 0, y: 0, z: 0}; 262 | 263 | var vtxCount = 0; 264 | 265 | for (var y = 0; y < length - 2; ++y) { 266 | for (var x = 0; x < width - 2; ++x) { 267 | 268 | // Get the points of the face 269 | p1.x = x*step; 270 | p1.y = y*step; 271 | p1.z = heightData[x + y*width]; 272 | 273 | p2.x = (x + 1)*step; 274 | p2.y = y*step; 275 | p2.z = heightData[(x + 1) + y*width]; 276 | 277 | p3.x = (x + 1)*step; 278 | p3.y = (y + 1)*step; 279 | p3.z = heightData[(x + 1) + (y + 1)*width]; 280 | 281 | p4.x = x*step; 282 | p4.y = (y + 1)*step; 283 | p4.z = heightData[x + (y + 1)*width]; 284 | 285 | obj += stringifyVertexOBJ( p1 ); 286 | obj += stringifyVertexOBJ( p2 ); 287 | obj += stringifyVertexOBJ( p3 ); 288 | obj += stringifyVertexOBJ( p4 ); 289 | 290 | objStr += "f -4 -3 -2 -1 \n"; // relative 291 | } 292 | } 293 | 294 | objStr += ("# End \n"); 295 | 296 | return objStr; 297 | }; 298 | 299 | my.createSTLString = function(name, heightData, width, length, step) { 300 | 301 | var p1 = { x: 0, y: 0, z: 0}; 302 | var p2 = { x: 0, y: 0, z: 0}; 303 | var p3 = { x: 0, y: 0, z: 0}; 304 | 305 | var stl = "solid " + name + " \n"; 306 | 307 | for (var y = 0; y < length - 2; ++y) { 308 | for (var x = 0; x < width - 2; ++x) { 309 | 310 | // Get the points of the face left 311 | p1.x = x*step; 312 | p1.y = y*step; 313 | p1.z = heightData[x + y*width]; 314 | p2.x = (x + 1)*step; 315 | p2.y = y*step; 316 | p2.z = heightData[(x + 1) + y*width]; 317 | p3.x = x*step; 318 | p3.y = (y + 1)*step; 319 | p3.z = heightData[x + (y + 1)*width]; 320 | 321 | stl += ("facet normal " + stringifyVector( normalForFace(p1,p2,p3) )+" \n"); 322 | 323 | stl += ("outer loop \n"); 324 | stl += stringifyVertexSTL( p1 ); 325 | stl += stringifyVertexSTL( p2 ); 326 | stl += stringifyVertexSTL( p3 ); 327 | stl += ("endloop \n"); 328 | 329 | stl += ("endfacet \n"); 330 | 331 | // Get the points of the face right 332 | p1.x = (x + 1)*step; 333 | p1.y = y*step; 334 | p1.z = heightData[(x + 1) + y*width]; 335 | p2.x = (x + 1)*step; 336 | p2.y = (y + 1)*step; 337 | p2.z = heightData[(x + 1) + (y + 1)*width]; 338 | p3.x = x*step; 339 | p3.y = (y + 1)*step; 340 | p3.z = heightData[x + (y + 1)*width]; 341 | 342 | stl += ("facet normal " + stringifyVector( normalForFace(p1,p2,p3) )+" \n"); 343 | 344 | stl += ("outer loop \n"); 345 | stl += stringifyVertexSTL( p1 ); 346 | stl += stringifyVertexSTL( p2 ); 347 | stl += stringifyVertexSTL( p3 ); 348 | stl += ("endloop \n"); 349 | 350 | stl += ("endfacet \n"); 351 | } 352 | } 353 | 354 | stl += ("endsolid " + name + " \n"); 355 | 356 | return stl; 357 | }; 358 | 359 | return my; 360 | 361 | })(Utils || {}); 362 | -------------------------------------------------------------------------------- /js/image2surface.js: -------------------------------------------------------------------------------- 1 | //Author-Hans Kellner 2 | //Description-Generate a surface from an image in Autodesk Fusion 360. 3 | 4 | /*! 5 | Copyright (C) 2015-2018 Hans Kellner: https://github.com/hanskellner/Fusion360Image2Surface 6 | MIT License: See https://github.com/hanskellner/Fusion360Image2Surface/LICENSE.md 7 | */ 8 | 9 | var _inputImage, 10 | _imageWidth, 11 | _imageHeight, 12 | _imageFileName, 13 | _pixels, 14 | _content, 15 | _lineGroup, 16 | _lineHolder, 17 | _camera, 18 | _scene, 19 | _renderer, 20 | _material, 21 | _canvas, 22 | _context, 23 | _controls, 24 | _gui, 25 | _guiOptions; 26 | 27 | 28 | var GuiOptions = function() { 29 | this.pixelStep = 5; // pixel step over in the image 30 | this.meshStep = 1; // amount in mms to step over mesh per pixel 31 | this.maxHeight = 5; // max mesh height in mms for brightest image color 32 | this.invert = false; // true to invert height values (dark == highest) 33 | this.smoothing = true; //turn on smoothing 34 | this.absolute = false; 35 | }; 36 | 37 | // Initialize the page 38 | $(document).ready( function() { 39 | 40 | _gui = new dat.GUI(); 41 | 42 | _guiOptions = new GuiOptions(); 43 | _gui.add(_guiOptions, 'pixelStep', 1.00, 50.00, 5.00).name('Pixels to Skip').step(1).onChange( createLines ); 44 | _gui.add(_guiOptions, 'meshStep', 0.10, 10.00, 1.00).name('Stepover (mm)').step(0.1).onChange( createLines ); 45 | _gui.add(_guiOptions, 'maxHeight', 1.00, 500.00, 5.00).name('Max Height (mm)').step(0.1).onChange( createLines ); 46 | _gui.add(_guiOptions, 'invert').name('Invert Heights').onChange( createLines ); 47 | _gui.add(_guiOptions, 'smoothing').name('Smooth').onChange( createLines ); 48 | _gui.add(_guiOptions, 'absolute').name('Absolute (B&W)').onChange( createLines ); 49 | 50 | $(window).bind('resize', onWindowResize); 51 | 52 | //init image drag and drop 53 | if (typeof(FileReader) != "undefined") { 54 | 55 | var dropzoneId = "dropzone"; 56 | 57 | window.addEventListener("dragenter", function(e) { 58 | var dropElement = $(e.target); 59 | if (!dropElement.hasClass(dropzoneId)) { 60 | e.dataTransfer.effectAllowed = "none"; 61 | e.dataTransfer.dropEffect = "none"; 62 | } 63 | event.preventDefault(); 64 | }, false); 65 | 66 | window.addEventListener("dragover", function(e) { 67 | var dropElement = $(e.target); 68 | if (dropElement.hasClass(dropzoneId)) { 69 | $('.dropzone').css('background-color', 'green'); 70 | } 71 | event.preventDefault(); 72 | }); 73 | 74 | window.addEventListener("dragleave", function(e) { 75 | var dropElement = $(e.target); 76 | if (dropElement.hasClass(dropzoneId)) { 77 | $('.dropzone').css('background-color', 'black'); 78 | } 79 | event.preventDefault(); 80 | }); 81 | 82 | window.addEventListener("drop", function(e) { 83 | var dropElement = $(e.target); 84 | if (!dropElement.hasClass(dropzoneId)) { 85 | e.preventDefault(); 86 | e.dataTransfer.effectAllowed = "none"; 87 | e.dataTransfer.dropEffect = "none"; 88 | } 89 | else { 90 | $('.dropzone').css('background-color', 'black'); 91 | e.preventDefault(); 92 | 93 | var file = event.dataTransfer.files[0]; 94 | loadImageFile(file); 95 | } 96 | }); 97 | 98 | enableDropZone(true); 99 | 100 | document.getElementById('getimagefile').addEventListener('change', readImageURL, true); 101 | } 102 | 103 | // stop the user getting a text cursor 104 | document.onselectstart = function() { 105 | return false; 106 | }; 107 | 108 | _content = document.getElementById("content"); 109 | 110 | $(window).keydown(onKeyDown); 111 | 112 | if (!Detector.webgl) { 113 | $('#dropzone').empty(); 114 | Detector.addGetWebGLMessage({ 115 | parent: document.getElementById('dropzone') 116 | }); 117 | } 118 | else { 119 | _camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 5000); 120 | _camera.position.z = 400; 121 | 122 | _renderer = new THREE.WebGLRenderer({ 123 | antialias: true, 124 | clearAlpha: 1, 125 | sortObjects: false, 126 | sortElements: false 127 | }); 128 | //_renderer.setPixelRatio( window.devicePixelRatio ? window.devicePixelRatio : 1 ); 129 | 130 | _content.appendChild(_renderer.domElement); 131 | 132 | // Create and attach controls to the renderer. 133 | // Controls only work when the mouse is over the renderer's domElement (the canvas). 134 | _controls = new THREE.TrackballControls( _camera, _renderer.domElement ); 135 | _controls.rotateSpeed = 2.0; 136 | _controls.zoomSpeed = 1.2; 137 | _controls.panSpeed = 0.8; 138 | _controls.noZoom = false; 139 | _controls.noPan = false; 140 | _controls.staticMoving = true; // true == Disable damping 141 | //_controls.dynamicDampingFactor = 0.3; 142 | //_controls.keys = [ 65, 83, 68 ]; 143 | 144 | _controls.addEventListener( 'change', render ); 145 | 146 | _scene = new THREE.Scene(); 147 | 148 | _lineHolder = new THREE.Object3D(); 149 | _scene.add(_lineHolder); 150 | } 151 | 152 | onWindowResize(); 153 | animate(); 154 | }); 155 | 156 | function resetGUIOptions() { 157 | _guiOptions.pixelStep = 5; 158 | _guiOptions.meshStep = 1; 159 | _guiOptions.maxHeight = 5; 160 | _guiOptions.invert = false; 161 | _guiOptions.smoothing = true; //turn on smoothing 162 | _guiOptions.absolute = false; 163 | 164 | // Iterate over all controllers 165 | for (var i in _gui.__controllers) { 166 | _gui.__controllers[i].updateDisplay(); 167 | } 168 | } 169 | 170 | function readImageURL() { 171 | var file = document.getElementById("getimagefile").files[0]; 172 | loadImageFile(file); 173 | } 174 | 175 | function loadImageFile(file) { 176 | if (file == null) 177 | return; 178 | 179 | var fileType = file.type; 180 | if (!fileType.match(/image\/\w+/)) { 181 | alert("Only image files supported."); 182 | return; 183 | } 184 | 185 | var reader = new FileReader(); 186 | reader.onload = function() { 187 | 188 | _inputImage = new Image(); 189 | _inputImage.src = reader.result; 190 | 191 | _inputImage.onload = function() { 192 | onImageLoaded(); 193 | }; 194 | }; 195 | 196 | reader.readAsDataURL(file); 197 | 198 | _imageFileName = file.name.replace(/^.*[\\\/]/, ''); // Just want filename, no path 199 | $('#imagefilename').html(_imageFileName); 200 | } 201 | 202 | // Called from html page 203 | function clearImageLoaded() { 204 | _inputImage = null; 205 | 206 | $('#imagefilename').html(''); 207 | $('#imagedim').html(''); 208 | 209 | if (_lineGroup != null) { 210 | _lineHolder.remove(_lineGroup); 211 | _lineGroup = null; 212 | } 213 | 214 | enableDropZone(true); 215 | 216 | // Reset camera/controls 217 | _camera.position.z = 400; 218 | _controls.reset(); 219 | } 220 | 221 | function onImageLoaded() { 222 | 223 | resetGUIOptions(); 224 | 225 | // load image into canvas pixels 226 | _imageWidth = _inputImage.width; 227 | _imageHeight = _inputImage.height; 228 | 229 | $('#imagedim').html(_imageWidth + ' x ' + _imageHeight); 230 | 231 | _canvas = document.createElement('canvas'); 232 | _canvas.width = _imageWidth 233 | _canvas.height = _imageHeight; 234 | 235 | _context = _canvas.getContext('2d'); 236 | _context.drawImage(_inputImage, 0, 0); 237 | 238 | _pixels = _context.getImageData(0,0,_imageWidth,_imageHeight).data; 239 | 240 | enableDropZone(false); // Hide while editing 241 | 242 | createLines(); 243 | } 244 | 245 | /** 246 | * Create Lines from image 247 | */ 248 | function createLines() { 249 | 250 | if (_inputImage == null) 251 | return; 252 | 253 | if (_lineGroup) 254 | _lineHolder.remove(_lineGroup); 255 | 256 | _lineGroup = new THREE.Object3D(); 257 | 258 | _material = new THREE.LineBasicMaterial({ 259 | color: 0xffffff, 260 | opacity: 1.0, 261 | linewidth: 3.0, //_guiOptions.lineThickness, 262 | //blending: THREE.AdditiveBlending, 263 | depthTest: false, 264 | vertexColors: true 265 | } ); 266 | 267 | var xSteps = Math.floor(_imageWidth / _guiOptions.pixelStep); 268 | var ySteps = Math.floor(_imageHeight / _guiOptions.pixelStep); 269 | 270 | var xStepsHalf = Math.floor(xSteps/2); 271 | var yStepsHalf = Math.floor(ySteps/2); 272 | 273 | // go through the image pixels. Note that Y == 0 is the top of the image. 274 | // First create lines along X axis 275 | for (var y1 = 0; y1 < ySteps; ++y1) { 276 | 277 | var geometry = new THREE.Geometry(); 278 | var yStepMesh = (yStepsHalf - y1 - 1) * _guiOptions.meshStep; 279 | 280 | for (var x1 = 0; x1 < xSteps; ++x1) { 281 | 282 | var color = getColor(x1 * _guiOptions.pixelStep, y1 * _guiOptions.pixelStep); 283 | var brightness = getBrightness(color); // 0 - 1 284 | 285 | var zHeight = brightness * _guiOptions.maxHeight; 286 | 287 | var xStepMesh = (x1 - xStepsHalf) * _guiOptions.meshStep; 288 | 289 | geometry.vertices.push(new THREE.Vector3(xStepMesh, yStepMesh, zHeight)); 290 | geometry.colors.push(color); 291 | } 292 | 293 | //add a line along X axis 294 | _lineGroup.add(new THREE.Line(geometry, _material)); 295 | } 296 | 297 | // Now create lines along Y axis 298 | for (var x2 = 0; x2 < xSteps; ++x2) { 299 | 300 | var geometry = new THREE.Geometry(); 301 | var xStepMesh = (x2 - xStepsHalf) * _guiOptions.meshStep; 302 | 303 | for (var y2 = 0; y2 < ySteps; ++y2) { 304 | 305 | var color = getColor(x2 * _guiOptions.pixelStep, y2 * _guiOptions.pixelStep); 306 | var brightness = getBrightness(color); // 0 - 1 307 | 308 | var zHeight = brightness * _guiOptions.maxHeight; 309 | 310 | var yStepMesh = (yStepsHalf - y2 - 1) * _guiOptions.meshStep; 311 | 312 | geometry.vertices.push(new THREE.Vector3(xStepMesh, yStepMesh, zHeight)); 313 | geometry.colors.push(color); 314 | } 315 | 316 | //add a line along Y axis 317 | _lineGroup.add(new THREE.Line(geometry, _material)); 318 | } 319 | 320 | _lineHolder.add(_lineGroup); 321 | 322 | // Calc surface/mesh dimensions but round to 2 decimal places 323 | var surfaceWidth = parseFloat(Math.round((xSteps * _guiOptions.meshStep) * 100) / 100).toFixed(2); 324 | var surfaceHeight = parseFloat(Math.round((ySteps * _guiOptions.meshStep) * 100) / 100).toFixed(2); 325 | $('#surfacedim').html(surfaceWidth + ' x ' + surfaceHeight + ' mms'); 326 | } 327 | 328 | // Returns an array containing height data normalized to the specified height value. 329 | function getHeightData() { 330 | 331 | var xSteps = Math.floor(_imageWidth / _guiOptions.pixelStep); 332 | var ySteps = Math.floor(_imageHeight / _guiOptions.pixelStep); 333 | 334 | var heightData = new Float32Array( xSteps * ySteps ); 335 | 336 | var idxHeight = 0; 337 | 338 | // Note that we need to step from bottom to top since image data is 339 | // top->bottom but model data is bottom->top 340 | for (var y = ySteps - 1; y >= 0; --y) { 341 | var yStep = y * _guiOptions.pixelStep; 342 | 343 | for (var x = 0; x < xSteps; ++x) { 344 | var xStep = x * _guiOptions.pixelStep; 345 | 346 | var color = getColor(xStep, yStep); 347 | var brightness = getBrightness(color); // val 0 - 1 348 | 349 | heightData[idxHeight++] = brightness * _guiOptions.maxHeight; 350 | } 351 | } 352 | 353 | return { data: heightData, width: xSteps, height: ySteps }; 354 | } 355 | 356 | // Called from html page 357 | function createMeshOBJString() { 358 | 359 | render(); 360 | 361 | // Get the height data from the image 362 | var imageHeightData = getHeightData(); 363 | if (imageHeightData < 1) 364 | return ""; 365 | 366 | // Generate the mesh for the height data. Use quads as Fusion hates tris. 367 | var mesh = Utils.createMesh(imageHeightData.data, imageHeightData.width, imageHeightData.height, _guiOptions.meshStep, true /*isQuad*/); 368 | 369 | // Now generate a string containing the OBJ file contents 370 | return Utils.createOBJString("", mesh); 371 | } 372 | 373 | function onKeyDown(evt) { 374 | //'S' key 375 | //if (event.keyCode == '83') { 376 | // onWindowResize(); 377 | //} 378 | } 379 | 380 | function animate() { 381 | requestAnimationFrame(animate); 382 | _controls.update(); 383 | render(); 384 | } 385 | 386 | function onWindowResize() { 387 | _camera.aspect = window.innerWidth / window.innerHeight; 388 | _camera.updateProjectionMatrix(); 389 | _renderer.setSize( window.innerWidth, window.innerHeight, false ); 390 | _controls.handleResize(); 391 | render(); 392 | } 393 | 394 | function render() { 395 | _renderer.render(_scene, _camera); 396 | } 397 | 398 | // Returns a Color for a given pixel in the pixel array. 399 | // Index is X (left to right), Y (top to bottom) 400 | function getColor(x, y) { 401 | var base = (Math.floor(y) * _imageWidth + Math.floor(x)) * 4; 402 | var c = { 403 | r: _pixels[base + 0], 404 | g: _pixels[base + 1], 405 | b: _pixels[base + 2], 406 | a: _pixels[base + 3] // REVIEW: Use alpha in calc? 407 | }; 408 | if (_guiOptions.smoothing&&x>0&&y>0&&x<_imageWidth-1&&y<_imageHeight-1) { 409 | //console.log( 'X:', x ); 410 | 411 | var left = ((Math.floor(y) * _imageWidth + Math.floor(x-1)) * 4); 412 | var leftup = ((Math.floor(y-1) * _imageWidth + Math.floor(x-1)) * 4); 413 | var leftdown = ((Math.floor(y+1) * _imageWidth + Math.floor(x-1)) * 4); 414 | var right = ((Math.floor(y) * _imageWidth + Math.floor(x+1)) * 4); 415 | var rightup = ((Math.floor(y-1) * _imageWidth + Math.floor(x+1)) * 4); 416 | var rightdown = ((Math.floor(y+1) * _imageWidth + Math.floor(x+1)) * 4); 417 | var up = ((Math.floor(y-1) * _imageWidth + Math.floor(x)) * 4); 418 | var down = ((Math.floor(y+1) * _imageWidth + Math.floor(x)) * 4); 419 | 420 | c.r+=_pixels[left+0]+_pixels[right+0]+_pixels[up+0]+_pixels[down+0]+_pixels[leftup+0]+_pixels[leftdown+0]+_pixels[rightup+0]+_pixels[rightdown+0]; 421 | c.g+=_pixels[left+1]+_pixels[right+1]+_pixels[up+1]+_pixels[down+1]+_pixels[leftup+1]+_pixels[leftdown+1]+_pixels[rightup+1]+_pixels[rightdown+1]; 422 | c.b+=_pixels[left+2]+_pixels[right+2]+_pixels[up+2]+_pixels[down+2]+_pixels[leftup+2]+_pixels[leftdown+2]+_pixels[rightup+2]+_pixels[rightdown+2]; 423 | 424 | c.r/=9; 425 | c.g/=9; 426 | c.b/=9; 427 | } 428 | 429 | // Init with rgb (0-1) 430 | return new THREE.Color(c.r/255, c.g/255, c.b/255); 431 | } 432 | 433 | 434 | //return pixel brightness between 0 and 1 based on human perceptual bias 435 | function getBrightness(c) { 436 | var brightness = 0.0 437 | if(_guiOptions.absolute) { 438 | brightness = (c.r + c.g + c.b)/3.0; 439 | } else { 440 | brightness = ( 0.34 * c.r + 0.5 * c.g + 0.16 * c.b ); 441 | } 442 | // console.log('r:' +c.r + 'g:' + c.g + 'b:' + c.b); 443 | // console.log(brightness); 444 | if (_guiOptions.invert) 445 | brightness = 1.0 - brightness; 446 | return brightness; 447 | } 448 | 449 | function enableDropZone(flag) { 450 | var dz = $('#dropzone'); 451 | if (flag && typeof(FileReader) != "undefined") 452 | dz.css({ display: "block" }); 453 | else 454 | dz.css({ display: "none" }); 455 | } 456 | -------------------------------------------------------------------------------- /js/jquery.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery JavaScript Library v1.5.1 3 | * http://jquery.com/ 4 | * 5 | * Copyright 2011, John Resig 6 | * Dual licensed under the MIT or GPL Version 2 licenses. 7 | * http://jquery.org/license 8 | * 9 | * Includes Sizzle.js 10 | * http://sizzlejs.com/ 11 | * Copyright 2011, The Dojo Foundation 12 | * Released under the MIT, BSD, and GPL Licenses. 13 | * 14 | * Date: Wed Feb 23 13:55:29 2011 -0500 15 | */ 16 | (function(a,b){function cg(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cd(a){if(!bZ[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";bZ[a]=c}return bZ[a]}function cc(a,b){var c={};d.each(cb.concat.apply([],cb.slice(0,b)),function(){c[this]=a});return c}function bY(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bX(){try{return new a.XMLHttpRequest}catch(b){}}function bW(){d(a).unload(function(){for(var a in bU)bU[a](0,1)})}function bQ(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g=0===c})}function N(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function F(a,b){return(a&&a!=="*"?a+".":"")+b.replace(r,"`").replace(s,"&")}function E(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,q=[],r=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;ic)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function C(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function w(){return!0}function v(){return!1}function g(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function f(a,c,f){if(f===b&&a.nodeType===1){f=a.getAttribute("data-"+c);if(typeof f==="string"){try{f=f==="true"?!0:f==="false"?!1:f==="null"?null:d.isNaN(f)?e.test(f)?d.parseJSON(f):f:parseFloat(f)}catch(g){}d.data(a,c,f)}else f=b}return f}var c=a.document,d=function(){function I(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(I,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,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=navigator.userAgent,w,x=!1,y,z="then done fail isResolved isRejected promise".split(" "),A,B=Object.prototype.toString,C=Object.prototype.hasOwnProperty,D=Array.prototype.push,E=Array.prototype.slice,F=String.prototype.trim,G=Array.prototype.indexOf,H={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.1",length:0,size:function(){return this.length},toArray:function(){return E.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 e=this.constructor();d.isArray(a)?D.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),y.done(a);return this},eq:function(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(E.apply(this,arguments),"slice",E.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:D,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,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"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=!0;if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",A,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",A),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&I()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):H[B.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!C.call(a,"constructor")&&!C.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||C.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g1){var f=E.call(arguments,0),g=b,h=function(a){return function(b){f[a]=arguments.length>1?E.call(arguments,0):b,--g||c.resolveWith(e,f)}};while(b--)a=f[b],a&&d.isFunction(a.promise)?a.promise().then(h(b),c.reject):--g;g||c.resolveWith(e,f)}else c!==a&&c.resolve(a);return e},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}d.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.subclass=this.subclass,a.fn.init=function b(b,c){c&&c instanceof d&&!(c instanceof a)&&(c=a(c));return d.fn.init.call(this,b,c,e)},a.fn.init.prototype=a.fn;var e=a(c);return a},browser:{}}),y=d._Deferred(),d.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){H["[object "+b+"]"]=b.toLowerCase()}),w=d.uaMatch(v),w.browser&&(d.browser[w.browser]=!0,d.browser.version=w.version),d.browser.webkit&&(d.browser.safari=!0),G&&(d.inArray=function(a,b){return G.call(b,a)}),i.test(" ")&&(j=/^[\s\xA0]+/,k=/[\s\xA0]+$/),g=d(c),c.addEventListener?A=function(){c.removeEventListener("DOMContentLoaded",A,!1),d.ready()}:c.attachEvent&&(A=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",A),d.ready())});return d}();(function(){d.support={};var b=c.createElement("div");b.style.display="none",b.innerHTML="
a";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e),b=e=f=null}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function"),b=null;return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}})();var e=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.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?d.cache[a[d.expando]]:a[d.expando];return!!a&&!g(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,h=b.nodeType,i=h?d.cache:b,j=h?b[d.expando]:d.expando;if(!i[j])return;if(c){var k=e?i[j][f]:i[j];if(k){delete k[c];if(!g(k))return}}if(e){delete i[j][f];if(!g(i[j]))return}var l=i[j][f];d.support.deleteExpando||i!=a?delete i[j]:i[j]=null,l?(i[j]={},h||(i[j].toJSON=d.noop),i[j][f]=l):h&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var g=this[0].attributes,h;for(var i=0,j=g.length;i-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var k=i?f:0,l=i?f+1:h.length;k=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=k.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&l.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var o=a.getAttributeNode("tabIndex");return o&&o.specified?o.value:m.test(a.nodeName)||n.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var p=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return p===null?b:p}h&&(a[c]=e);return a[c]}});var p=/\.(.*)$/,q=/^(?:textarea|input|select)$/i,r=/\./g,s=/ /g,t=/[^\w\s.|`]/g,u=function(a){return a.replace(t,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=v;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(){return typeof d!=="undefined"&&!d.event.triggered?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=v);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),u).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(p,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=!0,l[m]())}catch(q){}k&&(l["on"+m]=k),d.event.triggered=!1}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},B=function B(a){var c=a.target,e,f;if(q.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=A(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:B,beforedeactivate:B,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&B.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&B.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",A(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in z)d.event.add(this,c+".specialChange",z[c]);return q.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return q.test(this.nodeName)}},z=d.event.special.change.filters,z.focus=z.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function c(a){a=d.event.fix(a),a.type=b;return d.event.handle.call(this,a)}d.event.special[b]={setup:function(){this.addEventListener(a,c,!0)},teardown:function(){this.removeEventListener(a,c,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){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,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.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(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.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]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),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]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.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!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){return"text"===a.getAttribute("type")},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},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=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([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.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":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=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=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(q){p=function(a,b){var c=0,d=b||[];if(f.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)&&(l.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:[]}},l.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&&(l.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")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector,d=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(e){d=!0}b&&(k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(d||!l.match.PSEUDO.test(c)&&!/!=/.test(c))return b.call(a,c)}catch(e){}return k(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;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(var g=c;g0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=L.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(N(c[0])||N(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=K.call(arguments);G.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!M[a]?d.unique(f):f,(this.length>1||I.test(e))&&H.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},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 P=/ jQuery\d+="(?:\d+|null)"/g,Q=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,S=/<([\w:]+)/,T=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};X.optgroup=X.option,X.tbody=X.tfoot=X.colgroup=X.caption=X.thead,X.th=X.td,d.support.htmlSerialize||(X._default=[1,"div
","
"]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(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 d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(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(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(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=d(arguments[0]);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,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.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 d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(P,""):null;if(typeof a!=="string"||V.test(a)||!d.support.leadingWhitespace&&Q.test(a)||X[(S.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(R,"<$1>");try{for(var c=0,e=this.length;c1&&l0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){$(a,e),f=_(a),g=_(e);for(h=0;f[h];++h)$(f[h],g[h])}if(b){Z(a,e);if(c){f=_(a),g=_(e);for(h=0;f[h];++h)Z(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||U.test(i)){if(typeof i==="string"){i=i.replace(R,"<$1>");var j=(S.exec(i)||["",""])[1].toLowerCase(),k=X[j]||X._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=T.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]===""&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&Q.test(i)&&m.insertBefore(b.createTextNode(Q.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bb=/alpha\([^)]*\)/i,bc=/opacity=([^)]*)/,bd=/-([a-z])/ig,be=/([A-Z])/g,bf=/^-?\d+(?:px)?$/i,bg=/^-?\d/,bh={position:"absolute",visibility:"hidden",display:"block"},bi=["Left","Right"],bj=["Top","Bottom"],bk,bl,bm,bn=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bk(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bk)return bk(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bd,bn)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bo(a,b,e):d.swap(a,bh,function(){f=bo(a,b,e)});if(f<=0){f=bk(a,b,b),f==="0px"&&bm&&(f=bm(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bf.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return bc.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bb.test(f)?f.replace(bb,e):c.filter+" "+e}}),c.defaultView&&c.defaultView.getComputedStyle&&(bl=function(a,c,e){var f,g,h;e=e.replace(be,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bm=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bf.test(d)&&bg.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bk=bl||bm,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var bp=/%20/g,bq=/\[\]$/,br=/\r?\n/g,bs=/#.*$/,bt=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bu=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bv=/(?:^file|^widget|\-extension):$/,bw=/^(?:GET|HEAD)$/,bx=/^\/\//,by=/\?/,bz=/)<[^<]*)*<\/script>/gi,bA=/^(?:select|textarea)/i,bB=/\s+/,bC=/([?&])_=[^&]*/,bD=/(^|\-)([a-z])/g,bE=function(a,b,c){return b+c.toUpperCase()},bF=/^([\w\+\.\-]+:)\/\/([^\/?#:]*)(?::(\d+))?/,bG=d.fn.load,bH={},bI={},bJ,bK;try{bJ=c.location.href}catch(bL){bJ=c.createElement("a"),bJ.href="",bJ=bJ.href}bK=bF.exec(bJ.toLowerCase()),d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bG)return bG.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.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?d("
").append(c.replace(bz,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bA.test(this.nodeName)||bu.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(br,"\r\n")}}):{name:b.name,value:c.replace(br,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bJ,isLocal:bv.test(bK[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","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bM(bH),ajaxTransport:bM(bI),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bP(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bQ(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bD,bE)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bt.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bs,"").replace(bx,bK[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bB),e.crossDomain||(q=bF.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bK[1]||q[2]!=bK[2]||(q[3]||(q[1]==="http:"?80:443))!=(bK[3]||(bK[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bN(bH,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!bw.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(by.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bC,"$1_="+w);e.url=x+(x===e.url?(by.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bN(bI,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bO(g,a[g],c,f);return e.join("&").replace(bp,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bR=d.now(),bS=/(\=)\?(&|$)|()\?\?()/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bR++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bS.test(b.url)||f&&bS.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bS,l),b.url===j&&(f&&(k=k.replace(bS,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.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(!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 bT=d.now(),bU,bV;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bX()||bY()}:bX,bV=d.ajaxSettings.xhr(),d.support.ajax=!!bV,d.support.cors=bV&&"withCredentials"in bV,bV=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),(!a.crossDomain||a.hasContent)&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bU[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bU||(bU={},bW()),h=bT++,g.onreadystatechange=bU[h]=c):c()},abort:function(){c&&c(0,1)}}}});var bZ={},b$=/^(?:toggle|show|hide)$/,b_=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,ca,cb=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(cc("show",3),a,b,c);for(var g=0,h=this.length;g=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:cc("show",1),slideUp:cc("hide",1),slideToggle:cc("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!ca&&(ca=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b
";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),a=b=e=f=g=h=null,d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=e==="absolute"&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.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):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=cf.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!cf.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=cg(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=cg(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window); -------------------------------------------------------------------------------- /js/jquery.mousewheel.min.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net) 2 | * Licensed under the MIT License (LICENSE.txt). 3 | * 4 | * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 5 | * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6 | * Thanks to: Seamus Leahy for adding deltaX and deltaY 7 | * 8 | * Version: 3.0.4 9 | * 10 | * Requires: 1.2.2+ 11 | */ 12 | (function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(i){var g=i||window.event,f=[].slice.call(arguments,1),j=0,h=true,e=0,d=0;i=c.event.fix(g);i.type="mousewheel";if(i.wheelDelta){j=i.wheelDelta/120}if(i.detail){j=-i.detail/3}d=j;if(g.axis!==undefined&&g.axis===g.HORIZONTAL_AXIS){d=0;e=-1*j}if(g.wheelDeltaY!==undefined){d=g.wheelDeltaY/120}if(g.wheelDeltaX!==undefined){e=-1*g.wheelDeltaX/120}f.unshift(i,j,e,d);return c.event.handle.apply(this,f)}})(jQuery); --------------------------------------------------------------------------------