├── .classpath ├── .gitignore ├── .project ├── README.md ├── data └── README ├── examples ├── BasicExample │ ├── BasicExample.pde │ └── data │ │ └── stereo.jpg ├── PanoramaView │ ├── PanoramaSphere.pde │ ├── PanoramaView.pde │ └── data │ │ └── panorama.jpg ├── RadarExample │ └── RadarExample.pde └── VideoSeeThrough │ └── VideoSeeThrough.pde ├── lib ├── README ├── jna.jar └── jovr-0.7.0.0.jar ├── license.txt ├── resources ├── README.md ├── build.properties ├── build.xml ├── code │ ├── ExampleTaglet.class │ ├── ExampleTaglet.java │ ├── ant-contrib-1.0b3.jar │ └── doc.sh ├── library.properties └── stylesheet.css ├── src └── oculus │ ├── OculusRift.java │ └── shaders │ └── barrel_frag.glsl └── web ├── index.html └── stylesheet.css /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | tmp 3 | distribution 4 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | processing-oculus 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Oculus library for Processing 2 | 3 | Wraps Sunao Hashimoto's [OculusRiftP5](https://github.com/kougaku/OculusRiftP5) project as a stand-alone library. 4 | 5 | Uses JOVR ([source](https://github.com/jherico/jovr), [binaries](http://mvnrepository.com/artifact/org.saintandreas/jovr)), the Java bindings for the Oculus Rift head tracker. 6 | -------------------------------------------------------------------------------- /data/README: -------------------------------------------------------------------------------- 1 | the data folder: 2 | If your library is using files like images, sound files, 3 | any data file, etc., put them into the data folder. 4 | When coding your library you can use processing's internal loading 5 | functions like loadImage(), loadStrings(), etc. to load files 6 | located inside the data folder into your library. 7 | 8 | -------------------------------------------------------------------------------- /examples/BasicExample/BasicExample.pde: -------------------------------------------------------------------------------- 1 | // This example shows simple scene that contains a wall, 2 | // a floorboard, a cube, and stereo picture. 3 | // Author: Sunao Hashimoto (https://github.com/kougaku) 4 | 5 | import oculus.*; 6 | 7 | PImage imgL; 8 | PImage imgR; 9 | PVector position; 10 | 11 | OculusRift oculus; 12 | 13 | void setup() { 14 | fullScreen(OculusRift.RENDERER); 15 | oculus = (OculusRift)g; 16 | oculus.enableHeadTracking(); 17 | 18 | PImage img = loadImage("stereo.jpg"); 19 | imgL = img.get(0, 0, img.width/2, img.height); 20 | imgR = img.get(img.width/2, 0, img.width/2, img.height); 21 | 22 | position = new PVector(0, 1200, 0); // 1200 mm from floor. 23 | } 24 | 25 | void draw() { 26 | text("framerate: " + frameRate, 20, 20); 27 | } 28 | 29 | // Draw the scene for each eye 30 | void draw(int eye) { 31 | // The scale is approximately real scale. The unit is a millimeter. 32 | // The default eye position is on the origin (0, 0, 0) in the scene. 33 | // The parameter "eye" gives LEFT or RIGHT. 34 | 35 | background(50); 36 | fill(255); 37 | translate(position.x, position.y, position.z); 38 | 39 | // picture 40 | pushMatrix(); 41 | translate(0, -1500, -1800); 42 | imageMode(CENTER); 43 | scale(3.0); 44 | if (eye == LEFT) { 45 | image(imgL, 0, 0); 46 | } else if (eye == RIGHT) { 47 | image(imgR, 0, 0); 48 | } 49 | popMatrix(); 50 | 51 | // light 52 | lights(); 53 | 54 | // floor 55 | pushMatrix(); 56 | rotateX(radians(90)); 57 | drawPlate(4000, 4000, 500); 58 | popMatrix(); 59 | 60 | // wall 61 | pushMatrix(); 62 | translate(0, -1500, -2000); 63 | drawPlate(4000, 3000, 500); 64 | popMatrix(); 65 | 66 | // cube 67 | pushMatrix(); 68 | translate(0, -500, -800); 69 | fill(50, 200, 50); 70 | rotateX(millis()/1000.0); 71 | rotateY(millis()/900.0); 72 | box(200); 73 | popMatrix(); 74 | } 75 | 76 | void drawPlate(float w, float h, float grid_interval) { 77 | for (float x=-w/2; x>> 63 | float changeV = t.height/(float)(numPointsH-1); 64 | float v = 0; // Height variable for the texture 65 | 66 | beginShape(TRIANGLE_STRIP); 67 | texture(t); 68 | for (int i=0; i< (numPointsH-1); i++) { // For all the rings but top and bottom 69 | // Goes into the array here instead of loop to save time 70 | float coory = coorY[i]; 71 | float cooryPlus = coorY[i+1]; 72 | 73 | float multxz = multXZ[i]; 74 | float multxzPlus = multXZ[i+1]; 75 | float u = t.width; // Width variable for the texture <<< flip horizontal >>> 76 | 77 | for (int j=0; j 2 | 3 | 4 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ${ant.description} 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | ${line} 81 | Building the Processing library ${project.name} ${library.version} 82 | ${line} 83 | src path ${project.src} 84 | bin path ${project.bin} 85 | classpath.local ${classpath.local.location} 86 | sketchbook ${sketchbook.location} 87 | java version ${java.target.version} 88 | ${line} 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | ${exampleDir} 347 | 353 | 354 | 360 | 361 | 362 | 363 | 364 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | ${line} 383 | Name ${project.name} 384 | Version ${library.prettyVersion} (${library.version}) 385 | Compiled ${project.compile} 386 | Sketchbook ${sketchbook.location} 387 | ${line} 388 | done, finished. 389 | ${line} 390 | 391 | 392 | 393 | 394 | 395 | -------------------------------------------------------------------------------- /resources/code/ExampleTaglet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeanticode/processing-oculus/a6248a254c9802137a0eb59f0d9b9769c1b0ede5/resources/code/ExampleTaglet.class -------------------------------------------------------------------------------- /resources/code/ExampleTaglet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or 5 | * without modification, are permitted provided that the following 6 | * conditions are met: 7 | * 8 | * -Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 11 | * -Redistribution in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in 13 | * the documentation and/or other materials provided with the 14 | * distribution. 15 | * 16 | * Neither the name of Sun Microsystems, Inc. or the names of 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * This software is provided "AS IS," without a warranty of any 21 | * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 22 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY 24 | * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY 25 | * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR 26 | * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR 27 | * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE 28 | * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, 29 | * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER 30 | * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF 31 | * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN 32 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 33 | * 34 | * You acknowledge that Software is not designed, licensed or 35 | * intended for use in the design, construction, operation or 36 | * maintenance of any nuclear facility. 37 | */ 38 | 39 | import com.sun.tools.doclets.Taglet; 40 | import com.sun.javadoc.*; 41 | import java.util.Map; 42 | import java.io.*; 43 | /** 44 | * A sample Taglet representing @example. This tag can be used in any kind of 45 | * {@link com.sun.javadoc.Doc}. It is not an inline tag. The text is displayed 46 | * in yellow to remind the developer to perform a task. For 47 | * example, "@example Hello" would be shown as: 48 | *
49 | *
50 | * To Do: 51 | *
Fix this! 52 | *
53 | *
54 | * 55 | * @author Jamie Ho 56 | * @since 1.4 57 | */ 58 | 59 | public class ExampleTaglet implements Taglet { 60 | 61 | private static final String NAME = "example"; 62 | private static final String HEADER = "example To Do:"; 63 | 64 | /** 65 | * Return the name of this custom tag. 66 | */ 67 | public String getName() { 68 | return NAME; 69 | } 70 | 71 | /** 72 | * Will return true since @example 73 | * can be used in field documentation. 74 | * @return true since @example 75 | * can be used in field documentation and false 76 | * otherwise. 77 | */ 78 | public boolean inField() { 79 | return true; 80 | } 81 | 82 | /** 83 | * Will return true since @example 84 | * can be used in constructor documentation. 85 | * @return true since @example 86 | * can be used in constructor documentation and false 87 | * otherwise. 88 | */ 89 | public boolean inConstructor() { 90 | return true; 91 | } 92 | 93 | /** 94 | * Will return true since @example 95 | * can be used in method documentation. 96 | * @return true since @example 97 | * can be used in method documentation and false 98 | * otherwise. 99 | */ 100 | public boolean inMethod() { 101 | return true; 102 | } 103 | 104 | /** 105 | * Will return true since @example 106 | * can be used in method documentation. 107 | * @return true since @example 108 | * can be used in overview documentation and false 109 | * otherwise. 110 | */ 111 | public boolean inOverview() { 112 | return true; 113 | } 114 | 115 | /** 116 | * Will return true since @example 117 | * can be used in package documentation. 118 | * @return true since @example 119 | * can be used in package documentation and false 120 | * otherwise. 121 | */ 122 | public boolean inPackage() { 123 | return true; 124 | } 125 | 126 | /** 127 | * Will return true since @example 128 | * can be used in type documentation (classes or interfaces). 129 | * @return true since @example 130 | * can be used in type documentation and false 131 | * otherwise. 132 | */ 133 | public boolean inType() { 134 | return true; 135 | } 136 | 137 | /** 138 | * Will return false since @example 139 | * is not an inline tag. 140 | * @return false since @example 141 | * is not an inline tag. 142 | */ 143 | 144 | public boolean isInlineTag() { 145 | return false; 146 | } 147 | 148 | /** 149 | * Register this Taglet. 150 | * @param tagletMap the map to register this tag to. 151 | */ 152 | public static void register(Map tagletMap) { 153 | ExampleTaglet tag = new ExampleTaglet(); 154 | Taglet t = (Taglet) tagletMap.get(tag.getName()); 155 | if (t != null) { 156 | tagletMap.remove(tag.getName()); 157 | } 158 | tagletMap.put(tag.getName(), tag); 159 | } 160 | 161 | /** 162 | * Given the Tag representation of this custom 163 | * tag, return its string representation. 164 | * @param tag the Tag representation of this custom tag. 165 | */ 166 | public String toString(Tag tag) { 167 | return createHTML(readFile(tag.text())); 168 | } 169 | 170 | 171 | /** 172 | * Given an array of Tags representing this custom 173 | * tag, return its string representation. 174 | * @param tags the array of Tags representing of this custom tag. 175 | */ 176 | public String toString(Tag[] tags) { 177 | if (tags.length == 0) { 178 | return null; 179 | } 180 | return createHTML(readFile(tags[0].text())); 181 | } 182 | 183 | 184 | 185 | String createHTML(String theString) { 186 | if(theString!=null) { 187 | String dd = ""; 193 | 194 | return dd+"\n
" + 195 | "
+Example
" + 196 | "
"+theString+"
" + 197 | "
"; 198 | } 199 | return ""; 200 | } 201 | 202 | 203 | /** 204 | * check if the examples directory exists and return the example as given in the tag. 205 | * @param theExample the name of the example 206 | */ 207 | String readFile(String theExample) { 208 | String record = ""; 209 | String myResult = ""; 210 | int recCount = 0; 211 | String myDir = "../examples"; 212 | File file=new File(myDir); 213 | if(file.exists()==false) { 214 | myDir = "./examples"; 215 | } 216 | try { 217 | FileReader fr = new FileReader(myDir+"/"+theExample+"/"+theExample+".pde"); 218 | BufferedReader br = new BufferedReader(fr); 219 | record = new String(); 220 | while ((record = br.readLine()) != null) { 221 | myResult += record+"\n"; 222 | } 223 | } catch (IOException e) { 224 | System.out.println(e); 225 | return null; 226 | } 227 | return myResult; 228 | } 229 | } 230 | 231 | 232 | -------------------------------------------------------------------------------- /resources/code/ant-contrib-1.0b3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeanticode/processing-oculus/a6248a254c9802137a0eb59f0d9b9769c1b0ede5/resources/code/ant-contrib-1.0b3.jar -------------------------------------------------------------------------------- /resources/code/doc.sh: -------------------------------------------------------------------------------- 1 | # a shell script to create a java documentation 2 | # for a processing library. 3 | # 4 | # make changes to the variables below so they 5 | # fit the structure of your library 6 | 7 | # the package name of your library 8 | package=template; 9 | 10 | # source folder location 11 | src=../src; 12 | 13 | # the destination folder of your documentation 14 | dest=../documentation; 15 | 16 | 17 | # compile the java documentation 18 | javadoc -d $dest -stylesheetfile ./stylesheet.css -sourcepath ${src} ${package} 19 | -------------------------------------------------------------------------------- /resources/library.properties: -------------------------------------------------------------------------------- 1 | # More on this file here: https://github.com/processing/processing/wiki/Library-Basics 2 | # UTF-8 supported. 3 | 4 | # The name of your library as you want it formatted. 5 | name = ##library.name## 6 | 7 | # List of authors. Links can be provided using the syntax [author name](url). 8 | authors = [##author.name##](##author.url##) 9 | 10 | # A web page for your library, NOT a direct link to where to download it. 11 | url = ##library.url## 12 | 13 | # The category (or categories) of your library, must be from the following list: 14 | # "3D" "Animation" "Compilations" "Data" 15 | # "Fabrication" "Geometry" "GUI" "Hardware" 16 | # "I/O" "Language" "Math" "Simulation" 17 | # "Sound" "Utilities" "Typography" "Video & Vision" 18 | # 19 | # If a value other than those listed is used, your library will listed as 20 | # "Other". Many categories must be comma-separated. 21 | categories = ##library.categories## 22 | 23 | # A short sentence (or fragment) to summarize the library's function. This will 24 | # be shown from inside the PDE when the library is being installed. Avoid 25 | # repeating the name of your library here. Also, avoid saying anything redundant 26 | # like mentioning that it's a library. This should start with a capitalized 27 | # letter, and end with a period. 28 | sentence = ##library.sentence## 29 | 30 | # Additional information suitable for the Processing website. The value of 31 | # 'sentence' always will be prepended, so you should start by writing the 32 | # second sentence here. If your library only works on certain operating systems, 33 | # mention it here. 34 | paragraph = ##library.paragraph## 35 | 36 | # Links in the 'sentence' and 'paragraph' attributes can be inserted using the 37 | # same syntax as for authors. 38 | # That is, [here is a link to Processing](http://processing.org/) 39 | 40 | # A version number that increments once with each release. This is used to 41 | # compare different versions of the same library, and check if an update is 42 | # available. You should think of it as a counter, counting the total number of 43 | # releases you've had. 44 | version = ##library.version## # This must be parsable as an int 45 | 46 | # The version as the user will see it. If blank, the version attribute will be 47 | # used here. This should be a single word, with no spaces. 48 | prettyVersion = ##library.prettyVersion## # This is treated as a String 49 | 50 | # The min and max revision of Processing compatible with your library. 51 | # Note that these fields use the revision and not the version of Processing, 52 | # parsable as an int. For example, the revision number for 2.2.1 is 227. 53 | # You can find the revision numbers in the change log: https://raw.githubusercontent.com/processing/processing/master/build/shared/revisions.txt 54 | # Only use maxRevision (or minRevision), when your library is known to 55 | # break in a later (or earlier) release. Otherwise, use the default value 0. 56 | minRevision = ##compatible.minRevision## 57 | maxRevision = ##compatible.maxRevision## 58 | -------------------------------------------------------------------------------- /resources/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* Javadoc style sheet */ 2 | /* Define colors, fonts and other style attributes here to override the defaults */ 3 | /* processingLibs style by andreas schlegel, sojamo */ 4 | 5 | 6 | body { 7 | margin : 0; 8 | padding : 0; 9 | padding-left : 10px; 10 | padding-right : 8px; 11 | background-color : #FFFFFF; 12 | font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; 13 | font-size : 100%; 14 | font-size : 0.7em; 15 | font-weight : normal; 16 | line-height : normal; 17 | margin-bottom:30px; 18 | } 19 | 20 | 21 | 22 | 23 | /* Headings */ 24 | h1, h2, h3, h4, h5, th { 25 | font-family :Arial, Helvetica, sans-serif; 26 | font-size:1.2em; 27 | } 28 | 29 | 30 | p { 31 | font-size : 1em; 32 | width:80%; 33 | } 34 | 35 | pre, code { 36 | font-family : "Courier New", Courier, monospace; 37 | font-size : 12px; 38 | line-height : normal; 39 | } 40 | 41 | 42 | 43 | table { 44 | border:0; 45 | margin-bottom:10px; 46 | margin-top:10px; 47 | } 48 | 49 | 50 | tr, td { 51 | border-top: 0px solid; 52 | border-left: 0px solid; 53 | padding-top:8px; 54 | padding-bottom:8px; 55 | } 56 | 57 | 58 | 59 | hr { 60 | border:0; 61 | height:1px; 62 | padding:0; 63 | margin:0; 64 | margin-bottom:4px; 65 | 66 | } 67 | 68 | 69 | 70 | dd, th, td, font { 71 | font-size:1.0em; 72 | line-height:1.0em; 73 | } 74 | 75 | 76 | 77 | dt { 78 | margin-bottom:0px; 79 | } 80 | 81 | 82 | 83 | dd { 84 | margin-top:2px; 85 | margin-bottom:4px; 86 | } 87 | 88 | 89 | 90 | a { 91 | text-decoration: underline; 92 | font-weight: normal; 93 | } 94 | 95 | a:hover, 96 | a:active { 97 | text-decoration: underline; 98 | font-weight: normal; 99 | } 100 | 101 | a:visited, 102 | a:link:visited { 103 | text-decoration: underline; 104 | font-weight: normal; 105 | } 106 | 107 | 108 | img { 109 | border: 0px solid #000000; 110 | } 111 | 112 | 113 | 114 | /* Navigation bar fonts */ 115 | .NavBarCell1 { 116 | border:0; 117 | } 118 | 119 | .NavBarCell1Rev { 120 | border:0; 121 | } 122 | 123 | .NavBarFont1 { 124 | font-family: Arial, Helvetica, sans-serif; 125 | font-size:1.1em; 126 | } 127 | 128 | 129 | .NavBarFont1 b { 130 | font-weight:normal; 131 | } 132 | 133 | 134 | 135 | .NavBarFont1:after, .NavBarFont1Rev:after { 136 | font-weight:normal; 137 | content: " \\"; 138 | } 139 | 140 | 141 | .NavBarFont1Rev { 142 | font-family: Arial, Helvetica, sans-serif; 143 | font-size:1.1em; 144 | } 145 | 146 | .NavBarFont1Rev b { 147 | font-family: Arial, Helvetica, sans-serif; 148 | font-size:1.1em; 149 | font-weight:normal; 150 | } 151 | 152 | .NavBarCell2 { 153 | font-family: Arial, Helvetica, sans-serif; 154 | } 155 | 156 | .NavBarCell3 { 157 | font-family: Arial, Helvetica, sans-serif; 158 | } 159 | 160 | 161 | 162 | font.FrameItemFont { 163 | font-family: Helvetica, Arial, sans-serif; 164 | font-size:1.1em; 165 | line-height:1.1em; 166 | } 167 | 168 | font.FrameHeadingFont { 169 | font-family: Helvetica, Arial, sans-serif; 170 | line-height:32px; 171 | } 172 | 173 | /* Font used in left-hand frame lists */ 174 | .FrameTitleFont { 175 | font-family: Helvetica, Arial, sans-serif 176 | } 177 | 178 | 179 | .toggleList { 180 | padding:0; 181 | margin:0; 182 | margin-top:12px; 183 | } 184 | 185 | .toggleList dt { 186 | font-weight:bold; 187 | font-size:12px; 188 | font-family:arial,sans-serif; 189 | padding:0px; 190 | margin:10px 0px 10px 0px; 191 | } 192 | 193 | .toggleList dt span { 194 | font-family: monospace; 195 | padding:0; 196 | margin:0; 197 | } 198 | 199 | 200 | .toggleList dd { 201 | margin:0; 202 | padding:0; 203 | } 204 | 205 | html.isjs .toggleList dd { 206 | display: none; 207 | } 208 | 209 | .toggleList pre { 210 | padding: 4px 4px 4px 4px; 211 | } 212 | 213 | 214 | 215 | 216 | 217 | /* COLORS */ 218 | 219 | pre, code { 220 | color: #000000; 221 | } 222 | 223 | 224 | body { 225 | color : #333333; 226 | background-color :#FFFFFF; 227 | } 228 | 229 | 230 | h1, h2, h3, h4, h5, h6 { 231 | color:#555; 232 | } 233 | 234 | a, 235 | .toggleList dt { 236 | color: #1a7eb0; 237 | } 238 | 239 | a:hover, 240 | a:active { 241 | color: #1a7eb0; 242 | } 243 | 244 | a:visited, 245 | a:link:visited { 246 | color: #1a7eb0; 247 | } 248 | 249 | td,tr { 250 | border-color: #999999; 251 | } 252 | 253 | hr { 254 | color:#999999; 255 | background:#999999; 256 | } 257 | 258 | 259 | .TableHeadingColor { 260 | background: #dcdcdc; 261 | color: #555; 262 | } 263 | 264 | 265 | .TableSubHeadingColor { 266 | background: #EEEEFF 267 | } 268 | 269 | .TableRowColor { 270 | background: #FFFFFF 271 | } 272 | 273 | 274 | .NavBarCell1 { 275 | background-color:#dcdcdc; 276 | color:#000; 277 | } 278 | 279 | .NavBarCell1 a { 280 | color:#333; 281 | } 282 | 283 | 284 | .NavBarCell1Rev { 285 | background-color:transparent; 286 | } 287 | 288 | .NavBarFont1 { 289 | color:#333; 290 | } 291 | 292 | 293 | .NavBarFont1Rev { 294 | color:#fff; 295 | } 296 | 297 | .NavBarCell2 { 298 | background-color:#999; 299 | } 300 | 301 | .NavBarCell2 a { 302 | color:#fff; 303 | } 304 | 305 | 306 | 307 | .NavBarCell3 { 308 | background-color:#dcdcdc; 309 | } 310 | 311 | -------------------------------------------------------------------------------- /src/oculus/OculusRift.java: -------------------------------------------------------------------------------- 1 | /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Copyright (c) 2015, Sunao Hashimoto All rights reserved. 5 | Adapted as a Processing library by Andres Colubri 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of the kougaku-navi nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | /* 31 | Thanks a lot for the following codes. 32 | 33 | jherico/jovr 34 | https://github.com/jherico/jovr 35 | 36 | JOVR – Java bindings for Oculus Rift SDK 0.4.2.0 | Laht's blog 37 | http://laht.info/jovr-java-bindings-for-oculus-rift-sdk-0-4-0/ 38 | 39 | ixd-hof/Processing 40 | https://github.com/ixd-hof/Processing/tree/master/Examples/Oculus%20Rift/OculusRift_Basic 41 | 42 | xohm/SimpleOculusRift 43 | https://github.com/xohm/SimpleOculusRift 44 | 45 | mactkg/pg_jack_p3d.pde 46 | https://gist.github.com/mactkg/66f99c9563c6a043e14e 47 | 48 | Solved: Using a Quaternion and Vector to construct a camera view matrix 49 | https://social.msdn.microsoft.com/Forums/en-US/ec92a231-2dbf-4f3e-b7f5-0a4d9ea4cae2 50 | */ 51 | 52 | package oculus; 53 | 54 | import processing.core.PApplet; 55 | import processing.core.PGraphics; 56 | import processing.core.PMatrix3D; 57 | import processing.opengl.PGraphics3D; 58 | import processing.opengl.PShader; 59 | 60 | import com.oculusvr.capi.Hmd; 61 | import com.oculusvr.capi.OvrQuaternionf; 62 | import com.oculusvr.capi.OvrVector3f; 63 | import com.oculusvr.capi.TrackingState; 64 | import java.lang.reflect.Method; 65 | import java.net.URL; 66 | 67 | public class OculusRift extends PGraphics3D { 68 | 69 | public final static String RENDERER = "oculus.OculusRift"; 70 | 71 | public int eyeWidth; 72 | public int eyeHeight; 73 | 74 | // Parameters for DK2 75 | private boolean initialized = false; 76 | 77 | private final int oculus_width = 1920; // for DK2 78 | private final int oculus_height = 1080; // for DK2 79 | private final float fov_deg = 100; // for DK2 80 | private final float z_near = 10; 81 | private final float z_far = 100000; 82 | 83 | private final float scaleFactor = 2.11f; 84 | private final float imageScaling = 2.27f; 85 | private final int imageShiftX = 437; 86 | private final int imageCutWidth = 0; 87 | private final float sensingScale = 1000.0f; // for millimeter 88 | 89 | private PGraphics pg_backup; 90 | private Method onDrawSceneMethod; 91 | 92 | private PGraphics scene; 93 | private PGraphics fb; 94 | private PShader barrel; 95 | 96 | private Hmd hmd; 97 | private boolean isUsingHeadTracking; 98 | private PMatrix3D headMatrix; 99 | private PMatrix3D correctionMatrix; 100 | 101 | static protected URL barrelShaderFragURL = 102 | OculusRift.class.getResource("/oculus/shaders/barrel_frag.glsl"); 103 | 104 | public OculusRift() { 105 | super(); 106 | } 107 | 108 | public void beginDraw() { 109 | super.beginDraw(); 110 | if (!initialized) initOculus(); 111 | drawOculus(); 112 | } 113 | 114 | // Enable head tracking 115 | public boolean enableHeadTracking() { 116 | Hmd.initialize(); 117 | hmd = Hmd.create(); 118 | if (hmd == null) { 119 | isUsingHeadTracking = false; 120 | } else { 121 | isUsingHeadTracking = true; 122 | resetHeadState(); 123 | } 124 | return isUsingHeadTracking; 125 | } 126 | 127 | // Reset head state by current state. 128 | public void resetHeadState() { 129 | PMatrix3D m = getMatrixFromSensor(); 130 | m.invert(); 131 | correctionMatrix = m; 132 | } 133 | 134 | // Get corrected head state matrix. 135 | public PMatrix3D getHeadState() { 136 | PMatrix3D m = getMatrixFromSensor(); 137 | m.apply(correctionMatrix); 138 | return m; 139 | } 140 | 141 | // ------------------------------------------------------------- 142 | // Private 143 | 144 | private void initOculus() { 145 | eyeWidth = oculus_width/2; 146 | eyeHeight = oculus_height; 147 | scene = parent.createGraphics(eyeWidth, eyeHeight, P3D); 148 | fb = parent.createGraphics(oculus_width, oculus_height, P3D); 149 | 150 | barrel = new PShader(parent, defTextureShaderVertURL, barrelShaderFragURL); 151 | onDrawSceneMethod = getMethodRef(parent, "draw", new Class[] { int.class }); 152 | if (onDrawSceneMethod == null) { 153 | throw new RuntimeException( 154 | "OculusRift: sketch is missing a draw(int eye) function\n" + 155 | "to draw the scene for each eye."); 156 | } 157 | 158 | correctionMatrix = new PMatrix3D(); 159 | headMatrix = new PMatrix3D(); 160 | isUsingHeadTracking = false; 161 | 162 | initialized = true; 163 | } 164 | 165 | private void drawOculus() { 166 | updateHeadState(); 167 | 168 | int pimageMode = imageMode; 169 | int pblendMode = blendMode; 170 | parent.imageMode(CENTER); 171 | parent.blendMode(ADD); 172 | parent.background(0); 173 | 174 | // Render left eye 175 | beginScene(); 176 | runOnDrawSceneMethod(LEFT); 177 | endScene(); 178 | set_shader(LEFT); 179 | shader(barrel); 180 | fb.beginDraw(); 181 | fb.background(0); 182 | fb.image(scene, 50, 0); 183 | fb.fill(0); 184 | fb.rect(0, 0, imageCutWidth, fb.height); 185 | fb.rect(scene.width-imageCutWidth, 0, imageCutWidth, scene.height); 186 | fb.endDraw(); 187 | image(fb, parent.width/2 + imageShiftX, parent.height/2, fb.width*imageScaling, fb.height*imageScaling); 188 | resetShader(); 189 | 190 | // Render right eye 191 | beginScene(); 192 | runOnDrawSceneMethod(RIGHT); 193 | endScene(); 194 | set_shader(RIGHT); 195 | shader(barrel); 196 | fb.beginDraw(); 197 | fb.background(0); 198 | fb.image(scene, scene.width-50, 0); 199 | fb.fill(0); 200 | fb.rect(scene.width, 0, imageCutWidth, scene.height); 201 | fb.rect(fb.width - imageCutWidth, 0, imageCutWidth, fb.height); 202 | fb.endDraw(); 203 | image(fb, parent.width/2 - imageShiftX, parent.height/2, fb.width*imageScaling, fb.height*imageScaling); 204 | resetShader(); 205 | 206 | parent.blendMode(pblendMode); 207 | parent.imageMode(pimageMode); 208 | } 209 | 210 | private void updateHeadState() { 211 | if (!isUsingHeadTracking) return; 212 | headMatrix = getHeadState(); 213 | headMatrix.print(); 214 | } 215 | 216 | private void applyHeadState() { 217 | if (!isUsingHeadTracking) return; 218 | scene.applyMatrix(headMatrix); 219 | } 220 | 221 | private PMatrix3D getMatrixFromSensor() { 222 | TrackingState sensorState = hmd.getTrackingState(Hmd.getTimeInSeconds()); 223 | 224 | 225 | OvrVector3f pos = sensorState.HeadPose.Pose.Position; 226 | OvrQuaternionf quat = sensorState.HeadPose.Pose.Orientation; 227 | return calcMatrix(pos.x, pos.y, pos.z, quat.x, quat.y, quat.z, quat.w); 228 | } 229 | 230 | private void runOnDrawSceneMethod(int eye) { 231 | try { 232 | onDrawSceneMethod.invoke(parent, new Object[] { eye }); 233 | } catch (Exception e) { 234 | } 235 | } 236 | 237 | private void beginScene() { 238 | scene.beginDraw(); 239 | pg_backup = parent.g; 240 | parent.g = scene; 241 | scene.resetMatrix(); 242 | scene.perspective(PApplet.radians(fov_deg), scene.width*1.0f/scene.height, z_near, z_far); 243 | applyHeadState(); 244 | } 245 | 246 | private void endScene() { 247 | parent.g = pg_backup; 248 | scene.endDraw(); 249 | } 250 | 251 | private void set_shader(int eye) { 252 | float x = 0.0f; 253 | float y = 0.0f; 254 | float w = 0.5f; 255 | float h = 1.0f; 256 | float DistortionXCenterOffset = 0.25f; 257 | float as = w/h; 258 | 259 | float K0 = 1.0f; 260 | float K1 = 0.22f; 261 | float K2 = 0.24f; 262 | float K3 = 0.0f; 263 | 264 | if (eye == LEFT) { 265 | x = 0.0f; 266 | y = 0.0f; 267 | w = 0.5f; 268 | h = 1.0f; 269 | DistortionXCenterOffset = 0.25f; 270 | } else if (eye == RIGHT) { 271 | x = 0.5f; 272 | y = 0.0f; 273 | w = 0.5f; 274 | h = 1.0f; 275 | DistortionXCenterOffset = -0.25f; 276 | } 277 | 278 | barrel.set("LensCenter", x + (w + DistortionXCenterOffset * 0.5f)*0.5f, y + h*0.5f); 279 | barrel.set("ScreenCenter", x + w*0.5f, y + h*0.5f); 280 | barrel.set("Scale", (w/2.0f) * scaleFactor, (h/2.0f) * scaleFactor * as); 281 | barrel.set("ScaleIn", (2.0f/w), (2.0f/h) / as); 282 | barrel.set("HmdWarpParam", K0, K1, K2, K3); 283 | } 284 | 285 | private PMatrix3D calcMatrix(float px, float py, float pz, float qx, float qy, float qz, float qw) { 286 | PMatrix3D mat = new PMatrix3D(); 287 | 288 | // calculate matrix terms 289 | float two_xSquared = 2 * qx * qx; 290 | float two_ySquared = 2 * qy * qy; 291 | float two_zSquared = 2 * qz * qz; 292 | float two_xy = 2 * qx * qy; 293 | float two_wz = 2 * qw * qz; 294 | float two_xz = 2 * qx * qz; 295 | float two_wy = 2 * qw * qy; 296 | float two_yz = 2 * qy * qz; 297 | float two_wx = 2 * qw * qx; 298 | 299 | // update view matrix orientation 300 | mat.m00 = 1 - two_ySquared - two_zSquared; 301 | mat.m01 = two_xy + two_wz; 302 | mat.m02 = two_xz - two_wy; 303 | mat.m10 = two_xy - two_wz; 304 | mat.m11 = 1 - two_xSquared - two_zSquared; 305 | mat.m12 = two_yz + two_wx; 306 | mat.m20 = two_xz + two_wy; 307 | mat.m21 = two_yz - two_wx; 308 | mat.m22 = 1 - two_xSquared - two_ySquared; 309 | 310 | // change right-hand to left-hand 311 | mat.preApply( 312 | 1, 0, 0, 0, 313 | 0, -1, 0, 0, 314 | 0, 0, 1, 0, 315 | 0, 0, 0, 1 316 | ); 317 | mat.scale(1, -1, 1); 318 | 319 | // Position 320 | mat.m03 = sensingScale * pz; 321 | mat.m13 = sensingScale * py; 322 | mat.m23 = sensingScale * (-px); 323 | 324 | return mat; 325 | } 326 | 327 | @SuppressWarnings("rawtypes") 328 | private Method getMethodRef(Object obj, String methodName, Class[] paraList) { 329 | Method ret = null; 330 | try { 331 | ret = obj.getClass().getMethod(methodName, paraList); 332 | } 333 | catch (Exception e) { 334 | } 335 | return ret; 336 | } 337 | } -------------------------------------------------------------------------------- /src/oculus/shaders/barrel_frag.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Sunao Hashimoto All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | * Neither the name of the kougaku-navi nor the names of its contributors 12 | may be used to endorse or promote products derived from this software 13 | without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | uniform sampler2D texture; 28 | uniform mat4 texMatrix; 29 | 30 | varying vec4 vertColor; 31 | varying vec4 vertTexCoord; 32 | 33 | uniform vec2 LensCenter; 34 | uniform vec2 ScreenCenter; 35 | uniform vec2 Scale; 36 | uniform vec2 ScaleIn; 37 | uniform vec4 HmdWarpParam; 38 | 39 | vec2 HmdWarp(vec2 texIn) 40 | { 41 | vec2 theta = (texIn - LensCenter) * ScaleIn; 42 | float rSq = theta.x * theta.x + theta.y * theta.y; 43 | vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq); 44 | return LensCenter + Scale * theta1; 45 | } 46 | 47 | void main() 48 | { 49 | vec2 tc = HmdWarp(vertTexCoord.xy); 50 | if (any(notEqual(clamp(tc, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25, 0.5)) - tc, vec2(0.0, 0.0)))) 51 | gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); 52 | else 53 | gl_FragColor = texture2D(texture, tc); 54 | } -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | ##library.name## 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 25 | 26 | 38 | 39 |
40 | 41 |
42 |

##library.name##

43 |

44 | A library by ##author.name## for the Processing programming environment.
45 | Last update, ##date##. 46 |

47 |

48 | ##library.sentence##
49 | ##library.paragraph##
50 | Feel free to replace this paragraph with a description of the library.
51 | Contributed libraries are developed, documented, and maintained by members of the Processing community. Further directions are included with each library. For feedback and support, please post to the Discourse. We strongly encourage all libraries to be open source, but not all of them are. 52 |

53 |
54 | 55 | 56 | 57 |
58 |

Download

59 |

60 | Download ##library.name## version ##library.prettyVersion## (##library.version##) in 61 | .zip format. 62 |

63 |

Installation

64 |

65 | Unzip and put the extracted ##project.name## folder into the libraries folder of your Processing sketches. Reference and examples are included in the ##project.name## folder. 66 |

67 |
68 | 69 | 70 |
71 |

Keywords. ##library.keywords##

72 |

Reference. Have a look at the javadoc reference here. A copy of the reference is included in the .zip as well.

73 |

Source. The source code of ##library.name## is available at ##source.host##, and its repository can be browsed here.

74 |
75 | 76 | 77 |
78 |

Examples

79 |

Find a list of examples in the current distribution of ##library.name##, or have a look at them by following the links below.

80 |
    81 | ##examples## 82 |
83 |
84 | 85 | 86 |
87 |

Tested

88 |

89 | 90 | Platform ##tested.platform## 91 | 92 | 93 |
Processing ##tested.processingVersion## 94 | 95 | 96 |
Dependencies ##library.dependencies## 97 |

98 |
99 | 100 | 101 | 102 | 114 | 115 | 116 | 121 | 122 | 123 | 127 | 128 | 129 |
130 |
131 | 132 | 135 |
136 | 137 | -------------------------------------------------------------------------------- /web/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* processingLibs style by andreas schlegel, sojamo. */ 2 | 3 | 4 | * { 5 | margin:0; 6 | padding:0; 7 | border:0; 8 | } 9 | 10 | 11 | body { 12 | font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; 13 | font-size : 100%; 14 | font-size : 0.70em; 15 | font-weight : normal; 16 | line-height : normal; 17 | } 18 | 19 | 20 | 21 | #container { 22 | margin-left:64px; 23 | background-color:#fff; 24 | } 25 | 26 | #header { 27 | float:left; 28 | padding-top:24px; 29 | padding-bottom:48px; 30 | } 31 | 32 | #menu { 33 | margin-top:16px; 34 | float:left; 35 | margin-bottom:64px; 36 | } 37 | 38 | 39 | #about, 40 | #download, 41 | #examples, 42 | #demos, 43 | #misc { 44 | width:480px; 45 | float:left; 46 | margin-right:24px; 47 | } 48 | 49 | 50 | #resources, #info { 51 | width:320px; 52 | float:left; 53 | } 54 | 55 | 56 | .clear { 57 | clear:both; 58 | } 59 | 60 | #footer { 61 | margin-top:300px; 62 | height:20px; 63 | margin-bottom:32px; 64 | } 65 | 66 | 67 | ul { 68 | list-style:none; 69 | padding:0; 70 | margin:0; 71 | } 72 | 73 | 74 | #menu ul li, #subMenu ul li { 75 | float:left; 76 | padding-right:6px; 77 | } 78 | 79 | 80 | 81 | 82 | 83 | 84 | /* Headings */ 85 | 86 | h1 { 87 | font-size:2em; 88 | font-weight:normal; 89 | } 90 | 91 | 92 | h2, h3, h4, h5, th { 93 | font-size:1.3em; 94 | font-weight:normal; 95 | margin-bottom:4px; 96 | } 97 | 98 | 99 | 100 | p { 101 | font-size:1em; 102 | width:90%; 103 | margin-bottom:32px; 104 | } 105 | 106 | 107 | pre, code { 108 | font-family:"Courier New", Courier, monospace; 109 | font-size:1em; 110 | line-height:normal; 111 | } 112 | 113 | 114 | 115 | 116 | hr { 117 | border:0; 118 | height:1px; 119 | margin-bottom:24px; 120 | } 121 | 122 | 123 | a { 124 | text-decoration: underline; 125 | font-weight: normal; 126 | } 127 | 128 | 129 | a:hover, 130 | a:active { 131 | text-decoration: underline; 132 | font-weight: normal; 133 | } 134 | 135 | 136 | a:visited, 137 | a:link:visited { 138 | text-decoration: underline; 139 | font-weight: normal; 140 | } 141 | 142 | 143 | 144 | img { 145 | border: 0px solid #000000; 146 | } 147 | 148 | 149 | 150 | 151 | 152 | /* COLORS */ 153 | 154 | 155 | body { 156 | color : #333; 157 | background-color :#fff; 158 | } 159 | 160 | 161 | #header { 162 | background-color:#fff; 163 | color:#333; 164 | } 165 | 166 | 167 | 168 | h1, h2, h3, h4, h5, h6 { 169 | color:#666; 170 | } 171 | 172 | 173 | pre, code { 174 | color: #000000; 175 | } 176 | 177 | 178 | a,strong { 179 | color: #333; 180 | } 181 | 182 | 183 | a:hover, 184 | a:active { 185 | color: #333; 186 | } 187 | 188 | 189 | a:visited, 190 | a:link:visited { 191 | color: #333; 192 | } 193 | 194 | 195 | #footer, #menu { 196 | background-color:#fff; 197 | color:#333; 198 | } 199 | 200 | 201 | #footer a, #menu a { 202 | color:#333; 203 | } 204 | --------------------------------------------------------------------------------