├── .gitignore ├── .vscode ├── settings.json └── tasks.json ├── CLA.md ├── CONTRIBUTING.md ├── CopyrightNotice.md ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── README.md ├── _config-develop.yml ├── _config-master.yml ├── code ├── _headers ├── directionsHTML │ ├── app.js │ ├── app.ts │ ├── index.html │ └── tsconfig.json ├── directionsWebGL │ ├── app.js │ ├── app.ts │ ├── index.html │ └── tsconfig.json ├── draggablecubes │ ├── app.js │ ├── app.ts │ ├── crosshair_small.png │ ├── index.html │ ├── original-draggablecubes-example.html │ ├── style.css │ └── tsconfig.json ├── geopose │ ├── app.js │ ├── app.ts │ ├── box.png │ ├── buzz.png │ ├── index.html │ ├── style.css │ └── tsconfig.json ├── index.html ├── jsartoolkit │ ├── app.js │ ├── app.ts │ ├── index.html │ └── tsconfig.json ├── panorama-reality-test │ ├── index.html │ ├── reality.js │ ├── reality.ts │ └── tsconfig.json ├── panorama-reality │ ├── index.html │ ├── reality.js │ ├── reality.ts │ └── tsconfig.json ├── panoramas │ ├── app.js │ ├── app.ts │ ├── images │ │ ├── aqui.jpg │ │ ├── cent.jpg │ │ ├── high.jpg │ │ ├── pied.jpg │ │ └── woc.jpg │ ├── index.html │ └── tsconfig.json ├── periodic │ ├── app.js │ ├── index.html │ ├── newer-original-three-example.html │ ├── original-three-example.html │ └── style.css ├── resources │ ├── GVUBrochure.pdf │ ├── TechSquare.pdf │ ├── artoolkit │ │ ├── HiroPattern.pdf │ │ └── patt.hiro │ ├── cesium │ │ └── Assets │ │ │ └── IAU2006_XYS │ │ │ ├── IAU2006_XYS_0.json │ │ │ ├── IAU2006_XYS_1.json │ │ │ ├── IAU2006_XYS_10.json │ │ │ ├── IAU2006_XYS_11.json │ │ │ ├── IAU2006_XYS_12.json │ │ │ ├── IAU2006_XYS_13.json │ │ │ ├── IAU2006_XYS_14.json │ │ │ ├── IAU2006_XYS_15.json │ │ │ ├── IAU2006_XYS_16.json │ │ │ ├── IAU2006_XYS_17.json │ │ │ ├── IAU2006_XYS_18.json │ │ │ ├── IAU2006_XYS_19.json │ │ │ ├── IAU2006_XYS_2.json │ │ │ ├── IAU2006_XYS_20.json │ │ │ ├── IAU2006_XYS_21.json │ │ │ ├── IAU2006_XYS_22.json │ │ │ ├── IAU2006_XYS_23.json │ │ │ ├── IAU2006_XYS_24.json │ │ │ ├── IAU2006_XYS_25.json │ │ │ ├── IAU2006_XYS_26.json │ │ │ ├── IAU2006_XYS_27.json │ │ │ ├── IAU2006_XYS_3.json │ │ │ ├── IAU2006_XYS_4.json │ │ │ ├── IAU2006_XYS_5.json │ │ │ ├── IAU2006_XYS_6.json │ │ │ ├── IAU2006_XYS_7.json │ │ │ ├── IAU2006_XYS_8.json │ │ │ └── IAU2006_XYS_9.json │ ├── datasets │ │ ├── ArgonTutorial.dat │ │ ├── ArgonTutorial.xml │ │ ├── GVUBrochure.dat │ │ ├── GVUBrochure.xml │ │ ├── StonesAndChips.dat │ │ └── StonesAndChips.xml │ ├── fonts │ │ ├── LICENSE │ │ ├── helvetiker_bold.typeface.json │ │ └── helvetiker_regular.typeface.json │ ├── geometries │ │ └── DecalGeometry.js │ ├── lib │ │ ├── ArgonSunMoon.js │ │ ├── CSS3DArgonHUD.js │ │ ├── CSS3DArgonRenderer.js │ │ ├── dat.gui.min.js │ │ ├── stats.min.js │ │ ├── tango │ │ │ ├── THREE.WebAR.js │ │ │ └── three.js │ │ ├── three │ │ │ ├── modifiers │ │ │ │ ├── ExplodeModifier.js │ │ │ │ └── TessellateModifier.js │ │ │ └── three.min.js │ │ └── tween.min.js │ ├── obj │ │ └── leeperrysmith │ │ │ ├── .htaccess │ │ │ ├── Infinite-Level_02_Disp_NoSmoothUV-4096.jpg │ │ │ ├── Infinite-Level_02_Tangent_SmoothUV.jpg │ │ │ ├── LeePerrySmith.js │ │ │ ├── LeePerrySmith.obj │ │ │ ├── LeePerrySmith_License.txt │ │ │ ├── Map-COL.jpg │ │ │ └── Map-SPEC.jpg │ └── textures │ │ └── decal │ │ ├── LICENSE.TXT │ │ ├── decal-diffuse.png │ │ └── decal-normal.jpg ├── streetview-reality │ ├── index.html │ ├── reality.js │ ├── reality.ts │ └── tsconfig.json ├── streetview │ ├── app.js │ ├── index.html │ └── tsconfig.json ├── tango │ ├── app.js │ ├── app.ts │ ├── index.html │ └── tsconfig.json ├── vuforia-jsartoolkit │ ├── app.js │ ├── app.ts │ ├── index.html │ └── tsconfig.json ├── vuforia │ ├── app.js │ ├── app.ts │ ├── index.html │ └── tsconfig.json └── vuforiaDecals │ ├── app.js │ ├── app.ts │ ├── index.html │ ├── original-decals-example.html │ └── tsconfig.json ├── package.json └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | typings 3 | _site -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "./node_modules/typescript/lib" 3 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "tsc", 6 | "isShellCommand": true, 7 | "args": ["-p","${fileDirname}"], 8 | "echoCommand": true, 9 | "showOutput": "always", 10 | "isBuildCommand": true, 11 | "problemMatcher": [ 12 | "$tsc" 13 | ] 14 | } -------------------------------------------------------------------------------- /CLA.md: -------------------------------------------------------------------------------- 1 | ## Georgia Tech Research Corporation 2 | ### Individual Contributor License Agreement ("Agreement") 3 | 4 | #### (*CLA can be signed electronically [using this form](https://docs.google.com/forms/d/1wl5Rg7ishq6nsfbMVoif6322NOzhjdyryHvxmiCQITc/viewform?c=0&w=1&usp=mail_form_link)*) 5 | 6 | Thank you for your interest in Georgia Tech Research Corporation (“GTRC”) software. In order to clarify the intellectual property license granted with Contributions from any person or entity, GTRC must have a Contributor License Agreement ("CLA") on file that has been signed by each Contributor, indicating agreement to the license terms below. 7 | 8 | This license is for your protection as a Contributor as well as the protection of GTRC and its users; it does not change your rights to use your own Contributions for any other purpose. 9 | 10 | If you have not already done so, please complete and sign this CLA. **You may sign this CLA electronically [using this form](https://docs.google.com/forms/d/1wl5Rg7ishq6nsfbMVoif6322NOzhjdyryHvxmiCQITc/viewform?c=0&w=1&usp=mail_form_link)**, or you may print, then scan and email a pdf file of this Agreement to industry@gatech.edu. If necessary, send an original signed Agreement to Georgia Tech Research Corporation, Attn: Director of Licensing, 505 10th Street NW, Atlanta, Georgia 30332-0415, U.S.A. 11 | 12 | Please read this document carefully before signing and keep a copy for your records. 13 | 14 | Full name: ______________________________________________________ 15 | 16 | Mailing Address: ________________________________________________ 17 | 18 | Mailing Address (cont'd): _______________________________________ 19 | 20 | Country: ______________________________________________________ 21 | 22 | Telephone: ______________________________________________________ 23 | 24 | E-Mail: ______________________________________________________ 25 | 26 | Github id: ______________________________________________________ 27 | 28 | 29 | 30 | 31 | You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GTRC. In return, GTRC shall not use Your Contributions in a way that is contrary to the public benefit or inconsistent with its nonprofit status and bylaws in effect at the time of the Contribution. Except for the license granted herein to GTRC and recipients of software distributed by GTRC, You reserve all right, title, and interest in and to Your Contributions. 32 | 33 | 1. Definitions. 34 | "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GTRC. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 35 | "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GTRC for inclusion in, or documentation of, any of the products owned or managed by GTRC (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GTRC or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GTRC for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 36 | 37 | 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GTRC and to recipients of software distributed by GTRC a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 38 | 39 | 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GTRC and to recipients of software distributed by GTRC a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 40 | 41 | 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to GTRC, or that your employer has executed a separate license agreement with GTRC. 42 | 43 | 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 44 | 45 | 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 46 | 47 | 7. Should You wish to submit work that is not Your original creation, You may submit it to GTRC separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as 48 | "Submitted on behalf of a third-party: [named here]". 49 | 50 | 8. You agree to notify GTRC of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. 51 | 52 | Please sign: __________________________________ Date: ________________ 53 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | If you would like to contribute to the argonjs project, please fill out our [Contributor License Agreement](https://github.com/argonjs/argonjs.github.io/blob/master/CLA.md), either electornically (using the link on that page) or by printing, filling in, and mailing the form. 2 | 3 | Our public roadmap for the project is on our [Trello board](https://trello.com/b/gBsEa8eg/argon-public-roadmap), if you would like ideas for how to help out. 4 | 5 | We will add more information on our style guidelines and so on, as we move forward. For now, please talk to us (ideally on our [Slack](http://argonjs.slack.com) for the project) and we can see how best to collaborate. 6 | -------------------------------------------------------------------------------- /CopyrightNotice.md: -------------------------------------------------------------------------------- 1 | ## Copyright 2016 Georgia Tech Research Corporation 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # Hello! This is where you manage which Jekyll version is used to run. 2 | # When you want to use a different version, change it below, save the 3 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 4 | # 5 | # bundle exec jekyll serve 6 | # 7 | # This will help ensure the proper Jekyll version is running. 8 | # Happy Jekylling! 9 | source 'https://rubygems.org' 10 | gem "jekyll", "3.4.3" 11 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.5.1) 5 | public_suffix (~> 2.0, >= 2.0.2) 6 | colorator (1.1.0) 7 | ffi (1.9.18) 8 | forwardable-extended (2.6.0) 9 | jekyll (3.4.3) 10 | addressable (~> 2.4) 11 | colorator (~> 1.0) 12 | jekyll-sass-converter (~> 1.0) 13 | jekyll-watch (~> 1.1) 14 | kramdown (~> 1.3) 15 | liquid (~> 3.0) 16 | mercenary (~> 0.3.3) 17 | pathutil (~> 0.9) 18 | rouge (~> 1.7) 19 | safe_yaml (~> 1.0) 20 | jekyll-sass-converter (1.5.0) 21 | sass (~> 3.4) 22 | jekyll-watch (1.5.0) 23 | listen (~> 3.0, < 3.1) 24 | kramdown (1.13.2) 25 | liquid (3.0.6) 26 | listen (3.0.8) 27 | rb-fsevent (~> 0.9, >= 0.9.4) 28 | rb-inotify (~> 0.9, >= 0.9.7) 29 | mercenary (0.3.6) 30 | pathutil (0.14.0) 31 | forwardable-extended (~> 2.6) 32 | public_suffix (2.0.5) 33 | rb-fsevent (0.9.8) 34 | rb-inotify (0.9.8) 35 | ffi (>= 0.5.0) 36 | rouge (1.11.1) 37 | safe_yaml (1.0.4) 38 | sass (3.4.23) 39 | 40 | PLATFORMS 41 | ruby 42 | 43 | DEPENDENCIES 44 | jekyll (= 3.4.3) 45 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # samples 2 | A collection of simple examples that demonstrate the use of various argon.js features 3 | 4 | ## Local Development 5 | 6 | Setup: [Install Jekyll](https://jekyllrb.com/docs/installation/) 7 | 8 | ```sh 9 | git clone https://github.com/argonjs/samples.git # Clone the repository. 10 | cd samples && npm install # Install dependencies. 11 | npm run devsite # Generate a local development site in _site. 12 | npm run serve # Start the local development server. 13 | ``` 14 | 15 | And open in your browser **[http://localhost:1337](http://localhost:1337)**. 16 | 17 | When you change the ts files, rebuild with `npm run build`. 18 | 19 | When you change the HTML or js files, you need to regenerate _site with `npm run devsite`. 20 | 21 | ## Questions 22 | 23 | For questions and support, [ask on one of our support channels](https://www.argonjs.io/#develop). 24 | 25 | ## Stay in Touch 26 | 27 | - To hang out with the community, join the argonjs slack ([see the slack-join link in our developer support links](https://www.argonjs.io/#develop)). 28 | - [Follow @argonjs on Twitter](https://twitter.com/argonjs). 29 | 30 | ## Contributing 31 | 32 | Get involved! Check out the [Contributing Guide](CONTRIBUTING.md) for how to get started. 33 | 34 | ## License 35 | 36 | This program is free software and is distributed under an [Apache License](LICENSE.txt). 37 | -------------------------------------------------------------------------------- /_config-develop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | port: 1237 3 | host: 0.0.0.0 4 | safe: false 5 | 6 | ### site serving configuration ### 7 | source: code 8 | include: [_headers] 9 | timezone: null 10 | lsi: false 11 | markdown: kramdown 12 | 13 | keywords: "argon, augmented reality, web, javascript" 14 | 15 | argonjs: "https://rawgit.com/argonjs/argon/develop/dist/argon.js" 16 | 17 | redirect: "false" 18 | 19 | # argonjs: "https://unpkg.com/@argonjs/argon@1.1/dist/argon.js" 20 | -------------------------------------------------------------------------------- /_config-master.yml: -------------------------------------------------------------------------------- 1 | --- 2 | port: 1237 3 | host: 0.0.0.0 4 | safe: false 5 | 6 | ### site serving configuration ### 7 | source: code 8 | include: [_headers] 9 | timezone: null 10 | lsi: false 11 | markdown: kramdown 12 | 13 | keywords: "argon, augmented reality, web, javascript" 14 | 15 | # argonjs: "https://rawgit.com/argonjs/argon/develop/dist/argon.js" 16 | 17 | redirect: "true" 18 | 19 | argonjs: "https://unpkg.com/@argonjs/argon@^1.3.3/dist/argon.js" 20 | -------------------------------------------------------------------------------- /code/_headers: -------------------------------------------------------------------------------- 1 | /resources/* 2 | Access-Control-Allow-Origin: * 3 | 4 | /panoramas/images/* 5 | Access-Control-Allow-Origin: * -------------------------------------------------------------------------------- /code/directionsHTML/app.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | // set up Argon 4 | var app = Argon.init(); 5 | // set up THREE. Create a scene, a perspective camera and an object 6 | // for the user's location 7 | var scene = new THREE.Scene(); 8 | var camera = new THREE.PerspectiveCamera(); 9 | var stage = new THREE.Object3D; 10 | scene.add(camera); 11 | scene.add(stage); 12 | // The CSS3DArgonRenderer supports mono and stereo views, and 13 | // includes both 3D elements and a place to put things that appear 14 | // fixed to the screen (heads-up-display) 15 | var renderer = new THREE.CSS3DArgonRenderer(); 16 | app.view.element.appendChild(renderer.domElement); 17 | // to easily control stuff on the display 18 | var hud = new THREE.CSS3DArgonHUD(); 19 | // We put some elements in the index.html, for convenience. 20 | // Here, we retrieve the description box and move it to the 21 | // the CSS3DArgonHUD hudElements[0]. We only put it in the left 22 | // hud since we'll be hiding it in stereo 23 | var description = document.getElementById('description'); 24 | hud.hudElements[0].appendChild(description); 25 | app.view.element.appendChild(hud.domElement); 26 | // creating 6 divs to indicate the x y z positioning 27 | var divXpos = document.createElement('div'); 28 | var divXneg = document.createElement('div'); 29 | var divYpos = document.createElement('div'); 30 | var divYneg = document.createElement('div'); 31 | var divZpos = document.createElement('div'); 32 | var divZneg = document.createElement('div'); 33 | // programatically create a stylesheet for our direction divs 34 | // and add it to the document 35 | var style = document.createElement("style"); 36 | style.type = 'text/css'; 37 | document.head.appendChild(style); 38 | var sheet = style.sheet; 39 | sheet.insertRule("\n .cssContent {\n opacity: 0.5;\n width: 100px;\n height: 100px;\n border-radius: 50%;\n line-height: 100px;\n fontSize: 20px;\n text-align: center;\n }\n", 0); 40 | // Put content in each one (should do this as a couple of functions) 41 | // for X 42 | divXpos.className = "cssContent"; 43 | divXpos.style.backgroundColor = "red"; 44 | divXpos.innerText = "Pos X = East"; 45 | divXneg.className = "cssContent"; 46 | divXneg.style.backgroundColor = "red"; 47 | divXneg.innerText = "Neg X = West"; 48 | // for Y 49 | divYpos.className = "cssContent"; 50 | divYpos.style.backgroundColor = "blue"; 51 | divYpos.innerText = "Pos Y = Up"; 52 | divYneg.className = "cssContent"; 53 | divYneg.style.backgroundColor = "blue"; 54 | divYneg.innerText = "Neg Y = Down"; 55 | //for Z 56 | divZpos.className = "cssContent"; 57 | divZpos.style.backgroundColor = "green"; 58 | divZpos.innerText = "Pos Z = South"; 59 | divZneg.className = "cssContent"; 60 | divZneg.style.backgroundColor = "green"; 61 | divZneg.innerText = "Neg Z = North"; 62 | // create 6 CSS3DObjects in the scene graph. The CSS3DObject object 63 | // is used by the CSS3DArgonRenderer. Because an HTML element can only 64 | // appear once in the DOM, we need two elements to create a stereo view. 65 | // The CSS3DArgonRenderer manages these for you, using the CSS3DObject. 66 | // You can pass a single DIV to the CSS3DObject, which 67 | // will be cloned to create a second matching DIV in stereo mode, or you 68 | // can pass in two DIVs in an array (one for the left and one for the 69 | // right eyes). If the content of the DIV does not change as the 70 | // application runs, letting the CSS3DArgonRenderer clone them is 71 | // simplest. If it is changing, passing in two and updating both 72 | // yourself is simplest. 73 | var cssObjectXpos = new THREE.CSS3DObject(divXpos); 74 | var cssObjectXneg = new THREE.CSS3DObject(divXneg); 75 | var cssObjectYpos = new THREE.CSS3DObject(divYpos); 76 | var cssObjectYneg = new THREE.CSS3DObject(divYneg); 77 | var cssObjectZpos = new THREE.CSS3DObject(divZpos); 78 | var cssObjectZneg = new THREE.CSS3DObject(divZneg); 79 | // the width and height is used to align things. 80 | cssObjectXpos.position.x = 200.0; 81 | cssObjectXpos.position.y = 0.0; 82 | cssObjectXpos.position.z = 0.0; 83 | cssObjectXpos.rotation.y = -Math.PI / 2; 84 | cssObjectXneg.position.x = -200.0; 85 | cssObjectXneg.position.y = 0.0; 86 | cssObjectXneg.position.z = 0.0; 87 | cssObjectXneg.rotation.y = Math.PI / 2; 88 | // for Y 89 | cssObjectYpos.position.x = 0.0; 90 | cssObjectYpos.position.y = 200.0; 91 | cssObjectYpos.position.z = 0.0; 92 | cssObjectYpos.rotation.x = Math.PI / 2; 93 | cssObjectYneg.position.x = 0.0; 94 | cssObjectYneg.position.y = -200.0; 95 | cssObjectYneg.position.z = 0.0; 96 | cssObjectYneg.rotation.x = -Math.PI / 2; 97 | // for Z 98 | cssObjectZpos.position.x = 0.0; 99 | cssObjectZpos.position.y = 0.0; 100 | cssObjectZpos.position.z = 200.0; 101 | cssObjectZpos.rotation.y = Math.PI; 102 | cssObjectZneg.position.x = 0.0; 103 | cssObjectZneg.position.y = 0.0; 104 | cssObjectZneg.position.z = -200.0; 105 | //no rotation need for this one 106 | stage.add(cssObjectXpos); 107 | stage.add(cssObjectXneg); 108 | stage.add(cssObjectYpos); 109 | stage.add(cssObjectYneg); 110 | stage.add(cssObjectZpos); 111 | stage.add(cssObjectZneg); 112 | // the updateEvent is called each time the 3D world should be 113 | // rendered, before the renderEvent. The state of your application 114 | // should be updated here. 115 | app.updateEvent.on(function () { 116 | // get the pose of the "stage" to anchor our content. 117 | // The "stage" defines an East-Up-South coordinate system 118 | // (assuming geolocation is available). 119 | var stagePose = app.getEntityPose(app.stage); 120 | // set the pose of our THREE stage object 121 | if (stagePose.poseStatus & Argon.PoseStatus.KNOWN) { 122 | stage.position.copy(stagePose.position); 123 | stage.quaternion.copy(stagePose.orientation); 124 | } 125 | }); 126 | app.renderEvent.on(function () { 127 | var viewport = app.view.viewport; 128 | var subViews = app.view.subviews; 129 | // if we have 1 subView, we're in mono mode. If more, stereo. 130 | var monoMode = subViews.length == 1; 131 | // set the renderer to know the current size of the viewport. 132 | // This is the full size of the viewport, which would include 133 | // both views if we are in stereo viewing mode 134 | renderer.setSize(viewport.width, viewport.height); 135 | hud.setSize(viewport.width, viewport.height); 136 | // there is 1 subview in monocular mode, 2 in stereo mode 137 | for (var _i = 0, subViews_1 = subViews; _i < subViews_1.length; _i++) { 138 | var subview = subViews_1[_i]; 139 | // set the position and orientation of the camera for 140 | // this subview 141 | camera.position.copy(subview.pose.position); 142 | camera.quaternion.copy(subview.pose.orientation); 143 | // the underlying system provides a full projection matrix 144 | // for the camera. Use it, and then update the FOV of the 145 | // camera from it (needed by the CSS Perspective DIV) 146 | camera.projectionMatrix.fromArray(subview.frustum.projectionMatrix); 147 | camera.fov = subview.frustum.fovy * 180 / Math.PI; 148 | // set the viewport for this view 149 | var _a = subview.viewport, x = _a.x, y = _a.y, width = _a.width, height = _a.height; 150 | renderer.setViewport(x, y, width, height, subview.index); 151 | // render this view. 152 | renderer.render(scene, camera, subview.index); 153 | // adjust the hud, but only in mono 154 | if (monoMode) { 155 | hud.setViewport(x, y, width, height, subview.index); 156 | hud.render(subview.index); 157 | } 158 | } 159 | }); 160 | -------------------------------------------------------------------------------- /code/directionsHTML/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // set up Argon 5 | const app = Argon.init(); 6 | 7 | // set up THREE. Create a scene, a perspective camera and an object 8 | // for the user's location 9 | const scene = new THREE.Scene(); 10 | const camera = new THREE.PerspectiveCamera(); 11 | const stage = new THREE.Object3D; 12 | scene.add(camera); 13 | scene.add(stage); 14 | 15 | // The CSS3DArgonRenderer supports mono and stereo views, and 16 | // includes both 3D elements and a place to put things that appear 17 | // fixed to the screen (heads-up-display) 18 | const renderer = new (THREE).CSS3DArgonRenderer(); 19 | app.view.element.appendChild(renderer.domElement); 20 | 21 | // to easily control stuff on the display 22 | const hud = new (THREE).CSS3DArgonHUD(); 23 | 24 | // We put some elements in the index.html, for convenience. 25 | // Here, we retrieve the description box and move it to the 26 | // the CSS3DArgonHUD hudElements[0]. We only put it in the left 27 | // hud since we'll be hiding it in stereo 28 | var description = document.getElementById( 'description' ); 29 | hud.hudElements[0].appendChild(description); 30 | app.view.element.appendChild(hud.domElement); 31 | 32 | // creating 6 divs to indicate the x y z positioning 33 | var divXpos = document.createElement('div') 34 | var divXneg = document.createElement('div') 35 | var divYpos = document.createElement('div') 36 | var divYneg = document.createElement('div') 37 | var divZpos = document.createElement('div') 38 | var divZneg = document.createElement('div') 39 | 40 | // programatically create a stylesheet for our direction divs 41 | // and add it to the document 42 | const style = document.createElement("style"); 43 | style.type = 'text/css'; 44 | document.head.appendChild(style); 45 | const sheet = style.sheet; 46 | sheet.insertRule(` 47 | .cssContent { 48 | opacity: 0.5; 49 | width: 100px; 50 | height: 100px; 51 | border-radius: 50%; 52 | line-height: 100px; 53 | fontSize: 20px; 54 | text-align: center; 55 | } 56 | `, 0); 57 | 58 | // Put content in each one (should do this as a couple of functions) 59 | // for X 60 | divXpos.className = "cssContent" 61 | divXpos.style.backgroundColor = "red" 62 | divXpos.innerText = "Pos X = East" 63 | 64 | divXneg.className = "cssContent" 65 | divXneg.style.backgroundColor = "red" 66 | divXneg.innerText = "Neg X = West" 67 | 68 | // for Y 69 | divYpos.className = "cssContent" 70 | divYpos.style.backgroundColor = "blue" 71 | divYpos.innerText = "Pos Y = Up" 72 | 73 | divYneg.className = "cssContent" 74 | divYneg.style.backgroundColor = "blue" 75 | divYneg.innerText = "Neg Y = Down" 76 | 77 | //for Z 78 | divZpos.className = "cssContent" 79 | divZpos.style.backgroundColor = "green" 80 | divZpos.innerText = "Pos Z = South" 81 | 82 | divZneg.className = "cssContent" 83 | divZneg.style.backgroundColor = "green" 84 | divZneg.innerText = "Neg Z = North" 85 | 86 | // create 6 CSS3DObjects in the scene graph. The CSS3DObject object 87 | // is used by the CSS3DArgonRenderer. Because an HTML element can only 88 | // appear once in the DOM, we need two elements to create a stereo view. 89 | // The CSS3DArgonRenderer manages these for you, using the CSS3DObject. 90 | // You can pass a single DIV to the CSS3DObject, which 91 | // will be cloned to create a second matching DIV in stereo mode, or you 92 | // can pass in two DIVs in an array (one for the left and one for the 93 | // right eyes). If the content of the DIV does not change as the 94 | // application runs, letting the CSS3DArgonRenderer clone them is 95 | // simplest. If it is changing, passing in two and updating both 96 | // yourself is simplest. 97 | var cssObjectXpos = new (THREE).CSS3DObject(divXpos) 98 | var cssObjectXneg = new (THREE).CSS3DObject(divXneg) 99 | var cssObjectYpos = new (THREE).CSS3DObject(divYpos) 100 | var cssObjectYneg = new (THREE).CSS3DObject(divYneg) 101 | var cssObjectZpos = new (THREE).CSS3DObject(divZpos) 102 | var cssObjectZneg = new (THREE).CSS3DObject(divZneg) 103 | 104 | // the width and height is used to align things. 105 | cssObjectXpos.position.x = 200.0 106 | cssObjectXpos.position.y = 0.0 107 | cssObjectXpos.position.z = 0.0 108 | cssObjectXpos.rotation.y = - Math.PI / 2 109 | 110 | cssObjectXneg.position.x = -200.0 111 | cssObjectXneg.position.y = 0.0 112 | cssObjectXneg.position.z = 0.0 113 | cssObjectXneg.rotation.y = Math.PI / 2 114 | 115 | // for Y 116 | cssObjectYpos.position.x = 0.0 117 | cssObjectYpos.position.y = 200.0 118 | cssObjectYpos.position.z = 0.0 119 | cssObjectYpos.rotation.x = Math.PI / 2 120 | 121 | cssObjectYneg.position.x = 0.0 122 | cssObjectYneg.position.y = - 200.0 123 | cssObjectYneg.position.z = 0.0 124 | cssObjectYneg.rotation.x = - Math.PI / 2 125 | 126 | // for Z 127 | cssObjectZpos.position.x = 0.0 128 | cssObjectZpos.position.y = 0.0 129 | cssObjectZpos.position.z = 200.0 130 | cssObjectZpos.rotation.y = Math.PI 131 | 132 | cssObjectZneg.position.x = 0.0 133 | cssObjectZneg.position.y = 0.0 134 | cssObjectZneg.position.z = -200.0 135 | //no rotation need for this one 136 | 137 | stage.add(cssObjectXpos) 138 | stage.add(cssObjectXneg) 139 | stage.add(cssObjectYpos) 140 | stage.add(cssObjectYneg) 141 | stage.add(cssObjectZpos) 142 | stage.add(cssObjectZneg) 143 | 144 | // the updateEvent is called each time the 3D world should be 145 | // rendered, before the renderEvent. The state of your application 146 | // should be updated here. 147 | app.updateEvent.on(() => { 148 | // get the pose of the "stage" to anchor our content. 149 | // The "stage" defines an East-Up-South coordinate system 150 | // (assuming geolocation is available). 151 | const stagePose = app.getEntityPose(app.stage); 152 | 153 | // set the pose of our THREE stage object 154 | if (stagePose.poseStatus & Argon.PoseStatus.KNOWN) { 155 | stage.position.copy(stagePose.position); 156 | stage.quaternion.copy(stagePose.orientation); 157 | } 158 | }) 159 | 160 | app.renderEvent.on(() => { 161 | 162 | const viewport = app.view.viewport; 163 | const subViews = app.view.subviews; 164 | 165 | // if we have 1 subView, we're in mono mode. If more, stereo. 166 | var monoMode = subViews.length == 1; 167 | 168 | // set the renderer to know the current size of the viewport. 169 | // This is the full size of the viewport, which would include 170 | // both views if we are in stereo viewing mode 171 | renderer.setSize(viewport.width, viewport.height); 172 | hud.setSize(viewport.width, viewport.height); 173 | 174 | // there is 1 subview in monocular mode, 2 in stereo mode 175 | for (let subview of subViews) { 176 | // set the position and orientation of the camera for 177 | // this subview 178 | camera.position.copy(subview.pose.position); 179 | camera.quaternion.copy(subview.pose.orientation); 180 | 181 | // the underlying system provides a full projection matrix 182 | // for the camera. Use it, and then update the FOV of the 183 | // camera from it (needed by the CSS Perspective DIV) 184 | camera.projectionMatrix.fromArray(subview.frustum.projectionMatrix); 185 | camera.fov = subview.frustum.fovy * 180 / Math.PI; 186 | 187 | // set the viewport for this view 188 | let {x,y,width,height} = subview.viewport; 189 | renderer.setViewport(x,y,width,height, subview.index); 190 | 191 | // render this view. 192 | renderer.render(scene, camera, subview.index); 193 | 194 | // adjust the hud, but only in mono 195 | if (monoMode) { 196 | hud.setViewport(x,y,width,height, subview.index); 197 | hud.render(subview.index); 198 | } 199 | } 200 | }); 201 | -------------------------------------------------------------------------------- /code/directionsHTML/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Directions 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 37 | 38 | 39 |
40 |
41 |

Six directions in HTML

42 |
(click to dismiss)
43 |

This example displays a directional reference frame around the camera in Cartesian coordinates, using the EastUpSouth orientation for positive (x, y, z). A userLocation geospatial entity is created and positioned at the position of the user, and updated when the user's position changes. It uses HTML elements to put a text label at 200 meters in each of the negative/positive directions: x is west/east; y is down/up; z is north/south.

44 |
45 |
46 | 47 | 52 | 53 | 62 | -------------------------------------------------------------------------------- /code/directionsHTML/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /code/directionsWebGL/app.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | // any time we use an INERTIAL frame in Cesium, it needs to know where to find it's 5 | // ASSET folder on the web. The SunMoonLights computation uses INERTIAL frames, so 6 | // so we need to put the assets on the web and point Cesium at them 7 | var CESIUM_BASE_URL = '../resources/cesium/'; 8 | // set up Argon 9 | var app = Argon.init(); 10 | // this app uses geoposed content, so subscribe to geolocation updates 11 | app.subscribeGeolocation(); 12 | // set up THREE. Create a scene, a perspective camera and an object 13 | // for the user's location 14 | var scene = new THREE.Scene(); 15 | var camera = new THREE.PerspectiveCamera(); 16 | var stage = new THREE.Object3D; 17 | scene.add(camera); 18 | scene.add(stage); 19 | var directions = new THREE.Object3D; 20 | stage.add(directions); 21 | // We use the standard WebGLRenderer when we only need WebGL-based content 22 | var renderer = new THREE.WebGLRenderer({ 23 | alpha: true, 24 | logarithmicDepthBuffer: true, 25 | antialias: Argon.suggestedWebGLContextAntialiasAttribute 26 | }); 27 | var hud = new THREE.CSS3DArgonHUD(); 28 | // We also move the description box to the left Argon HUD. 29 | // We don't duplicated it because we only use it in mono mode 30 | var holder = document.createElement('div'); 31 | var hudDescription = document.getElementById('description'); 32 | holder.appendChild(hudDescription); 33 | hud.hudElements[0].appendChild(holder); 34 | // add a performance stats thing to the display 35 | var stats = new Stats(); 36 | hud.hudElements[0].appendChild(stats.dom); 37 | // app.view.element.appendChild(hud.domElement); 38 | // set the layers of our view 39 | app.view.setLayers([ 40 | { source: renderer.domElement }, 41 | { source: hud.domElement } 42 | ]); 43 | // In this example, we are using the actual position of the sun and moon to create lights. 44 | // The SunMoonLights functions are created by ArgonSunMoon.js, and turn on the sun or moon 45 | // when they are above the horizon. This package could be improved a lot (such as by 46 | // adjusting the color of light based on distance above horizon, taking the phase of the 47 | // moon into account, etc) but it provides a simple starting point. 48 | var sunMoonLights = new THREE.SunMoonLights(); 49 | // the SunMoonLights.update routine will add/remove the sun/moon lights depending on if 50 | // the sun/moon are above the horizon 51 | scene.add(sunMoonLights.lights); 52 | // add some ambient so things aren't so harshly illuminated 53 | var ambientlight = new THREE.AmbientLight(0x404040); // soft white ambient light 54 | scene.add(ambientlight); 55 | // install a reality that the user can select from 56 | app.reality.install(Argon.resolveURL('../streetview-reality/index.html')); 57 | // create 6 3D words for the 6 directions. 58 | var loader = new THREE.FontLoader(); 59 | loader.load('../resources/fonts/helvetiker_regular.typeface.json', function (font) { 60 | var textOptions = { 61 | font: font, 62 | size: 0.15, 63 | height: 0.1, 64 | curveSegments: 5, 65 | bevelThickness: 0.01, 66 | bevelSize: 0.01, 67 | bevelEnabled: true 68 | }; 69 | var textMaterial = new THREE.MeshStandardMaterial({ 70 | color: 0x5588ff 71 | }); 72 | function createDirectionLabel(text, position, rotation) { 73 | var textGeometry = new THREE.TextGeometry(text, textOptions); 74 | textGeometry.center(); 75 | var textMesh = new THREE.Mesh(textGeometry, textMaterial); 76 | if (position.x) 77 | textMesh.position.x = position.x; 78 | if (position.y) 79 | textMesh.position.y = position.y; 80 | if (position.z) 81 | textMesh.position.z = position.z; 82 | if (rotation.x) 83 | textMesh.rotation.x = rotation.x; 84 | if (rotation.y) 85 | textMesh.rotation.y = rotation.y; 86 | if (rotation.z) 87 | textMesh.rotation.z = rotation.z; 88 | directions.add(textMesh); 89 | } 90 | createDirectionLabel("North", { z: -1 }, {}); 91 | createDirectionLabel("South", { z: 1 }, { y: Math.PI }); 92 | createDirectionLabel("East", { x: 1 }, { y: -Math.PI / 2 }); 93 | createDirectionLabel("West", { x: -1 }, { y: Math.PI / 2 }); 94 | createDirectionLabel("Up", { y: 1 }, { x: Math.PI / 2 }); 95 | createDirectionLabel("Down", { y: -1 }, { x: -Math.PI / 2 }); 96 | }); 97 | // the updateEvent is called each time the 3D world should be 98 | // rendered, before the renderEvent. The state of your application 99 | // should be updated here. 100 | app.updateEvent.addEventListener(function () { 101 | // get the position and orientation of the "stage", 102 | // to anchor our content. The "stage" defines an East-Up-South 103 | // coordinate system (assuming geolocation is available). 104 | var stageEUSPose = app.getEntityPose(app.stageEUS); 105 | // If we know the user's geopose, set the position of our 106 | // THREE user object to match the stageEUS frame 107 | if (stageEUSPose.poseStatus & Argon.PoseStatus.KNOWN) { 108 | stage.position.copy(stageEUSPose.position); 109 | stage.quaternion.copy(stageEUSPose.orientation); 110 | } 111 | else { 112 | // If not, position the labels on the non-geopose stage 113 | var stagePose = app.getEntityPose(app.stage); 114 | if (stagePose.poseStatus & Argon.PoseStatus.KNOWN) { 115 | stage.position.copy(stagePose.position); 116 | stage.quaternion.copy(stagePose.orientation); 117 | } 118 | } 119 | // get sun and moon positions, add/remove lights as necessary 120 | var date = app.context.time; 121 | sunMoonLights.update(date, app.context.origin); 122 | // place directions content at appropriate height on stage depending on user tracking and display mode 123 | if (app.userTracking === '6DOF') { 124 | if (app.displayMode === 'head') { 125 | directions.position.y = Argon.AVERAGE_EYE_HEIGHT; 126 | } 127 | else { 128 | directions.position.y = Argon.AVERAGE_EYE_HEIGHT / 2; 129 | } 130 | } 131 | else { 132 | var userStagePose = app.getEntityPose(app.user, app.stage); 133 | directions.position.y = userStagePose.position.y; 134 | } 135 | }); 136 | // renderEvent is fired whenever argon wants the app to update its display 137 | app.renderEvent.addEventListener(function () { 138 | // set the renderer to know the current size of the viewport. 139 | // This is the full size of the viewport, which would include 140 | // both views if we are in stereo viewing mode 141 | var view = app.view; 142 | renderer.setSize(view.renderWidth, view.renderHeight, false); 143 | renderer.setPixelRatio(app.suggestedPixelRatio); 144 | var viewport = view.viewport; 145 | hud.setSize(viewport.width, viewport.height); 146 | // There is 1 subview in monocular mode, 2 in stereo mode. 147 | // If we are in mono view, show the description. If not, hide it, 148 | if (app.view.subviews.length > 1) { 149 | holder.style.display = 'none'; 150 | } 151 | else { 152 | holder.style.display = 'block'; 153 | } 154 | // there is 1 subview in monocular mode, 2 in stereo mode 155 | for (var _i = 0, _a = app.view.subviews; _i < _a.length; _i++) { 156 | var subview = _a[_i]; 157 | // set the position and orientation of the camera for 158 | // this subview 159 | camera.position.copy(subview.pose.position); 160 | camera.quaternion.copy(subview.pose.orientation); 161 | // the underlying system provide a full projection matrix 162 | // for the camera. 163 | camera.projectionMatrix.fromArray(subview.frustum.projectionMatrix); 164 | // set the viewport for this view 165 | var _b = subview.renderViewport, x = _b.x, y = _b.y, width = _b.width, height = _b.height; 166 | renderer.setViewport(x, y, width, height); 167 | // set the webGL rendering parameters and render this view 168 | renderer.setScissor(x, y, width, height); 169 | renderer.setScissorTest(true); 170 | renderer.render(scene, camera); 171 | // adjust the hud 172 | var _c = subview.viewport, x = _c.x, y = _c.y, width = _c.width, height = _c.height; 173 | hud.setViewport(x, y, width, height, subview.index); 174 | hud.render(subview.index); 175 | } 176 | stats.update(); 177 | }); 178 | -------------------------------------------------------------------------------- /code/directionsWebGL/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // any time we use an INERTIAL frame in Cesium, it needs to know where to find it's 6 | // ASSET folder on the web. The SunMoonLights computation uses INERTIAL frames, so 7 | // so we need to put the assets on the web and point Cesium at them 8 | var CESIUM_BASE_URL='../resources/cesium/'; 9 | 10 | // set up Argon 11 | const app = Argon.init(); 12 | 13 | // this app uses geoposed content, so subscribe to geolocation updates 14 | app.subscribeGeolocation(); 15 | 16 | // set up THREE. Create a scene, a perspective camera and an object 17 | // for the user's location 18 | const scene = new THREE.Scene(); 19 | const camera = new THREE.PerspectiveCamera(); 20 | const stage = new THREE.Object3D; 21 | scene.add(camera); 22 | scene.add(stage); 23 | 24 | const directions = new THREE.Object3D; 25 | stage.add(directions); 26 | 27 | // We use the standard WebGLRenderer when we only need WebGL-based content 28 | const renderer = new THREE.WebGLRenderer({ 29 | alpha: true, 30 | logarithmicDepthBuffer: true, 31 | antialias: Argon.suggestedWebGLContextAntialiasAttribute 32 | }); 33 | 34 | const hud = new (THREE).CSS3DArgonHUD(); 35 | 36 | // We also move the description box to the left Argon HUD. 37 | // We don't duplicated it because we only use it in mono mode 38 | var holder = document.createElement( 'div' ); 39 | var hudDescription = document.getElementById( 'description' ); 40 | holder.appendChild(hudDescription); 41 | hud.hudElements[0].appendChild(holder); 42 | 43 | // add a performance stats thing to the display 44 | var stats = new Stats(); 45 | hud.hudElements[0].appendChild(stats.dom); 46 | // app.view.element.appendChild(hud.domElement); 47 | 48 | // set the layers of our view 49 | app.view.setLayers([ 50 | { source: renderer.domElement }, 51 | { source: hud.domElement } 52 | ]); 53 | 54 | // In this example, we are using the actual position of the sun and moon to create lights. 55 | // The SunMoonLights functions are created by ArgonSunMoon.js, and turn on the sun or moon 56 | // when they are above the horizon. This package could be improved a lot (such as by 57 | // adjusting the color of light based on distance above horizon, taking the phase of the 58 | // moon into account, etc) but it provides a simple starting point. 59 | const sunMoonLights = new (THREE).SunMoonLights(); 60 | // the SunMoonLights.update routine will add/remove the sun/moon lights depending on if 61 | // the sun/moon are above the horizon 62 | scene.add( sunMoonLights.lights ); 63 | 64 | // add some ambient so things aren't so harshly illuminated 65 | var ambientlight = new THREE.AmbientLight( 0x404040 ); // soft white ambient light 66 | scene.add(ambientlight); 67 | 68 | // install a reality that the user can select from 69 | app.reality.install(Argon.resolveURL('../streetview-reality/index.html')); 70 | 71 | // create 6 3D words for the 6 directions. 72 | var loader = new THREE.FontLoader(); 73 | loader.load( '../resources/fonts/helvetiker_regular.typeface.json', function ( font ) { 74 | const textOptions = { 75 | font:font, 76 | size: 0.15, 77 | height: 0.1, 78 | curveSegments: 5, 79 | bevelThickness: 0.01, 80 | bevelSize: 0.01, 81 | bevelEnabled: true 82 | } 83 | 84 | var textMaterial = new THREE.MeshStandardMaterial({ 85 | color: 0x5588ff 86 | }) 87 | 88 | function createDirectionLabel(text, position, rotation) { 89 | var textGeometry = new THREE.TextGeometry(text, textOptions); 90 | textGeometry.center(); 91 | var textMesh = new THREE.Mesh(textGeometry, textMaterial); 92 | if (position.x) textMesh.position.x = position.x; 93 | if (position.y) textMesh.position.y = position.y; 94 | if (position.z) textMesh.position.z = position.z; 95 | if (rotation.x) textMesh.rotation.x = rotation.x; 96 | if (rotation.y) textMesh.rotation.y = rotation.y; 97 | if (rotation.z) textMesh.rotation.z = rotation.z; 98 | directions.add(textMesh); 99 | } 100 | 101 | createDirectionLabel("North", {z:-1}, {}); 102 | createDirectionLabel("South", {z:1}, {y:Math.PI}); 103 | createDirectionLabel("East", {x:1}, {y:-Math.PI/2}); 104 | createDirectionLabel("West", {x:-1}, {y:Math.PI/2}); 105 | createDirectionLabel("Up", {y:1}, {x:Math.PI/2}); 106 | createDirectionLabel("Down", {y:-1}, {x:-Math.PI/2}); 107 | }); 108 | 109 | // the updateEvent is called each time the 3D world should be 110 | // rendered, before the renderEvent. The state of your application 111 | // should be updated here. 112 | app.updateEvent.addEventListener(() => { 113 | // get the position and orientation of the "stage", 114 | // to anchor our content. The "stage" defines an East-Up-South 115 | // coordinate system (assuming geolocation is available). 116 | const stageEUSPose = app.getEntityPose(app.stageEUS); 117 | 118 | // If we know the user's geopose, set the position of our 119 | // THREE user object to match the stageEUS frame 120 | if (stageEUSPose.poseStatus & Argon.PoseStatus.KNOWN) { 121 | stage.position.copy(stageEUSPose.position); 122 | stage.quaternion.copy(stageEUSPose.orientation); 123 | } else { 124 | // If not, position the labels on the non-geopose stage 125 | const stagePose = app.getEntityPose(app.stage); 126 | if (stagePose.poseStatus & Argon.PoseStatus.KNOWN) { 127 | stage.position.copy(stagePose.position); 128 | stage.quaternion.copy(stagePose.orientation); 129 | } 130 | } 131 | 132 | // get sun and moon positions, add/remove lights as necessary 133 | var date = app.context.time; 134 | sunMoonLights.update(date, app.context.origin); 135 | 136 | // place directions content at appropriate height on stage depending on user tracking and display mode 137 | if (app.userTracking === '6DOF') { 138 | if (app.displayMode === 'head') { 139 | directions.position.y = Argon.AVERAGE_EYE_HEIGHT; 140 | } else { 141 | directions.position.y = Argon.AVERAGE_EYE_HEIGHT / 2; 142 | } 143 | } else { 144 | const userStagePose = app.getEntityPose(app.user, app.stage); 145 | directions.position.y = userStagePose.position.y; 146 | } 147 | }) 148 | 149 | // renderEvent is fired whenever argon wants the app to update its display 150 | app.renderEvent.addEventListener(() => { 151 | // set the renderer to know the current size of the viewport. 152 | // This is the full size of the viewport, which would include 153 | // both views if we are in stereo viewing mode 154 | const view = app.view; 155 | renderer.setSize(view.renderWidth, view.renderHeight, false); 156 | renderer.setPixelRatio(app.suggestedPixelRatio); 157 | 158 | const viewport = view.viewport; 159 | hud.setSize(viewport.width, viewport.height); 160 | 161 | // There is 1 subview in monocular mode, 2 in stereo mode. 162 | // If we are in mono view, show the description. If not, hide it, 163 | if (app.view.subviews.length > 1) { 164 | holder.style.display = 'none'; 165 | } else { 166 | holder.style.display = 'block'; 167 | } 168 | 169 | // there is 1 subview in monocular mode, 2 in stereo mode 170 | for (let subview of app.view.subviews) { 171 | // set the position and orientation of the camera for 172 | // this subview 173 | camera.position.copy(subview.pose.position); 174 | camera.quaternion.copy(subview.pose.orientation); 175 | // the underlying system provide a full projection matrix 176 | // for the camera. 177 | camera.projectionMatrix.fromArray(subview.frustum.projectionMatrix); 178 | 179 | // set the viewport for this view 180 | var {x,y,width,height} = subview.renderViewport; 181 | renderer.setViewport(x,y,width,height); 182 | 183 | // set the webGL rendering parameters and render this view 184 | renderer.setScissor(x,y,width,height); 185 | renderer.setScissorTest(true); 186 | renderer.render(scene, camera); 187 | 188 | // adjust the hud 189 | var {x,y,width,height} = subview.viewport; 190 | hud.setViewport(x,y,width,height, subview.index); 191 | hud.render(subview.index); 192 | } 193 | stats.update(); 194 | }) -------------------------------------------------------------------------------- /code/directionsWebGL/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Directions WebGL 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 38 | 39 | 40 |
41 |
42 |
43 |

Six directions in WebGL

44 |
(click to dismiss)
45 |

This example displays a directional reference frame around the camera in Cartesian coordinates, using the EastUpSouth orientation for positive (x, y, z). A userLocation geospatial entity is created and positioned at the position of the user, and updated when the user's position changes. It uses WebGL to put a sphere at 200 meters and a text label at 100 meters in each of the negative/positive directions: x is west/east; y is down/up; z is north/south.

46 |
47 |
48 |
49 | 50 | 55 | 56 | 65 | -------------------------------------------------------------------------------- /code/directionsWebGL/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /code/draggablecubes/crosshair_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/draggablecubes/crosshair_small.png -------------------------------------------------------------------------------- /code/draggablecubes/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Draggagle Cubes WebGL 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |
21 |
22 |
23 | 26 |
27 |
28 |

Draggable Cubes in the World

29 |
(click to dismiss)
30 |

This example repurposes the THREE.js draggablecubes example. The cubes have been put 31 | around you in the world. When selected, a cube will then move as the 32 | device moves, keeping it's position relative to the device. You can use touch/mouse interaction, 33 | or crosshair interaction.

34 |
35 |
36 | 37 | 42 | 43 | 52 | -------------------------------------------------------------------------------- /code/draggablecubes/original-draggablecubes-example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | three.js webgl - draggable cubes 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 254 | 255 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /code/draggablecubes/style.css: -------------------------------------------------------------------------------- 1 | #description { 2 | pointer-events: auto; 3 | font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; 4 | padding: 10px; 5 | background-color:rgba(255,255,255,0.7); 6 | -webkit-backdrop-filter: blur(5px); 7 | position:absolute; 8 | bottom: 0px; 9 | } 10 | 11 | .argon-focus #description { 12 | transition: opacity 0.8s; 13 | visibility: visible; 14 | opacity: 1; 15 | } 16 | 17 | .argon-no-focus #description { 18 | transition: visibility 0s linear 0.8s, opacity 0.8s; 19 | visibility: visible; 20 | opacity: 0; 21 | } 22 | canvas { 23 | pointer-events: auto !important; 24 | } 25 | 26 | body { 27 | margin: 0; 28 | font-family: Arial; 29 | overflow: hidden; 30 | } 31 | 32 | a { 33 | color: #ffffff; 34 | } 35 | 36 | #menu { 37 | position: absolute; 38 | top: 5px; 39 | width: 100%; 40 | text-align: center; 41 | pointer-events: auto; 42 | } 43 | 44 | button { 45 | color: white; 46 | background: rgba(27,55,55,0.75);; 47 | outline: 1px solid rgba(127,255,255,0.75); 48 | border: 0px; 49 | margin-bottom: 20px; 50 | padding: 5px 10px; 51 | cursor: pointer; 52 | } 53 | 54 | button:hover { 55 | color: #000000; 56 | background-color: rgba(0,255,255,0.5); 57 | } 58 | 59 | button:active { 60 | color: #000000; 61 | background-color: rgba(0,255,255,0.75); 62 | } 63 | 64 | 65 | .argon-focus #hud { 66 | transition: opacity 0.8s; 67 | visibility: visible; 68 | opacity: 1; 69 | } 70 | 71 | .argon-no-focus #hud { 72 | transition: visibility 0s linear 0.8s, opacity 0.8s; 73 | visibility: visible; 74 | opacity: 0; 75 | } 76 | 77 | #hud { 78 | pointer-events: auto; 79 | } 80 | 81 | .crosshair { 82 | width: 100%; 83 | height: 100%; 84 | } 85 | 86 | .show-crosshair { 87 | transition: opacity 0.8s; 88 | visibility: visible; 89 | opacity: 1; 90 | } 91 | 92 | .hide-crosshair { 93 | transition: visibility 0s linear 0.8s, opacity 0.8s; 94 | visibility: visible; 95 | opacity: 0; 96 | } 97 | 98 | #crosshair-wrapper { 99 | position: absolute; 100 | top: 50%; 101 | left: 50%; 102 | 103 | height: 20px; 104 | width: 20px; 105 | transform: translateY(-50%) translateX(-50%); 106 | -webkit-user-select: none; 107 | } 108 | -------------------------------------------------------------------------------- /code/draggablecubes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /code/geopose/box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/geopose/box.png -------------------------------------------------------------------------------- /code/geopose/buzz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/geopose/buzz.png -------------------------------------------------------------------------------- /code/geopose/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Geo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 | 21 |
22 |
23 | 24 | 25 |
26 |

A Simple Geo example

27 |
(click to dismiss)
28 |

This example takes the current location of the viewer, and positions a cube at a well known nearby location (the Georgia Tech campus, for us), and creates a second cube a small distance away from where the viewer was positioned when the example was loaded. We do this by adding a small amount to our current east-west location, in the local Three.js cartesian coordinates. This illustrates how to create geospatial content based on the current location, and update the internal geospatial location of the object.

29 |
30 | 31 | 32 | 33 | 38 | 47 | 48 | -------------------------------------------------------------------------------- /code/geopose/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial; 3 | } 4 | 5 | a { 6 | color: #ffffff; 7 | } 8 | 9 | .menu { 10 | position: absolute; 11 | bottom: 0; 12 | width: 100%; 13 | text-align: center; 14 | pointer-events: none; 15 | } 16 | 17 | button { 18 | color: white; 19 | background: rgba(27,55,55,0.75);; 20 | outline: 1px solid rgba(127,255,255,0.75); 21 | border: 0px; 22 | margin-bottom: 20px; 23 | padding: 5px 10px; 24 | cursor: pointer; 25 | } 26 | 27 | button:hover { 28 | background-color: rgba(0,255,255,0.5); 29 | } 30 | 31 | button:active { 32 | color: #000000; 33 | background-color: rgba(0,255,255,0.75); 34 | } 35 | 36 | #description { 37 | pointer-events: auto; 38 | font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; 39 | padding: 10px; 40 | background-color:rgba(255,255,255,0.7); 41 | -webkit-backdrop-filter: blur(5px); 42 | position:absolute; 43 | bottom: 0px; 44 | } 45 | 46 | .argon-focus #menu { 47 | transition: opacity 0.8s; 48 | visibility: visible; 49 | opacity: 1; 50 | } 51 | 52 | .argon-no-focus #menu { 53 | transition: visibility 0s linear 0.8s, opacity 0.8s; 54 | visibility: visible; 55 | opacity: 0; 56 | } 57 | 58 | #hud { 59 | pointer-events: auto; 60 | } 61 | -------------------------------------------------------------------------------- /code/geopose/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /code/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 28 | Samples 29 | 30 | 31 |

Samples

32 |

Examples illustrating how to use argon.js to create AR web pages.

33 | Geopose 34 | Vuforia 35 | Vuforia Decals 36 | Directions HTML 37 | Directions WebGL 38 | Periodic Table 39 | Panoramas 40 | Streetview 41 | Draggable Cubes 42 | JSARToolKit 43 | Vuforia-JSARToolKit 44 | Tango(experimental) 45 |
46 |
47 | Source on GitHub 48 |
49 |
50 |

Hosting of this site provided by Netlify

51 | 52 | 61 | 62 | -------------------------------------------------------------------------------- /code/jsartoolkit/app.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | // set up Argon. Share the canvas so the webrtc reality can draw the 6 | // video background in it 7 | var app = Argon.init(null, { 'sharedCanvas': true }, null); 8 | // set up THREE. Create a scene, a perspective camera and an object 9 | // for the user's location 10 | var scene = new THREE.Scene(); 11 | var camera = new THREE.PerspectiveCamera(); 12 | var userLocation = new THREE.Object3D(); 13 | scene.add(camera); 14 | scene.add(userLocation); 15 | scene.autoUpdate = false; 16 | // We use the standard WebGLRenderer when we only need WebGL-based content 17 | var renderer = new THREE.WebGLRenderer({ 18 | alpha: true, 19 | logarithmicDepthBuffer: true, 20 | antialias: Argon.suggestedWebGLContextAntialiasAttribute 21 | }); 22 | // account for the pixel density of the device 23 | renderer.setPixelRatio(window.devicePixelRatio); 24 | renderer.domElement.style.position = 'absolute'; 25 | renderer.domElement.style.bottom = '0'; 26 | renderer.domElement.style.left = '0'; 27 | renderer.domElement.style.width = '100%'; 28 | renderer.domElement.style.height = '100%'; 29 | app.view.element.appendChild(renderer.domElement); 30 | // do not clear the canvas when sharing it 31 | renderer.autoClear = false; 32 | // to easily control stuff on the display 33 | var hud = new THREE.CSS3DArgonHUD(); 34 | // We put some elements in the index.html, for convenience. 35 | // Here, we retrieve the description box and move it to the 36 | // the CSS3DArgonHUD hudElements[0]. We only put it in the left 37 | // hud since we'll be hiding it in stereo 38 | var description = document.getElementById('description'); 39 | hud.hudElements[0].appendChild(description); 40 | app.view.element.appendChild(hud.domElement); 41 | // let's show the rendering stats 42 | var stats = new Stats(); 43 | hud.hudElements[0].appendChild(stats.dom); 44 | // set the layers of our view 45 | app.view.setLayers([ 46 | { source: renderer.domElement }, 47 | { source: hud.domElement } 48 | ]); 49 | // create a bit of animated 3D text that says "argon.js" to display 50 | var uniforms = { 51 | amplitude: { type: "f", value: 0.0 } 52 | }; 53 | var argonTextObject = new THREE.Object3D(); 54 | argonTextObject.position.z = -0.5; 55 | userLocation.add(argonTextObject); 56 | var loader = new THREE.FontLoader(); 57 | loader.load('../resources/fonts/helvetiker_bold.typeface.json', function (font) { 58 | var shaderMaterial = new THREE.ShaderMaterial({ 59 | uniforms: uniforms, 60 | vertexShader: "\n uniform float amplitude;\n attribute vec3 customColor;\n attribute vec3 displacement;\n varying vec3 vNormal;\n varying vec3 vColor;\n void main() {\n vNormal = normal;\n vColor = customColor;\n vec3 newPosition = position + normal * amplitude * displacement;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );\n }\n ", 61 | fragmentShader: "\n varying vec3 vNormal;\n varying vec3 vColor;\n void main() {\n const float ambient = 0.4;\n vec3 light = vec3( 1.0 );\n light = normalize( light );\n float directional = max( dot( vNormal, light ), 0.0 );\n gl_FragColor = vec4( ( directional + ambient ) * vColor, 1.0 );\n }\n " 62 | }); 63 | var argonTextMesh = createTextMesh(font, "argon.js", shaderMaterial); 64 | argonTextObject.add(argonTextMesh); 65 | argonTextObject.scale.set(0.001, 0.001, 0.001); 66 | argonTextObject.position.z = -0.50; 67 | // add an argon updateEvent listener to slowly change the text over time. 68 | // we don't have to pack all our logic into one listener. 69 | app.context.updateEvent.addEventListener(function () { 70 | uniforms.amplitude.value = 1.0 + Math.sin(Date.now() * 0.001 * 0.5); 71 | }); 72 | }); 73 | function createTextMesh(font, text, material) { 74 | var textGeometry = new THREE.TextGeometry(text, { 75 | font: font, 76 | size: 40, 77 | height: 5, 78 | curveSegments: 3, 79 | bevelThickness: 2, 80 | bevelSize: 1, 81 | bevelEnabled: true 82 | }); 83 | textGeometry.center(); 84 | var tessellateModifier = new THREE.TessellateModifier(8); 85 | for (var i = 0; i < 6; i++) { 86 | tessellateModifier.modify(textGeometry); 87 | } 88 | var explodeModifier = new THREE.ExplodeModifier(); 89 | explodeModifier.modify(textGeometry); 90 | var numFaces = textGeometry.faces.length; 91 | var bufferGeometry = new THREE.BufferGeometry().fromGeometry(textGeometry); 92 | var colors = new Float32Array(numFaces * 3 * 3); 93 | var displacement = new Float32Array(numFaces * 3 * 3); 94 | var color = new THREE.Color(); 95 | for (var f = 0; f < numFaces; f++) { 96 | var index = 9 * f; 97 | var h = 0.07 + 0.1 * Math.random(); 98 | var s = 0.5 + 0.5 * Math.random(); 99 | var l = 0.6 + 0.4 * Math.random(); 100 | color.setHSL(h, s, l); 101 | var d = 5 + 20 * (0.5 - Math.random()); 102 | for (var i = 0; i < 3; i++) { 103 | colors[index + (3 * i)] = color.r; 104 | colors[index + (3 * i) + 1] = color.g; 105 | colors[index + (3 * i) + 2] = color.b; 106 | displacement[index + (3 * i)] = d; 107 | displacement[index + (3 * i) + 1] = d; 108 | displacement[index + (3 * i) + 2] = d; 109 | } 110 | } 111 | bufferGeometry.addAttribute('customColor', new THREE.BufferAttribute(colors, 3)); 112 | bufferGeometry.addAttribute('displacement', new THREE.BufferAttribute(displacement, 3)); 113 | var textMesh = new THREE.Mesh(bufferGeometry, material); 114 | return textMesh; 115 | } 116 | // set our desired reality 117 | app.reality.request(Argon.RealityViewer.WEBRTC); 118 | var webrtcRealitySession; 119 | // start listening for connections to a reality 120 | app.reality.connectEvent.addEventListener(function (session) { 121 | if (session.supportsProtocol('ar.jsartoolkit')) { 122 | // save a reference to this session 123 | webrtcRealitySession = session; 124 | webrtcRealitySession.request('ar.jsartoolkit.init').then(function () { 125 | webrtcRealitySession.request('ar.jsartoolkit.addMarker', { 126 | url: "../resources/artoolkit/patt.hiro" 127 | }).then(function (msg) { 128 | if (!msg) 129 | return; 130 | // tell argon we want to track a specific marker. Each marker 131 | // has a Cesium entity associated with it, and is expressed in a 132 | // coordinate frame relative to the camera. Because they are Cesium 133 | // entities, we can ask for their pose in any coordinate frame we know 134 | // about. 135 | var hiroEntity = app.context.subscribeToEntityById(msg.id); 136 | // create a THREE object to put on the marker 137 | var hiroObject = new THREE.Object3D; 138 | scene.add(hiroObject); 139 | // the updateEvent is called each time the 3D world should be 140 | // rendered, before the renderEvent. The state of your application 141 | // should be updated here. 142 | app.context.updateEvent.addEventListener(function () { 143 | // get the pose (in local coordinates) of the marker 144 | var hiroPose = app.context.getEntityPose(hiroEntity); 145 | // if the pose is known the target is visible, so set the 146 | // THREE object to the location and orientation 147 | if (hiroPose.poseStatus & Argon.PoseStatus.KNOWN) { 148 | hiroObject.position.copy(hiroPose.position); 149 | hiroObject.quaternion.copy(hiroPose.orientation); 150 | } 151 | // when the target is first seen after not being seen, the 152 | // status is FOUND. Here, we move the 3D text object from the 153 | // world to the target. 154 | // when the target is first lost after being seen, the status 155 | // is LOST. Here, we move the 3D text object back to the world 156 | if (hiroPose.poseStatus & Argon.PoseStatus.FOUND) { 157 | console.log("marker found"); 158 | hiroObject.add(argonTextObject); 159 | // note: currently artoolkit markers are always considered 1 meter across 160 | // this scale is a temporary fix 161 | argonTextObject.scale.set(0.01, 0.01, 0.01); 162 | argonTextObject.position.z = 0; 163 | } 164 | else if (hiroPose.poseStatus & Argon.PoseStatus.LOST) { 165 | console.log("marker lost"); 166 | argonTextObject.scale.set(0.001, 0.001, 0.001); 167 | argonTextObject.position.z = -0.50; 168 | userLocation.add(argonTextObject); 169 | } 170 | }); 171 | }); 172 | }); 173 | } 174 | }); 175 | // the updateEvent is called each time the 3D world should be 176 | // rendered, before the renderEvent. The state of your application 177 | // should be updated here. 178 | app.context.updateEvent.addEventListener(function () { 179 | // get the position and orientation (the "pose") of the user 180 | // in the local coordinate frame. 181 | var userPose = app.context.getEntityPose(app.context.user); 182 | // assuming we know the user's pose, set the position of our 183 | // THREE user object to match it 184 | if (userPose.poseStatus & Argon.PoseStatus.KNOWN) { 185 | userLocation.position.copy(userPose.position); 186 | } 187 | // udpate our scene matrices 188 | scene.updateMatrixWorld(false); 189 | }); 190 | // renderEvent is fired whenever argon wants the app to update its display 191 | app.renderEvent.addEventListener(function () { 192 | if (app.reality.isSharedCanvas) { 193 | // if this is a shared canvas we can't depend on our GL state 194 | // being exactly how we left it last frame 195 | renderer.resetGLState(); 196 | } 197 | else { 198 | // not a shared canvas, we need to clear it before rendering 199 | renderer.clear(); 200 | } 201 | // update the rendering stats 202 | stats.update(); 203 | // get the subviews for the current frame 204 | var subviews = app.view.subviews; 205 | // if we have 1 subView, we're in mono mode. If more, stereo. 206 | var monoMode = subviews.length == 1; 207 | // set the renderer to know the current size of the viewport. 208 | // This is the full size of the viewport, which would include 209 | // both subviews if we are in stereo viewing mode 210 | var view = app.view; 211 | renderer.setSize(view.renderWidth, view.renderHeight, false); 212 | renderer.setPixelRatio(app.suggestedPixelRatio); 213 | var viewport = view.viewport; 214 | hud.setSize(viewport.width, viewport.height); 215 | // there is 1 subview in monocular mode, 2 in stereo mode 216 | for (var _i = 0, subviews_1 = subviews; _i < subviews_1.length; _i++) { 217 | var subview = subviews_1[_i]; 218 | // set the position and orientation of the camera for 219 | // this subview 220 | camera.position.copy(subview.pose.position); 221 | camera.quaternion.copy(subview.pose.orientation); 222 | // the underlying system provide a full projection matrix 223 | // for the camera. 224 | camera.projectionMatrix.fromArray(subview.frustum.projectionMatrix); 225 | // set the viewport for this view 226 | var _a = subview.renderViewport, x = _a.x, y = _a.y, width = _a.width, height = _a.height; 227 | renderer.setViewport(x, y, width, height); 228 | // set the webGL rendering parameters and render this view 229 | renderer.setScissor(x, y, width, height); 230 | renderer.setScissorTest(true); 231 | renderer.render(scene, camera); 232 | // adjust the hud, but only in mono 233 | if (monoMode) { 234 | var _b = subview.viewport, x = _b.x, y = _b.y, width = _b.width, height = _b.height; 235 | hud.setViewport(x, y, width, height, subview.index); 236 | hud.render(subview.index); 237 | } 238 | } 239 | }); 240 | -------------------------------------------------------------------------------- /code/jsartoolkit/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | JSARToolKit 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 41 | 42 | 43 |
44 |
45 |

JSARToolKit Demo

46 |
(click to dismiss)
47 |

This example puts a dynamic 3D model of the text "argon.js" on the ARToolKit Hiro marker. When the marker is not seen, the text appears directly north.

48 |

Note that this sample only works in browsers supporting WebRTC (e.g. Desktop or Android Chrome)

49 |
50 |
51 | 52 | 57 | 58 | 67 | -------------------------------------------------------------------------------- /code/jsartoolkit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "lib": [ 5 | "dom", 6 | "es2015" 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /code/panorama-reality-test/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 28 | My Panorama Tour 29 | 30 |
31 | 32 | 41 | 42 | -------------------------------------------------------------------------------- /code/panorama-reality-test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ], 9 | "strictNullChecks": true 10 | } 11 | } -------------------------------------------------------------------------------- /code/panorama-reality/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | My Panorama Tour 16 | 17 | 18 | 19 | 28 | 29 | -------------------------------------------------------------------------------- /code/panorama-reality/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ], 9 | "strictNullChecks": true 10 | } 11 | } -------------------------------------------------------------------------------- /code/panoramas/app.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | // set up Argon 4 | var app = Argon.init('#my-pano-argon-app'); 5 | // set up THREE. Create a scene, a perspective camera and an object 6 | // for the user's location 7 | var scene = new THREE.Scene(); 8 | var camera = new THREE.PerspectiveCamera(); 9 | var stage = new THREE.Object3D; 10 | scene.add(camera); 11 | scene.add(stage); 12 | // We use the standard WebGLRenderer when we only need WebGL-based content 13 | var renderer = new THREE.WebGLRenderer({ 14 | alpha: true, 15 | logarithmicDepthBuffer: true, 16 | antialias: Argon.suggestedWebGLContextAntialiasAttribute 17 | }); 18 | // account for the pixel density of the device 19 | renderer.setPixelRatio(window.devicePixelRatio); 20 | app.view.setLayers([{ source: renderer.domElement }]); 21 | // add some ambient so things aren't so harshly illuminated 22 | var ambientlight = new THREE.AmbientLight(0x404040); // soft white ambient light 23 | scene.add(ambientlight); 24 | // set our desired reality 25 | app.reality.request(Argon.resolveURL('../panorama-reality/index.html')); 26 | var panoRealitySession; 27 | // list our panoramas 28 | var panoramas = [{ 29 | name: 'Georgia Aquarium', 30 | url: Argon.resolveURL('images/aqui.jpg'), 31 | longitude: -84.3951, 32 | latitude: 33.7634, 33 | height: 206 34 | }, 35 | { 36 | name: 'Centennial Park', 37 | url: Argon.resolveURL('images/cent.jpg'), 38 | longitude: -84.3931, 39 | latitude: 33.7608, 40 | height: 309 41 | }, 42 | { 43 | name: 'High Museum', 44 | url: Argon.resolveURL('images/high.jpg'), 45 | longitude: -84.38584, 46 | latitude: 33.79035, 47 | height: 289 48 | }, 49 | { 50 | name: 'Piedmont Park', 51 | url: Argon.resolveURL('images/pied.jpg'), 52 | longitude: -84.37427, 53 | latitude: 33.78577, 54 | height: 271 55 | } 56 | ]; 57 | var currentPanorama; 58 | // get the menu element 59 | var menu = document.getElementById('menu'); 60 | menu.style.zIndex = '2'; 61 | // add buttons to the menu for each panorama 62 | panoramas.forEach(function (p) { 63 | var button = document.createElement('button'); 64 | button.textContent = p.name; 65 | menu.appendChild(button); 66 | // when a button is tapped, have the reality fade in the corresponding panorama 67 | button.addEventListener('click', function () { 68 | if (panoRealitySession) { 69 | panoRealitySession.request('edu.gatech.ael.panorama.showPanorama', { 70 | url: p.url, 71 | transition: { 72 | easing: 'Quadratic.InOut', 73 | duration: 1000 74 | } 75 | }).then(function () { 76 | currentPanorama = p; 77 | }); 78 | } 79 | }); 80 | }); 81 | app.focusEvent.on(function () { 82 | document.getElementById('menu').style.display = 'block'; 83 | }); 84 | app.blurEvent.on(function () { 85 | document.getElementById('menu').style.display = 'none'; 86 | }); 87 | // start listening for connections to a reality 88 | app.reality.connectEvent.on(function (session) { 89 | // check if the connected supports our panorama protocol 90 | if (session.supportsProtocol('edu.gatech.ael.panorama')) { 91 | // save a reference to this session so our buttons can send messages 92 | panoRealitySession = session; 93 | // show the menu 94 | document.getElementById('menu').style.visibility = 'visible'; 95 | // load our panoramas 96 | panoramas.forEach(function (p) { 97 | panoRealitySession.request('edu.gatech.ael.panorama.loadPanorama', p); 98 | }); 99 | // fade in the first panorama slowly 100 | panoRealitySession.request('edu.gatech.ael.panorama.showPanorama', { 101 | url: panoramas[0].url, 102 | transition: { 103 | easing: 'Quadratic.InOut', 104 | duration: 2000 105 | } 106 | }).then(function () { 107 | currentPanorama = panoramas[0]; 108 | }); 109 | // hide the menu when the reality session closes 110 | session.closeEvent.on(function () { 111 | document.getElementById('menu').style.visibility = 'collapse'; 112 | panoRealitySession = undefined; 113 | currentPanorama = undefined; 114 | }); 115 | } 116 | }); 117 | var myMysteriousLabel = new THREE.Object3D(); 118 | // create a label 119 | var loader = new THREE.FontLoader(); 120 | loader.load('../resources/fonts/helvetiker_regular.typeface.json', function (font) { 121 | var textOptions = { 122 | font: font, 123 | size: 15, 124 | height: 10, 125 | curveSegments: 10, 126 | bevelThickness: 1, 127 | bevelSize: 1, 128 | bevelEnabled: true 129 | }; 130 | var textMaterial = new THREE.MeshStandardMaterial({ 131 | color: 0x5588ff 132 | }); 133 | function createDirectionLabel(text, position, rotation) { 134 | var textGeometry = new THREE.TextGeometry(text, textOptions); 135 | textGeometry.center(); 136 | var textMesh = new THREE.Mesh(textGeometry, textMaterial); 137 | if (position.x) 138 | textMesh.position.x = position.x; 139 | if (position.y) 140 | textMesh.position.y = position.y; 141 | if (position.z) 142 | textMesh.position.z = position.z; 143 | if (rotation.x) 144 | textMesh.rotation.x = rotation.x; 145 | if (rotation.y) 146 | textMesh.rotation.y = rotation.y; 147 | if (rotation.z) 148 | textMesh.rotation.z = rotation.z; 149 | return textMesh; 150 | } 151 | var textMesh = createDirectionLabel("Pears!?", { x: -300 }, { y: Math.PI / 2 }); 152 | myMysteriousLabel.add(textMesh); 153 | }); 154 | // the updateEvent is called each time the 3D world should be 155 | // rendered, before the renderEvent. The state of your application 156 | // should be updated here. 157 | app.updateEvent.on(function () { 158 | // get the pose of the "stage" to anchor our content. 159 | // The "stage" defines an East-Up-South coordinate system 160 | // (assuming geolocation is available). 161 | var stagePose = app.getEntityPose(app.stage); 162 | // set the pose of our THREE stage object 163 | if (stagePose.poseStatus & Argon.PoseStatus.KNOWN) { 164 | stage.position.copy(stagePose.position); 165 | stage.quaternion.copy(stagePose.orientation); 166 | } 167 | // show a 3d label when displaying a particular panorama 168 | if (currentPanorama && currentPanorama.name === 'High Museum') { 169 | stage.add(myMysteriousLabel); 170 | } 171 | else { 172 | stage.remove(myMysteriousLabel); 173 | } 174 | }); 175 | // renderEvent is fired whenever argon wants the app to update its display 176 | app.renderEvent.on(function () { 177 | // set the renderer to know the current size of the viewport. 178 | // This is the full size of the viewport, which would include 179 | // both views if we are in stereo viewing mode 180 | var view = app.view; 181 | renderer.setSize(view.renderWidth, view.renderHeight, false); 182 | renderer.setPixelRatio(app.suggestedPixelRatio); 183 | // there is 1 subview in monocular mode, 2 in stereo mode 184 | for (var _i = 0, _a = app.view.subviews; _i < _a.length; _i++) { 185 | var subview = _a[_i]; 186 | // set the position and orientation of the camera for 187 | // this subview 188 | camera.position.copy(subview.pose.position); 189 | camera.quaternion.copy(subview.pose.orientation); 190 | // the underlying system provide a full projection matrix 191 | // for the camera. 192 | camera.projectionMatrix.fromArray(subview.frustum.projectionMatrix); 193 | // set the viewport for this view 194 | var _b = subview.renderViewport, x = _b.x, y = _b.y, width = _b.width, height = _b.height; 195 | renderer.setViewport(x, y, width, height); 196 | // set the webGL rendering parameters and render this view 197 | renderer.setScissor(x, y, width, height); 198 | renderer.setScissorTest(true); 199 | renderer.render(scene, camera); 200 | } 201 | }); 202 | -------------------------------------------------------------------------------- /code/panoramas/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // set up Argon 5 | const app = Argon.init('#my-pano-argon-app'); 6 | 7 | // set up THREE. Create a scene, a perspective camera and an object 8 | // for the user's location 9 | const scene = new THREE.Scene(); 10 | const camera = new THREE.PerspectiveCamera(); 11 | const stage = new THREE.Object3D; 12 | scene.add(camera); 13 | scene.add(stage); 14 | 15 | // We use the standard WebGLRenderer when we only need WebGL-based content 16 | const renderer = new THREE.WebGLRenderer({ 17 | alpha: true, 18 | logarithmicDepthBuffer: true, 19 | antialias: Argon.suggestedWebGLContextAntialiasAttribute 20 | }); 21 | 22 | // account for the pixel density of the device 23 | renderer.setPixelRatio(window.devicePixelRatio); 24 | app.view.setLayers([{source: renderer.domElement}]); 25 | 26 | // add some ambient so things aren't so harshly illuminated 27 | var ambientlight = new THREE.AmbientLight( 0x404040 ); // soft white ambient light 28 | scene.add(ambientlight); 29 | 30 | // set our desired reality 31 | app.reality.request(Argon.resolveURL('../panorama-reality/index.html')) 32 | 33 | // the information needed for each panorama to be used. Panoramas need to be geolocated to be 34 | // used with the Reality, since a Reality must provide the position and orientation of the camera 35 | interface PanoramaInfo { 36 | name: string, 37 | url: string, 38 | longitude?: number, 39 | latitude?: number, 40 | height?: number, 41 | offsetDegrees?: number 42 | } 43 | 44 | let panoRealitySession:Argon.SessionPort; 45 | 46 | // list our panoramas 47 | const panoramas:PanoramaInfo[] = [{ 48 | name: 'Georgia Aquarium', 49 | url: Argon.resolveURL('images/aqui.jpg'), 50 | longitude: -84.3951, 51 | latitude: 33.7634, 52 | height: 206 53 | }, 54 | { 55 | name: 'Centennial Park', 56 | url: Argon.resolveURL('images/cent.jpg'), 57 | longitude: -84.3931, 58 | latitude: 33.7608, 59 | height: 309 60 | }, 61 | { 62 | name: 'High Museum', 63 | url: Argon.resolveURL('images/high.jpg'), 64 | longitude: -84.38584, 65 | latitude: 33.79035, 66 | height: 289 67 | }, 68 | { 69 | name: 'Piedmont Park', 70 | url: Argon.resolveURL('images/pied.jpg'), 71 | longitude: -84.37427, 72 | latitude: 33.78577, 73 | height: 271 74 | } 75 | ]; 76 | let currentPanorama:PanoramaInfo; 77 | 78 | // get the menu element 79 | var menu = document.getElementById('menu'); 80 | menu.style.zIndex = '2'; 81 | 82 | // add buttons to the menu for each panorama 83 | panoramas.forEach((p)=>{ 84 | var button = document.createElement('button'); 85 | button.textContent = p.name; 86 | menu.appendChild(button); 87 | // when a button is tapped, have the reality fade in the corresponding panorama 88 | button.addEventListener('click', ()=>{ 89 | if (panoRealitySession) { 90 | panoRealitySession.request('edu.gatech.ael.panorama.showPanorama', { 91 | url: p.url, 92 | transition: { 93 | easing: 'Quadratic.InOut', 94 | duration: 1000 95 | } 96 | }).then(()=>{ 97 | currentPanorama = p; 98 | }) 99 | } 100 | }) 101 | }) 102 | 103 | app.focusEvent.on(()=>{ 104 | document.getElementById('menu').style.display = 'block'; 105 | }) 106 | app.blurEvent.on(()=>{ 107 | document.getElementById('menu').style.display = 'none'; 108 | }) 109 | 110 | // start listening for connections to a reality 111 | app.reality.connectEvent.on((session)=>{ 112 | // check if the connected supports our panorama protocol 113 | if (session.supportsProtocol('edu.gatech.ael.panorama')) { 114 | // save a reference to this session so our buttons can send messages 115 | panoRealitySession = session 116 | // show the menu 117 | document.getElementById('menu').style.visibility = 'visible'; 118 | // load our panoramas 119 | panoramas.forEach((p)=>{ 120 | panoRealitySession.request('edu.gatech.ael.panorama.loadPanorama', p); 121 | }) 122 | // fade in the first panorama slowly 123 | panoRealitySession.request('edu.gatech.ael.panorama.showPanorama', { 124 | url: panoramas[0].url, 125 | transition: { 126 | easing: 'Quadratic.InOut', 127 | duration: 2000 128 | } 129 | }).then(()=>{ 130 | currentPanorama = panoramas[0]; 131 | }) 132 | // hide the menu when the reality session closes 133 | session.closeEvent.on(()=>{ 134 | document.getElementById('menu').style.visibility = 'collapse'; 135 | panoRealitySession = undefined; 136 | currentPanorama = undefined; 137 | }) 138 | } 139 | }) 140 | 141 | const myMysteriousLabel = new THREE.Object3D(); 142 | 143 | // create a label 144 | var loader = new THREE.FontLoader(); 145 | loader.load( '../resources/fonts/helvetiker_regular.typeface.json', function ( font ) { 146 | const textOptions = { 147 | font: font, 148 | size: 15, 149 | height: 10, 150 | curveSegments: 10, 151 | bevelThickness: 1, 152 | bevelSize: 1, 153 | bevelEnabled: true 154 | } 155 | 156 | var textMaterial = new THREE.MeshStandardMaterial({ 157 | color: 0x5588ff 158 | }) 159 | 160 | function createDirectionLabel(text, position, rotation) { 161 | var textGeometry = new THREE.TextGeometry(text, textOptions); 162 | textGeometry.center(); 163 | var textMesh = new THREE.Mesh(textGeometry, textMaterial); 164 | if (position.x) textMesh.position.x = position.x; 165 | if (position.y) textMesh.position.y = position.y; 166 | if (position.z) textMesh.position.z = position.z; 167 | if (rotation.x) textMesh.rotation.x = rotation.x; 168 | if (rotation.y) textMesh.rotation.y = rotation.y; 169 | if (rotation.z) textMesh.rotation.z = rotation.z; 170 | return textMesh; 171 | } 172 | 173 | var textMesh = createDirectionLabel("Pears!?", {x:-300}, {y:Math.PI/2}); 174 | myMysteriousLabel.add(textMesh); 175 | }) 176 | 177 | 178 | // the updateEvent is called each time the 3D world should be 179 | // rendered, before the renderEvent. The state of your application 180 | // should be updated here. 181 | app.updateEvent.on(() => { 182 | // get the pose of the "stage" to anchor our content. 183 | // The "stage" defines an East-Up-South coordinate system 184 | // (assuming geolocation is available). 185 | const stagePose = app.getEntityPose(app.stage); 186 | // set the pose of our THREE stage object 187 | if (stagePose.poseStatus & Argon.PoseStatus.KNOWN) { 188 | stage.position.copy(stagePose.position); 189 | stage.quaternion.copy(stagePose.orientation); 190 | } 191 | 192 | 193 | // show a 3d label when displaying a particular panorama 194 | if (currentPanorama && currentPanorama.name === 'High Museum') { 195 | stage.add(myMysteriousLabel); 196 | } else { 197 | stage.remove(myMysteriousLabel); 198 | } 199 | }) 200 | 201 | // renderEvent is fired whenever argon wants the app to update its display 202 | app.renderEvent.on(() => { 203 | // set the renderer to know the current size of the viewport. 204 | // This is the full size of the viewport, which would include 205 | // both views if we are in stereo viewing mode 206 | const view = app.view; 207 | renderer.setSize(view.renderWidth, view.renderHeight, false); 208 | renderer.setPixelRatio(app.suggestedPixelRatio); 209 | 210 | // there is 1 subview in monocular mode, 2 in stereo mode 211 | for (let subview of app.view.subviews) { 212 | // set the position and orientation of the camera for 213 | // this subview 214 | camera.position.copy(subview.pose.position); 215 | camera.quaternion.copy(subview.pose.orientation); 216 | // the underlying system provide a full projection matrix 217 | // for the camera. 218 | camera.projectionMatrix.fromArray(subview.frustum.projectionMatrix); 219 | 220 | // set the viewport for this view 221 | var {x,y,width,height} = subview.renderViewport; 222 | renderer.setViewport(x,y,width,height); 223 | 224 | // set the webGL rendering parameters and render this view 225 | renderer.setScissor(x,y,width,height); 226 | renderer.setScissorTest(true); 227 | renderer.render(scene, camera); 228 | } 229 | }) -------------------------------------------------------------------------------- /code/panoramas/images/aqui.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/panoramas/images/aqui.jpg -------------------------------------------------------------------------------- /code/panoramas/images/cent.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/panoramas/images/cent.jpg -------------------------------------------------------------------------------- /code/panoramas/images/high.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/panoramas/images/high.jpg -------------------------------------------------------------------------------- /code/panoramas/images/pied.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/panoramas/images/pied.jpg -------------------------------------------------------------------------------- /code/panoramas/images/woc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/panoramas/images/woc.jpg -------------------------------------------------------------------------------- /code/panoramas/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Panorama 6 | 7 | 8 | 9 | 10 | 11 | 12 | 97 | 98 | 99 |

My Travel Blog

100 |
101 |
102 | 103 |
104 |

Requesting a Custom Reality

105 |
(tap to dismiss)
106 |

This example demonstrates the use of custom reality views, a feature which enables multiple apps to together augment a custom view of reality. In this case, the app requests a reality created for rendering panoramas.

107 |
108 | 113 |
114 |
115 |
116 |

117 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam venenatis volutpat diam, sodales lobortis leo lacinia quis. Donec laoreet purus placerat tristique auctor. In faucibus ullamcorper dolor, eu scelerisque lectus interdum quis. Nulla magna mi, gravida vel tellus sollicitudin, finibus pretium erat. Aliquam dignissim lorem sed blandit pretium. Pellentesque sollicitudin lacinia aliquet. Pellentesque pharetra nunc id mollis laoreet. Maecenas laoreet diam nec sapien iaculis, id viverra dui luctus. 118 |

119 |

120 | Nullam risus magna, condimentum scelerisque elementum vel, porttitor non diam. Nullam quis arcu eu velit facilisis rutrum nec ac neque. Fusce sollicitudin ullamcorper dapibus. Quisque volutpat leo eget imperdiet luctus. Aliquam pharetra sapien nibh, in luctus elit accumsan a. Praesent lacinia tincidunt pretium. Curabitur quis nulla ut arcu tincidunt commodo. Donec nec fermentum neque, sit amet pulvinar tortor. Sed in quam ante. Nam malesuada nisl nec velit tristique, sed sagittis massa cursus. Mauris sit amet egestas lectus. Cras a nulla enim. Curabitur leo libero, porttitor at justo vel, sagittis euismod lorem. Praesent ullamcorper sed ante vel congue. Proin eget augue in erat euismod aliquet. 121 |

122 |

123 | In quis erat non nunc euismod efficitur. Maecenas vitae dolor et ligula interdum aliquet sit amet in nibh. Pellentesque sit amet justo et leo elementum malesuada at ac nisi. Sed bibendum dui a dignissim ultricies. Suspendisse eget eleifend metus, quis viverra mauris. Nullam pulvinar lacinia sodales. Aliquam commodo faucibus ante sed congue. Donec faucibus risus sit amet viverra ultrices. Proin tellus orci, tincidunt eu egestas et, vulputate quis nisi. Sed vitae varius eros. 124 |

125 |

126 | Praesent pulvinar lorem sed tellus auctor consequat. Interdum et malesuada fames ac ante ipsum primis in faucibus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In efficitur, risus sit amet scelerisque imperdiet, ante mauris molestie dolor, at finibus ex arcu a ex. Donec ligula nulla, ornare in lectus maximus, blandit sollicitudin sapien. Vivamus vel luctus orci, pellentesque volutpat metus. Quisque ultrices lacinia vestibulum. Donec nec tristique turpis. 127 |

128 |

129 | Duis gravida, enim quis ornare blandit, tortor metus dignissim ex, dapibus tincidunt erat urna vel enim. Donec mattis luctus neque et aliquet. Fusce at velit quam. Praesent vitae ligula tristique, tristique libero nec, viverra elit. Nulla hendrerit fringilla varius. Integer libero justo, tincidunt ac feugiat vitae, vehicula sed quam. Nam nibh ipsum, viverra ut pretium sed, pretium sed dolor. Integer semper tellus tincidunt, vestibulum lectus nec, vulputate purus. 130 |

131 |
132 | 133 | 134 | 143 | -------------------------------------------------------------------------------- /code/panoramas/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /code/periodic/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Periodic 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | 26 |
27 |
28 |
29 |

Periodic table (from three.js)

30 |
(click to dismiss)
31 |

This example adapts a three.js example showing the Periodic elements. In the three.js documentation, you can find the example written for the screen: The Argon version shows the four versions of the periodic table handing in space around the user. This illustrates how three.js is used to present and manipulate 3D graphics in Argon.

32 |
33 |
34 |
35 | 36 | 41 | 42 | 51 | -------------------------------------------------------------------------------- /code/periodic/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | } 4 | 5 | body { 6 | margin: 0; 7 | font-family: Arial; 8 | overflow: hidden; 9 | } 10 | 11 | a { 12 | color: #ffffff; 13 | } 14 | 15 | #menu { 16 | position: absolute; 17 | bottom: 50px; 18 | width: 100%; 19 | text-align: center; 20 | } 21 | 22 | .element { 23 | width: 120px; 24 | height: 160px; 25 | /* box-shadow: 0px 0px 20px rgba(0,255,255,0.5); */ 26 | border: 1px solid rgba(127,255,255,0.25); 27 | cursor: default; 28 | } 29 | 30 | .element:hover { 31 | /* box-shadow: 0px 0px 20px rgba(0,255,255,0.75); */ 32 | border: 1px solid rgba(127,255,255,1); 33 | } 34 | 35 | .element .number { 36 | position: absolute; 37 | top: 20px; 38 | right: 20px; 39 | font-size: 12px; 40 | color: rgba(127,255,255,0.75); 41 | } 42 | 43 | .element .symbol { 44 | position: absolute; 45 | top: 40px; 46 | width: 100%; 47 | font-size: 60px; 48 | text-align: center; 49 | color: rgba(255,255,255,0.75); 50 | font-weight: bold; 51 | } 52 | 53 | .element .details { 54 | position: absolute; 55 | bottom: 15px; 56 | width: 100%; 57 | font-size: 12px; 58 | text-align: center; 59 | color: rgba(127,255,255,0.75); 60 | } 61 | 62 | button { 63 | color: rgba(127,255,255,0.75); 64 | background: transparent; 65 | outline: 1px solid rgba(127,255,255,0.75); 66 | border: 0px; 67 | padding: 5px 10px; 68 | cursor: pointer; 69 | } 70 | button:hover { 71 | background-color: rgba(0,255,255,0.5); 72 | } 73 | button:active { 74 | color: #000000; 75 | background-color: rgba(0,255,255,0.75); 76 | } 77 | 78 | iframe { 79 | z-index: -1000; 80 | } 81 | 82 | #description { 83 | pointer-events: auto; 84 | font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; 85 | padding: 10px; 86 | background-color:rgba(255,255,255,0.7); 87 | -webkit-backdrop-filter: blur(5px); 88 | position:absolute; 89 | bottom: 0px; 90 | } 91 | 92 | .argon-focus #hud { 93 | transition: opacity 0.8s; 94 | visibility: visible; 95 | opacity: 1; 96 | } 97 | 98 | .argon-no-focus #hud { 99 | transition: visibility 0s linear 0.8s, opacity 0.8s; 100 | visibility: visible; 101 | opacity: 0; 102 | } 103 | 104 | #hud { 105 | pointer-events: auto; 106 | } 107 | -------------------------------------------------------------------------------- /code/resources/GVUBrochure.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/GVUBrochure.pdf -------------------------------------------------------------------------------- /code/resources/TechSquare.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/TechSquare.pdf -------------------------------------------------------------------------------- /code/resources/artoolkit/HiroPattern.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/artoolkit/HiroPattern.pdf -------------------------------------------------------------------------------- /code/resources/datasets/ArgonTutorial.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/datasets/ArgonTutorial.dat -------------------------------------------------------------------------------- /code/resources/datasets/ArgonTutorial.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /code/resources/datasets/GVUBrochure.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/datasets/GVUBrochure.dat -------------------------------------------------------------------------------- /code/resources/datasets/GVUBrochure.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /code/resources/datasets/StonesAndChips.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/datasets/StonesAndChips.dat -------------------------------------------------------------------------------- /code/resources/datasets/StonesAndChips.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /code/resources/fonts/LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/fonts/LICENSE -------------------------------------------------------------------------------- /code/resources/geometries/DecalGeometry.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Mugen87 / https://github.com/Mugen87 3 | * @author spite / https://github.com/spite 4 | * 5 | * You can use this geometry to create a decal mesh, that serves different kinds of purposes. 6 | * e.g. adding unique details to models, performing dynamic visual environmental changes or covering seams. 7 | * 8 | * Constructor parameter: 9 | * 10 | * mesh — Any mesh object 11 | * position — Position of the decal projector 12 | * orientation — Orientation of the decal projector 13 | * size — Size of the decal projector 14 | * 15 | * reference: http://blog.wolfire.com/2009/06/how-to-project-decals/ 16 | * 17 | */ 18 | 19 | ( function() { 20 | 21 | function DecalGeometry( mesh, position, orientation, size ) { 22 | 23 | THREE.BufferGeometry.call( this ); 24 | 25 | this.type = 'DecalGeometry'; 26 | 27 | // buffers 28 | 29 | var vertices = []; 30 | var normals = []; 31 | var uvs = []; 32 | 33 | // helpers 34 | 35 | var plane = new THREE.Vector3(); 36 | 37 | // this matrix represents the transformation of the decal projector 38 | 39 | var projectorMatrix = new THREE.Matrix4(); 40 | projectorMatrix.makeRotationFromEuler( orientation ); 41 | projectorMatrix.setPosition( position ); 42 | 43 | var projectorMatrixInverse = new THREE.Matrix4().getInverse( projectorMatrix ); 44 | 45 | // generate buffers 46 | 47 | generate(); 48 | 49 | // build geometry 50 | 51 | this.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); 52 | this.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) ); 53 | this.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); 54 | 55 | function generate() { 56 | 57 | var i, j; 58 | var geometry = new THREE.BufferGeometry(); 59 | var decalVertices = []; 60 | 61 | var vertex = new THREE.Vector3(); 62 | var normal = new THREE.Vector3(); 63 | 64 | // handle different geometry types 65 | 66 | if ( mesh.geometry.isGeometry ) { 67 | 68 | geometry.fromGeometry( mesh.geometry ); 69 | 70 | } else { 71 | 72 | geometry.copy( mesh.geometry ); 73 | 74 | } 75 | 76 | var positionAttribute = geometry.attributes.position; 77 | var normalAttribute = geometry.attributes.normal; 78 | 79 | // first, create an array of 'DecalVertex' objects 80 | // three consecutive 'DecalVertex' objects represent a single face 81 | // 82 | // this data structure will be later used to perform the clipping 83 | 84 | if ( geometry.index !== null ) { 85 | 86 | // indexed BufferGeometry 87 | 88 | var index = geometry.index; 89 | 90 | for ( i = 0; i < index.count; i ++ ) { 91 | 92 | vertex.fromBufferAttribute( positionAttribute, index.getX( i ) ); 93 | normal.fromBufferAttribute( normalAttribute, index.getX( i ) ); 94 | 95 | pushDecalVertex( decalVertices, vertex, normal ); 96 | 97 | } 98 | 99 | } else { 100 | 101 | // non-indexed BufferGeometry 102 | 103 | for ( i = 0; i < positionAttribute.count; i ++ ) { 104 | 105 | vertex.fromBufferAttribute( positionAttribute, i ); 106 | normal.fromBufferAttribute( normalAttribute, i ); 107 | 108 | pushDecalVertex( decalVertices, vertex, normal ); 109 | 110 | } 111 | 112 | } 113 | 114 | // second, clip the geometry so that it doesn't extend out from the projector 115 | 116 | decalVertices = clipGeometry( decalVertices, plane.set( 1, 0, 0 ) ); 117 | decalVertices = clipGeometry( decalVertices, plane.set( - 1, 0, 0 ) ); 118 | decalVertices = clipGeometry( decalVertices, plane.set( 0, 1, 0 ) ); 119 | decalVertices = clipGeometry( decalVertices, plane.set( 0, - 1, 0 ) ); 120 | decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, 1 ) ); 121 | decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, - 1 ) ); 122 | 123 | // third, generate final vertices, normals and uvs 124 | 125 | for ( i = 0; i < decalVertices.length; i ++ ) { 126 | 127 | var decalVertex = decalVertices[ i ]; 128 | 129 | // create texture coordinates (we are still in projector space) 130 | 131 | uvs.push( 132 | 0.5 + ( decalVertex.position.x / size.x ), 133 | 0.5 + ( decalVertex.position.y / size.y ) 134 | ); 135 | 136 | // transform the vertex back to world space 137 | 138 | decalVertex.position.applyMatrix4( projectorMatrix ); 139 | 140 | // now create vertex and normal buffer data 141 | 142 | vertices.push( decalVertex.position.x, decalVertex.position.y, decalVertex.position.z ); 143 | normals.push( decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z ); 144 | 145 | } 146 | 147 | } 148 | 149 | function pushDecalVertex( decalVertices, vertex, normal ) { 150 | 151 | // transform the vertex to world space, then to projector space 152 | 153 | vertex.applyMatrix4( mesh.matrix ); 154 | vertex.applyMatrix4( projectorMatrixInverse ); 155 | 156 | decalVertices.push( new DecalVertex( vertex.clone(), normal.clone() ) ); 157 | 158 | } 159 | 160 | function clipGeometry( inVertices, plane ) { 161 | 162 | var outVertices = []; 163 | 164 | var s = 0.5 * Math.abs( size.dot( plane ) ); 165 | 166 | // a single iteration clips one face, 167 | // which consists of three consecutive 'DecalVertex' objects 168 | 169 | for ( var i = 0; i < inVertices.length; i += 3 ) { 170 | 171 | var v1Out, v2Out, v3Out, total = 0; 172 | var nV1, nV2, nV3, nV4; 173 | 174 | var d1 = inVertices[ i + 0 ].position.dot( plane ) - s; 175 | var d2 = inVertices[ i + 1 ].position.dot( plane ) - s; 176 | var d3 = inVertices[ i + 2 ].position.dot( plane ) - s; 177 | 178 | v1Out = d1 > 0; 179 | v2Out = d2 > 0; 180 | v3Out = d3 > 0; 181 | 182 | // calculate, how many vertices of the face lie outside of the clipping plane 183 | 184 | total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 ); 185 | 186 | switch ( total ) { 187 | 188 | case 0: { 189 | 190 | // the entire face lies inside of the plane, no clipping needed 191 | 192 | outVertices.push( inVertices[ i ] ); 193 | outVertices.push( inVertices[ i + 1 ] ); 194 | outVertices.push( inVertices[ i + 2 ] ); 195 | break; 196 | 197 | } 198 | 199 | case 1: { 200 | 201 | // one vertex lies outside of the plane, perform clipping 202 | 203 | if ( v1Out ) { 204 | 205 | nV1 = inVertices[ i + 1 ]; 206 | nV2 = inVertices[ i + 2 ]; 207 | nV3 = clip( inVertices[ i ], nV1, plane, s ); 208 | nV4 = clip( inVertices[ i ], nV2, plane, s ); 209 | 210 | } 211 | 212 | if ( v2Out ) { 213 | 214 | nV1 = inVertices[ i ]; 215 | nV2 = inVertices[ i + 2 ]; 216 | nV3 = clip( inVertices[ i + 1 ], nV1, plane, s ); 217 | nV4 = clip( inVertices[ i + 1 ], nV2, plane, s ); 218 | 219 | outVertices.push( nV3 ); 220 | outVertices.push( nV2.clone() ); 221 | outVertices.push( nV1.clone() ); 222 | 223 | outVertices.push( nV2.clone() ); 224 | outVertices.push( nV3.clone() ); 225 | outVertices.push( nV4 ); 226 | break; 227 | 228 | } 229 | 230 | if ( v3Out ) { 231 | 232 | nV1 = inVertices[ i ]; 233 | nV2 = inVertices[ i + 1 ]; 234 | nV3 = clip( inVertices[ i + 2 ], nV1, plane, s ); 235 | nV4 = clip( inVertices[ i + 2 ], nV2, plane, s ); 236 | 237 | } 238 | 239 | outVertices.push( nV1.clone() ); 240 | outVertices.push( nV2.clone() ); 241 | outVertices.push( nV3 ); 242 | 243 | outVertices.push( nV4 ); 244 | outVertices.push( nV3.clone() ); 245 | outVertices.push( nV2.clone() ); 246 | 247 | break; 248 | 249 | } 250 | 251 | case 2: { 252 | 253 | // two vertices lies outside of the plane, perform clipping 254 | 255 | if ( ! v1Out ) { 256 | 257 | nV1 = inVertices[ i ].clone(); 258 | nV2 = clip( nV1, inVertices[ i + 1 ], plane, s ); 259 | nV3 = clip( nV1, inVertices[ i + 2 ], plane, s ); 260 | outVertices.push( nV1 ); 261 | outVertices.push( nV2 ); 262 | outVertices.push( nV3 ); 263 | 264 | } 265 | 266 | if ( ! v2Out ) { 267 | 268 | nV1 = inVertices[ i + 1 ].clone(); 269 | nV2 = clip( nV1, inVertices[ i + 2 ], plane, s ); 270 | nV3 = clip( nV1, inVertices[ i ], plane, s ); 271 | outVertices.push( nV1 ); 272 | outVertices.push( nV2 ); 273 | outVertices.push( nV3 ); 274 | 275 | } 276 | 277 | if ( ! v3Out ) { 278 | 279 | nV1 = inVertices[ i + 2 ].clone(); 280 | nV2 = clip( nV1, inVertices[ i ], plane, s ); 281 | nV3 = clip( nV1, inVertices[ i + 1 ], plane, s ); 282 | outVertices.push( nV1 ); 283 | outVertices.push( nV2 ); 284 | outVertices.push( nV3 ); 285 | 286 | } 287 | 288 | break; 289 | 290 | } 291 | 292 | case 3: { 293 | 294 | // the entire face lies outside of the plane, so let's discard the corresponding vertices 295 | 296 | break; 297 | 298 | } 299 | 300 | } 301 | 302 | } 303 | 304 | return outVertices; 305 | 306 | } 307 | 308 | function clip( v0, v1, p, s ) { 309 | 310 | var d0 = v0.position.dot( p ) - s; 311 | var d1 = v1.position.dot( p ) - s; 312 | 313 | var s0 = d0 / ( d0 - d1 ); 314 | 315 | var v = new DecalVertex( 316 | new THREE.Vector3( 317 | v0.position.x + s0 * ( v1.position.x - v0.position.x ), 318 | v0.position.y + s0 * ( v1.position.y - v0.position.y ), 319 | v0.position.z + s0 * ( v1.position.z - v0.position.z ) 320 | ), 321 | new THREE.Vector3( 322 | v0.normal.x + s0 * ( v1.normal.x - v0.normal.x ), 323 | v0.normal.y + s0 * ( v1.normal.y - v0.normal.y ), 324 | v0.normal.z + s0 * ( v1.normal.z - v0.normal.z ) 325 | ) 326 | ); 327 | 328 | // need to clip more values (texture coordinates)? do it this way: 329 | // intersectpoint.value = a.value + s * ( b.value - a.value ); 330 | 331 | return v; 332 | 333 | } 334 | 335 | } 336 | 337 | DecalGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); 338 | DecalGeometry.prototype.constructor = DecalGeometry; 339 | 340 | // helper 341 | 342 | function DecalVertex( position, normal ) { 343 | 344 | this.position = position; 345 | this.normal = normal; 346 | 347 | } 348 | 349 | DecalVertex.prototype.clone = function() { 350 | 351 | return new DecalVertex( this.position.clone(), this.normal.clone() ); 352 | 353 | }; 354 | 355 | // export 356 | 357 | THREE.DecalGeometry = DecalGeometry; 358 | 359 | } ) (); 360 | -------------------------------------------------------------------------------- /code/resources/lib/ArgonSunMoon.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | // here we are using pure Cesium and THREE functions. 4 | // should consider adding in SunCalc (https://github.com/mourner/suncalc) support, to get 5 | // some more information about sun/moon, such as time of day and phase of moon 6 | 7 | var Cesium = Argon.Cesium; 8 | var Cartesian3 = Cesium.Cartesian3; 9 | var Simon1994PlanetaryPositions = Cesium.Simon1994PlanetaryPositions; 10 | var JulianDate = Cesium.JulianDate; 11 | var CesiumMath = Cesium.CesiumMath; 12 | var Transforms = Cesium.Transforms; 13 | var ReferenceFrame = Cesium.ReferenceFrame; 14 | 15 | // Add function to argon to get the Sun and Moon entities, and to update them 16 | Argon.GetSunMoon = function () { 17 | var moonEntity = new Cesium.Entity({ 18 | name: "moon", 19 | position: Cartesian3.ZERO, 20 | orientation: Cesium.Quaternion.IDENTITY 21 | }); 22 | var sunEntity = new Cesium.Entity({ 23 | name: "sun", 24 | position: Cartesian3.ZERO, 25 | orientation: Cesium.Quaternion.IDENTITY 26 | }); 27 | 28 | return function () { 29 | return { moon: moonEntity, sun: sunEntity} 30 | }; 31 | }(); 32 | 33 | Argon.UpdateSunMoon = function() { 34 | var icrfToFixed = new Cesium.Matrix3(); 35 | var entities = Argon.GetSunMoon(); 36 | 37 | return function (date, frame) { 38 | if (!Cesium.defined(Transforms.computeIcrfToFixedMatrix(date, icrfToFixed))) { 39 | Transforms.computeTemeToPseudoFixedMatrix(date, icrfToFixed); 40 | } 41 | 42 | var retVal = { 43 | sun: new Cesium.Cartesian3(), 44 | moon: new Cesium.Cartesian3() 45 | } 46 | 47 | var translation = Simon1994PlanetaryPositions.computeMoonPositionInEarthInertialFrame(date, retVal.moon); 48 | Cesium.Matrix3.multiplyByVector(icrfToFixed, translation, translation); 49 | entities.moon.position.setValue(translation, ReferenceFrame.FIXED); 50 | if (frame != ReferenceFrame.FIXED) { 51 | translation = entities.moon.position.getValueInReferenceFrame(date, frame); 52 | if (translation) { 53 | entities.moon.position.setValue(translation, frame); 54 | translation.clone(retVal.moon); 55 | } else { 56 | retVal.moon.x = -0.1; 57 | retVal.moon.z = -0.1; 58 | retVal.moon.y = -1; 59 | } 60 | } 61 | 62 | translation = Simon1994PlanetaryPositions.computeSunPositionInEarthInertialFrame(date, retVal.sun); 63 | Cesium.Matrix3.multiplyByVector(icrfToFixed, translation, translation); 64 | entities.sun.position.setValue(translation, ReferenceFrame.FIXED); 65 | if (frame != ReferenceFrame.FIXED) { 66 | translation = entities.sun.position.getValueInReferenceFrame(date, frame); 67 | if (translation) { 68 | entities.sun.position.setValue(translation, frame); 69 | translation.clone(retVal.sun); 70 | } else { 71 | retVal.sun.x = 0.1; 72 | retVal.sun.z = 0.1; 73 | retVal.sun.y = 1; 74 | } 75 | } 76 | 77 | return retVal; 78 | } 79 | }(); 80 | 81 | if (typeof(THREE) !== 'undefined') { 82 | 83 | // if we're using THREE, let's create an object that we can use to retrieve 84 | // directional lights associated with the 85 | 86 | THREE.SunMoonLights = function () { 87 | // get the natural light entities, make them available 88 | this.entities = Argon.GetSunMoon(); 89 | 90 | // make the moon a dimmer, bluish light. Not really correct, but a start 91 | var moonlight = new THREE.DirectionalLight(0x9999aa, 0.25); 92 | var sunlight = new THREE.DirectionalLight(0xffffff, 1.0); 93 | this.moon = moonlight; 94 | this.sun = sunlight; 95 | 96 | // make the lights visible from outside 97 | lights = new THREE.Object3D(); 98 | this.lights = lights; 99 | 100 | var lastTime = null; 101 | this.update = function(date, frame) { 102 | if (!lastTime || JulianDate.secondsDifference(date,lastTime) > 1) { 103 | if (!lastTime) { 104 | lastTime = date.clone(); 105 | } 106 | else { 107 | date.clone(lastTime) 108 | } 109 | 110 | var positions = Argon.UpdateSunMoon(date, frame); 111 | 112 | var translation = positions.moon; 113 | Cartesian3.normalize(translation, translation); 114 | moonlight.position.set(translation.x, translation.y, translation.z); 115 | if (translation.y > 0) { 116 | lights.remove(moonlight); 117 | lights.add(moonlight); 118 | } else { 119 | lights.remove(moonlight); 120 | } 121 | 122 | translation = positions.sun; 123 | Cartesian3.normalize(translation, translation); 124 | sunlight.position.set(translation.x, translation.y, translation.z); 125 | if (translation.y > 0) { 126 | lights.remove(sunlight); 127 | lights.add(sunlight); 128 | } else { 129 | lights.remove(sunlight); 130 | } 131 | } 132 | } 133 | } 134 | } 135 | 136 | })(); -------------------------------------------------------------------------------- /code/resources/lib/CSS3DArgonHUD.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | * @author blairmacintyre / http://blairmacintyre.me/ 4 | */ 5 | 6 | THREE.CSS3DArgonHUD = function () { 7 | 8 | console.log( 'THREE.CSS3DArgonHUD', THREE.REVISION ); 9 | 10 | var _viewPortWidth = 0; 11 | var _viewPortHeight = 0; 12 | 13 | var _viewWidth = [1, 1]; 14 | var _viewHeight = [1, 1]; 15 | var _viewX = [0, 0]; 16 | var _viewY = [0, 0]; 17 | var _visible = [false, false]; 18 | 19 | var domElement = document.createElement( 'div' ); 20 | domElement.style.width = '0px'; 21 | domElement.style.height = '0px'; 22 | this.domElement = domElement; 23 | this.domElement.style.pointerEvents = 'none'; 24 | 25 | var hudElements = []; 26 | this.hudElements = hudElements; 27 | hudElements[0] = document.createElement( 'div' ); 28 | hudElements[0].style.display = 'none'; // start hidden 29 | hudElements[0].style.position = 'absolute'; 30 | hudElements[0].style.overflow = 'hidden'; 31 | hudElements[0].style.pointerEvents = 'none'; 32 | hudElements[0].style.bottom = '0px'; 33 | hudElements[0].style.left = '0px'; 34 | hudElements[0].style.width = '1px'; 35 | hudElements[0].style.height = '1px'; 36 | domElement.appendChild( hudElements[0] ); 37 | 38 | hudElements[1] = document.createElement( 'div' ); 39 | hudElements[1].style.display = 'none'; // start hidden 40 | hudElements[1].style.position = 'absolute'; 41 | hudElements[1].style.overflow = 'hidden'; 42 | hudElements[1].style.pointerEvents = 'none'; 43 | hudElements[1].style.bottom = '0px'; 44 | hudElements[1].style.left = '0px'; 45 | hudElements[1].style.width = '1px'; 46 | hudElements[1].style.height = '1px'; 47 | domElement.appendChild( hudElements[1] ); 48 | 49 | this.appendChild = function (element, element2) { 50 | if (!element2) { 51 | element2 = element.cloneNode( true ); 52 | } 53 | this.hudElements[0].appendChild(element); 54 | this.hudElements[1].appendChild(element2); 55 | } 56 | 57 | this.setViewport = function ( x, y, width, height, side ) { 58 | if (_viewX[side] != x) { 59 | hudElements[side].style.left = x + 'px'; 60 | _viewX[side] = x; 61 | } 62 | if (_viewY[side] != y) { 63 | hudElements[side].style.bottom = y + 'px'; 64 | _viewY[side] = y; 65 | } 66 | if (_viewWidth[side] != width) { 67 | hudElements[side].style.width = width + 'px'; 68 | _viewWidth[side] = width; 69 | } 70 | if (_viewHeight[side] != height) { 71 | hudElements[side].style.height = height + 'px'; 72 | _viewHeight[side] = height; 73 | } 74 | } 75 | 76 | this.showViewport = function (side) { 77 | if (!_visible[side]) { 78 | hudElements[side].style.display = 'inline-block'; 79 | _visible[side] = true; 80 | } 81 | } 82 | 83 | this.hideViewport = function (side) { 84 | if (_visible[side]) { 85 | hudElements[side].style.display = 'none'; 86 | _visible[side] = false; 87 | } 88 | } 89 | 90 | this.setSize = function ( width, height ) { 91 | // size of overall DOM 92 | if (_viewPortWidth != width) { 93 | domElement.style.width = width + 'px'; 94 | _viewPortWidth = width; 95 | } 96 | if (_viewPortHeight != height) { 97 | domElement.style.height = height + 'px'; 98 | _viewPortHeight = height; 99 | } 100 | /* 101 | * do not reset the subviews. 102 | */ 103 | // default viewports for left and right eyes. 104 | //hudElements[0].style.display = 'none'; 105 | //hudElements[1].style.display = 'none'; 106 | }; 107 | 108 | this.render = function ( side ) { 109 | if (!_visible[side]) { 110 | hudElements[side].style.display = 'inline-block'; 111 | _visible[side] = true; 112 | } 113 | 114 | // the only way I can think to actually hide the 115 | // second eye when not in stereo mode 116 | if (side == 0 && _viewPortWidth == _viewWidth[0]) { 117 | this.hideViewport(1); 118 | } 119 | }; 120 | }; -------------------------------------------------------------------------------- /code/resources/lib/stats.min.js: -------------------------------------------------------------------------------- 1 | // stats.js - http://github.com/mrdoob/stats.js 2 | var Stats=function(){function h(a){c.appendChild(a.dom);return a}function k(a){for(var d=0;de+1E3&&(r.update(1E3*a/(c-e),100),e=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){g=this.end()},domElement:c,setMode:k}}; 4 | Stats.Panel=function(h,k,l){var c=Infinity,g=0,e=Math.round,a=e(window.devicePixelRatio||1),r=80*a,f=48*a,t=3*a,u=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=f;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,f);b.fillStyle=k;b.fillText(h,t,u);b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(f, 5 | v){c=Math.min(c,f);g=Math.max(g,f);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=k;b.fillText(e(f)+" "+h+" ("+e(c)+"-"+e(g)+")",t,u);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,e((1-f/v)*p))}}};"object"===typeof module&&(module.exports=Stats); 6 | -------------------------------------------------------------------------------- /code/resources/lib/three/modifiers/ExplodeModifier.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Make all faces use unique vertices 3 | * so that each face can be separated from others 4 | * 5 | * @author alteredq / http://alteredqualia.com/ 6 | */ 7 | 8 | THREE.ExplodeModifier = function () { 9 | 10 | }; 11 | 12 | THREE.ExplodeModifier.prototype.modify = function ( geometry ) { 13 | 14 | var vertices = []; 15 | 16 | for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) { 17 | 18 | var n = vertices.length; 19 | 20 | var face = geometry.faces[ i ]; 21 | 22 | var a = face.a; 23 | var b = face.b; 24 | var c = face.c; 25 | 26 | var va = geometry.vertices[ a ]; 27 | var vb = geometry.vertices[ b ]; 28 | var vc = geometry.vertices[ c ]; 29 | 30 | vertices.push( va.clone() ); 31 | vertices.push( vb.clone() ); 32 | vertices.push( vc.clone() ); 33 | 34 | face.a = n; 35 | face.b = n + 1; 36 | face.c = n + 2; 37 | 38 | } 39 | 40 | geometry.vertices = vertices; 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /code/resources/lib/three/modifiers/TessellateModifier.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Break faces with edges longer than maxEdgeLength 3 | * - not recursive 4 | * 5 | * @author alteredq / http://alteredqualia.com/ 6 | */ 7 | 8 | THREE.TessellateModifier = function ( maxEdgeLength ) { 9 | 10 | this.maxEdgeLength = maxEdgeLength; 11 | 12 | }; 13 | 14 | THREE.TessellateModifier.prototype.modify = function ( geometry ) { 15 | 16 | var edge; 17 | 18 | var faces = []; 19 | var faceVertexUvs = []; 20 | var maxEdgeLengthSquared = this.maxEdgeLength * this.maxEdgeLength; 21 | 22 | for ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) { 23 | 24 | faceVertexUvs[ i ] = []; 25 | 26 | } 27 | 28 | for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) { 29 | 30 | var face = geometry.faces[ i ]; 31 | 32 | if ( face instanceof THREE.Face3 ) { 33 | 34 | var a = face.a; 35 | var b = face.b; 36 | var c = face.c; 37 | 38 | var va = geometry.vertices[ a ]; 39 | var vb = geometry.vertices[ b ]; 40 | var vc = geometry.vertices[ c ]; 41 | 42 | var dab = va.distanceToSquared( vb ); 43 | var dbc = vb.distanceToSquared( vc ); 44 | var dac = va.distanceToSquared( vc ); 45 | 46 | if ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) { 47 | 48 | var m = geometry.vertices.length; 49 | 50 | var triA = face.clone(); 51 | var triB = face.clone(); 52 | 53 | if ( dab >= dbc && dab >= dac ) { 54 | 55 | var vm = va.clone(); 56 | vm.lerp( vb, 0.5 ); 57 | 58 | triA.a = a; 59 | triA.b = m; 60 | triA.c = c; 61 | 62 | triB.a = m; 63 | triB.b = b; 64 | triB.c = c; 65 | 66 | if ( face.vertexNormals.length === 3 ) { 67 | 68 | var vnm = face.vertexNormals[ 0 ].clone(); 69 | vnm.lerp( face.vertexNormals[ 1 ], 0.5 ); 70 | 71 | triA.vertexNormals[ 1 ].copy( vnm ); 72 | triB.vertexNormals[ 0 ].copy( vnm ); 73 | 74 | } 75 | 76 | if ( face.vertexColors.length === 3 ) { 77 | 78 | var vcm = face.vertexColors[ 0 ].clone(); 79 | vcm.lerp( face.vertexColors[ 1 ], 0.5 ); 80 | 81 | triA.vertexColors[ 1 ].copy( vcm ); 82 | triB.vertexColors[ 0 ].copy( vcm ); 83 | 84 | } 85 | 86 | edge = 0; 87 | 88 | } else if ( dbc >= dab && dbc >= dac ) { 89 | 90 | var vm = vb.clone(); 91 | vm.lerp( vc, 0.5 ); 92 | 93 | triA.a = a; 94 | triA.b = b; 95 | triA.c = m; 96 | 97 | triB.a = m; 98 | triB.b = c; 99 | triB.c = a; 100 | 101 | if ( face.vertexNormals.length === 3 ) { 102 | 103 | var vnm = face.vertexNormals[ 1 ].clone(); 104 | vnm.lerp( face.vertexNormals[ 2 ], 0.5 ); 105 | 106 | triA.vertexNormals[ 2 ].copy( vnm ); 107 | 108 | triB.vertexNormals[ 0 ].copy( vnm ); 109 | triB.vertexNormals[ 1 ].copy( face.vertexNormals[ 2 ] ); 110 | triB.vertexNormals[ 2 ].copy( face.vertexNormals[ 0 ] ); 111 | 112 | } 113 | 114 | if ( face.vertexColors.length === 3 ) { 115 | 116 | var vcm = face.vertexColors[ 1 ].clone(); 117 | vcm.lerp( face.vertexColors[ 2 ], 0.5 ); 118 | 119 | triA.vertexColors[ 2 ].copy( vcm ); 120 | 121 | triB.vertexColors[ 0 ].copy( vcm ); 122 | triB.vertexColors[ 1 ].copy( face.vertexColors[ 2 ] ); 123 | triB.vertexColors[ 2 ].copy( face.vertexColors[ 0 ] ); 124 | 125 | } 126 | 127 | edge = 1; 128 | 129 | } else { 130 | 131 | var vm = va.clone(); 132 | vm.lerp( vc, 0.5 ); 133 | 134 | triA.a = a; 135 | triA.b = b; 136 | triA.c = m; 137 | 138 | triB.a = m; 139 | triB.b = b; 140 | triB.c = c; 141 | 142 | if ( face.vertexNormals.length === 3 ) { 143 | 144 | var vnm = face.vertexNormals[ 0 ].clone(); 145 | vnm.lerp( face.vertexNormals[ 2 ], 0.5 ); 146 | 147 | triA.vertexNormals[ 2 ].copy( vnm ); 148 | triB.vertexNormals[ 0 ].copy( vnm ); 149 | 150 | } 151 | 152 | if ( face.vertexColors.length === 3 ) { 153 | 154 | var vcm = face.vertexColors[ 0 ].clone(); 155 | vcm.lerp( face.vertexColors[ 2 ], 0.5 ); 156 | 157 | triA.vertexColors[ 2 ].copy( vcm ); 158 | triB.vertexColors[ 0 ].copy( vcm ); 159 | 160 | } 161 | 162 | edge = 2; 163 | 164 | } 165 | 166 | faces.push( triA, triB ); 167 | geometry.vertices.push( vm ); 168 | 169 | for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) { 170 | 171 | if ( geometry.faceVertexUvs[ j ].length ) { 172 | 173 | var uvs = geometry.faceVertexUvs[ j ][ i ]; 174 | 175 | var uvA = uvs[ 0 ]; 176 | var uvB = uvs[ 1 ]; 177 | var uvC = uvs[ 2 ]; 178 | 179 | // AB 180 | 181 | if ( edge === 0 ) { 182 | 183 | var uvM = uvA.clone(); 184 | uvM.lerp( uvB, 0.5 ); 185 | 186 | var uvsTriA = [ uvA.clone(), uvM.clone(), uvC.clone() ]; 187 | var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ]; 188 | 189 | // BC 190 | 191 | } else if ( edge === 1 ) { 192 | 193 | var uvM = uvB.clone(); 194 | uvM.lerp( uvC, 0.5 ); 195 | 196 | var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ]; 197 | var uvsTriB = [ uvM.clone(), uvC.clone(), uvA.clone() ]; 198 | 199 | // AC 200 | 201 | } else { 202 | 203 | var uvM = uvA.clone(); 204 | uvM.lerp( uvC, 0.5 ); 205 | 206 | var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ]; 207 | var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ]; 208 | 209 | } 210 | 211 | faceVertexUvs[ j ].push( uvsTriA, uvsTriB ); 212 | 213 | } 214 | 215 | } 216 | 217 | } else { 218 | 219 | faces.push( face ); 220 | 221 | for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) { 222 | 223 | faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] ); 224 | 225 | } 226 | 227 | } 228 | 229 | } 230 | 231 | } 232 | 233 | geometry.faces = faces; 234 | geometry.faceVertexUvs = faceVertexUvs; 235 | 236 | }; 237 | -------------------------------------------------------------------------------- /code/resources/lib/tween.min.js: -------------------------------------------------------------------------------- 1 | // tween.js - http://github.com/sole/tween.js 2 | 'use strict';var TWEEN=TWEEN||function(){var a=[];return{REVISION:"7",getAll:function(){return a},removeAll:function(){a=[]},add:function(c){a.push(c)},remove:function(c){c=a.indexOf(c);-1!==c&&a.splice(c,1)},update:function(c){if(0===a.length)return!1;for(var b=0,d=a.length,c=void 0!==c?c:Date.now();b(a*=2)?0.5*a*a:-0.5*(--a*(a-2)-1)}},Cubic:{In:function(a){return a*a*a},Out:function(a){return--a*a*a+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*a:0.5*((a-=2)*a*a+2)}},Quartic:{In:function(a){return a*a*a*a},Out:function(a){return 1- --a*a*a*a},InOut:function(a){return 1>(a*=2)?0.5*a*a*a*a:-0.5*((a-=2)*a*a*a-2)}},Quintic:{In:function(a){return a*a*a* 7 | a*a},Out:function(a){return--a*a*a*a*a+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*a*a*a:0.5*((a-=2)*a*a*a*a+2)}},Sinusoidal:{In:function(a){return 1-Math.cos(a*Math.PI/2)},Out:function(a){return Math.sin(a*Math.PI/2)},InOut:function(a){return 0.5*(1-Math.cos(Math.PI*a))}},Exponential:{In:function(a){return 0===a?0:Math.pow(1024,a-1)},Out:function(a){return 1===a?1:1-Math.pow(2,-10*a)},InOut:function(a){return 0===a?0:1===a?1:1>(a*=2)?0.5*Math.pow(1024,a-1):0.5*(-Math.pow(2,-10*(a-1))+2)}},Circular:{In:function(a){return 1- 8 | Math.sqrt(1-a*a)},Out:function(a){return Math.sqrt(1- --a*a)},InOut:function(a){return 1>(a*=2)?-0.5*(Math.sqrt(1-a*a)-1):0.5*(Math.sqrt(1-(a-=2)*a)+1)}},Elastic:{In:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return-(b*Math.pow(2,10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4))},Out:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return b*Math.pow(2,-10*a)*Math.sin((a-c)* 9 | 2*Math.PI/0.4)+1},InOut:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return 1>(a*=2)?-0.5*b*Math.pow(2,10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4):0.5*b*Math.pow(2,-10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4)+1}},Back:{In:function(a){return a*a*(2.70158*a-1.70158)},Out:function(a){return--a*a*(2.70158*a+1.70158)+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*(3.5949095*a-2.5949095):0.5*((a-=2)*a*(3.5949095*a+2.5949095)+2)}},Bounce:{In:function(a){return 1- 10 | TWEEN.Easing.Bounce.Out(1-a)},Out:function(a){return a<1/2.75?7.5625*a*a:a<2/2.75?7.5625*(a-=1.5/2.75)*a+0.75:a<2.5/2.75?7.5625*(a-=2.25/2.75)*a+0.9375:7.5625*(a-=2.625/2.75)*a+0.984375},InOut:function(a){return 0.5>a?0.5*TWEEN.Easing.Bounce.In(2*a):0.5*TWEEN.Easing.Bounce.Out(2*a-1)+0.5}}}; 11 | TWEEN.Interpolation={Linear:function(a,c){var b=a.length-1,d=b*c,e=Math.floor(d),f=TWEEN.Interpolation.Utils.Linear;return 0>c?f(a[0],a[1],d):1b?b:e+1],d-e)},Bezier:function(a,c){var b=0,d=a.length-1,e=Math.pow,f=TWEEN.Interpolation.Utils.Bernstein,h;for(h=0;h<=d;h++)b+=e(1-c,d-h)*e(c,h)*a[h]*f(d,h);return b},CatmullRom:function(a,c){var b=a.length-1,d=b*c,e=Math.floor(d),f=TWEEN.Interpolation.Utils.CatmullRom;return a[0]===a[b]?(0>c&&(e=Math.floor(d=b*(1+c))),f(a[(e- 12 | 1+b)%b],a[e],a[(e+1)%b],a[(e+2)%b],d-e)):0>c?a[0]-(f(a[0],a[0],a[1],a[1],-d)-a[0]):1 2 | SetOutputFilter DEFLATE 3 | 4 | 5 | 6 | SetOutputFilter DEFLATE 7 | 8 | -------------------------------------------------------------------------------- /code/resources/obj/leeperrysmith/Infinite-Level_02_Disp_NoSmoothUV-4096.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/obj/leeperrysmith/Infinite-Level_02_Disp_NoSmoothUV-4096.jpg -------------------------------------------------------------------------------- /code/resources/obj/leeperrysmith/Infinite-Level_02_Tangent_SmoothUV.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/obj/leeperrysmith/Infinite-Level_02_Tangent_SmoothUV.jpg -------------------------------------------------------------------------------- /code/resources/obj/leeperrysmith/LeePerrySmith_License.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Licence 2 | Infinite, 3D Head Scan by Lee Perry-Smith is licensed under a Creative Commons Attribution 3.0 Unported License. 3 | Based on a work at www.triplegangers.com. 4 | Permissions beyond the scope of this license may be available at http://www.ir-ltd.net/ 5 | Please remember: Do what you want with the files, but always mention where you got them from... 6 | -------------------------------------------------------------------------------- /code/resources/obj/leeperrysmith/Map-COL.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/obj/leeperrysmith/Map-COL.jpg -------------------------------------------------------------------------------- /code/resources/obj/leeperrysmith/Map-SPEC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/obj/leeperrysmith/Map-SPEC.jpg -------------------------------------------------------------------------------- /code/resources/textures/decal/LICENSE.TXT: -------------------------------------------------------------------------------- 1 | decal-diffuse.png 2 | decal-normal.jpg 3 | 4 | Licensed under a CC0 1.0 Universal (CC0 1.0) Public Domain Dedication License: 5 | http://creativecommons.org/publicdomain/zero/1.0/ -------------------------------------------------------------------------------- /code/resources/textures/decal/decal-diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/textures/decal/decal-diffuse.png -------------------------------------------------------------------------------- /code/resources/textures/decal/decal-normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/argonjs/samples/6da45a3cc05a9fcc8c16634afceb535b1b7aace8/code/resources/textures/decal/decal-normal.jpg -------------------------------------------------------------------------------- /code/streetview-reality/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | Google Street View 15 | 16 | 17 | 18 | 27 | 28 | -------------------------------------------------------------------------------- /code/streetview-reality/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /code/streetview/app.js: -------------------------------------------------------------------------------- 1 | /// 2 | // set up Argon 3 | var app = Argon.init(); 4 | // set our desired reality 5 | app.reality.request( 6 | Argon.resolveURL('../streetview-reality/index.html') 7 | ); 8 | -------------------------------------------------------------------------------- /code/streetview/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Streetview 6 | 7 | 8 | 9 | 10 | 11 | 67 | 68 | 69 |
70 |
71 |
72 |

Requesting a Custom Reality (Streetview)

73 |
(tap to dismiss)
74 |

This example demonstrates the use of custom reality views, a feature which enables multiple apps to together augment a custom view of reality. In this case, the app requests a streetview reality which finds the nearest panoramic imagery to the user's current location.

75 |
76 |
77 | 82 |
83 | 84 | 85 | 94 | -------------------------------------------------------------------------------- /code/streetview/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /code/tango/app.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | // set up Argon 5 | var app = Argon.init(null, { 'sharedCanvas': true }, null); 6 | // this app uses geoposed content, so subscribe to geolocation updates 7 | app.context.subscribeGeolocation(); 8 | // set up THREE. Create a scene, a perspective camera and an object 9 | // for the user's location 10 | var scene = new THREE.Scene(); 11 | var camera = new THREE.PerspectiveCamera(); 12 | var stage = new THREE.Object3D; 13 | scene.add(camera); 14 | scene.add(stage); 15 | // We use the standard WebGLRenderer when we only need WebGL-based content 16 | var renderer = new THREE.WebGLRenderer({ 17 | alpha: true, 18 | logarithmicDepthBuffer: true, 19 | antialias: Argon.suggestedWebGLContextAntialiasAttribute 20 | }); 21 | renderer.autoClear = false; 22 | var hud = new THREE.CSS3DArgonHUD(); 23 | // We also move the description box to the left Argon HUD. 24 | // We don't duplicated it because we only use it in mono mode 25 | var holder = document.createElement('div'); 26 | var hudDescription = document.getElementById('description'); 27 | var hudButtons = document.getElementById('hud'); 28 | holder.appendChild(hudDescription); 29 | holder.appendChild(hudButtons); 30 | hud.hudElements[0].appendChild(holder); 31 | // add a performance stats thing to the display 32 | var stats = new Stats(); 33 | hud.hudElements[0].appendChild(stats.dom); 34 | // app.view.element.appendChild(hud.domElement); 35 | // set the layers of our view 36 | app.view.setLayers([ 37 | { source: renderer.domElement }, 38 | { source: hud.domElement } 39 | ]); 40 | // add some ambient so things aren't so harshly illuminated 41 | var ambientlight = new THREE.AmbientLight(0x909090); // soft white ambient light 42 | scene.add(ambientlight); 43 | // create 6 3D words for the 6 directions. 44 | var loader = new THREE.FontLoader(); 45 | loader.load('../resources/fonts/helvetiker_regular.typeface.json', function (font) { 46 | var textOptions = { 47 | font: font, 48 | size: 0.15, 49 | height: 0.1, 50 | curveSegments: 5, 51 | bevelThickness: 0.01, 52 | bevelSize: 0.01, 53 | bevelEnabled: true 54 | }; 55 | var textMaterial = new THREE.MeshStandardMaterial({ 56 | color: 0x5588ff 57 | }); 58 | function createDirectionLabel(text, position, rotation) { 59 | var textGeometry = new THREE.TextGeometry(text, textOptions); 60 | textGeometry.center(); 61 | var textMesh = new THREE.Mesh(textGeometry, textMaterial); 62 | if (position.x) 63 | textMesh.position.x = position.x; 64 | if (position.y) 65 | textMesh.position.y = position.y; 66 | if (position.z) 67 | textMesh.position.z = position.z; 68 | if (rotation.x) 69 | textMesh.rotation.x = rotation.x; 70 | if (rotation.y) 71 | textMesh.rotation.y = rotation.y; 72 | if (rotation.z) 73 | textMesh.rotation.z = rotation.z; 74 | stage.add(textMesh); 75 | } 76 | createDirectionLabel("North", { z: -1 }, {}); 77 | createDirectionLabel("South", { z: 1 }, { y: Math.PI }); 78 | createDirectionLabel("East", { x: 1 }, { y: -Math.PI / 2 }); 79 | createDirectionLabel("West", { x: -1 }, { y: Math.PI / 2 }); 80 | createDirectionLabel("Up", { y: 1 }, { x: Math.PI / 2 }); 81 | createDirectionLabel("Down", { y: -1 }, { x: -Math.PI / 2 }); 82 | }); 83 | // the updateEvent is called each time the 3D world should be 84 | // rendered, before the renderEvent. The state of your application 85 | // should be updated here. 86 | app.updateEvent.addEventListener(function () { 87 | // get the position and orientation of the "stage", 88 | // to anchor our content. The "stage" defines an East-Up-South 89 | // coordinate system (assuming geolocation is available). 90 | var stagePose = app.context.getEntityPose(app.context.stage); 91 | // assuming we know the user's pose, set the position of our 92 | // THREE user object to match it 93 | if (stagePose.poseStatus & Argon.PoseStatus.KNOWN) { 94 | stage.position.copy(stagePose.position); 95 | stage.quaternion.copy(stagePose.orientation); 96 | } 97 | }); 98 | // renderEvent is fired whenever argon wants the app to update its display 99 | app.renderEvent.addEventListener(function () { 100 | if (app.reality.isSharedCanvas) { 101 | // if this is a shared canvas we can't depend on our GL state 102 | // being exactly how we left it last frame 103 | renderer.resetGLState(); 104 | } 105 | else { 106 | // not a shared canvas, we need to clear it before rendering 107 | renderer.clear(); 108 | } 109 | // set the renderer to know the current size of the viewport. 110 | // This is the full size of the viewport, which would include 111 | // both views if we are in stereo viewing mode 112 | var view = app.view; 113 | renderer.setSize(view.renderWidth, view.renderHeight, false); 114 | renderer.setPixelRatio(app.suggestedPixelRatio); 115 | var viewport = view.viewport; 116 | hud.setSize(viewport.width, viewport.height); 117 | // There is 1 subview in monocular mode, 2 in stereo mode. 118 | // If we are in mono view, show the description. If not, hide it, 119 | if (app.view.subviews.length > 1) { 120 | holder.style.display = 'none'; 121 | } 122 | else { 123 | holder.style.display = 'block'; 124 | } 125 | // there is 1 subview in monocular mode, 2 in stereo mode 126 | for (var _i = 0, _a = app.view.subviews; _i < _a.length; _i++) { 127 | var subview = _a[_i]; 128 | // set the position and orientation of the camera for 129 | // this subview 130 | camera.position.copy(subview.pose.position); 131 | camera.quaternion.copy(subview.pose.orientation); 132 | // the underlying system provide a full projection matrix 133 | // for the camera. 134 | camera.projectionMatrix.fromArray(subview.frustum.projectionMatrix); 135 | // set the viewport for this view 136 | var _b = subview.renderViewport, x = _b.x, y = _b.y, width = _b.width, height = _b.height; 137 | renderer.setViewport(x, y, width, height); 138 | // set the webGL rendering parameters and render this view 139 | renderer.setScissor(x, y, width, height); 140 | renderer.setScissorTest(true); 141 | renderer.render(scene, camera); 142 | // adjust the hud 143 | var _c = subview.viewport, x = _c.x, y = _c.y, width = _c.width, height = _c.height; 144 | hud.setViewport(x, y, width, height, subview.index); 145 | hud.render(subview.index); 146 | } 147 | stats.update(); 148 | }); 149 | // Tango functionailities 150 | // -------------------------- 151 | var tangoRealitySession; 152 | app.reality.connectEvent.addEventListener(function (session) { 153 | // check if the connected supports our protocol 154 | if (session.supportsProtocol('ar.tango')) { 155 | // save a reference to this session so our buttons can send messages 156 | tangoRealitySession = session; 157 | document.getElementById('menu').style.visibility = 'visible'; 158 | var cloudBtn_1 = document.getElementById('pointcloud-btn'); 159 | var placeBtn = document.getElementById('placeobject-btn'); 160 | var occlusionBtn_1 = document.getElementById('occlusion-btn'); 161 | // Toggle point cloud vision on/off 162 | cloudBtn_1.addEventListener('click', function () { 163 | if (tangoRealitySession) { 164 | tangoRealitySession.request('ar.tango.togglePointCloud') 165 | .then(function (_a) { 166 | var isOn = _a.result; 167 | cloudBtn_1.textContent = "PointCloud: " + (isOn ? 'ON' : 'OFF'); 168 | }); 169 | } 170 | }); 171 | // Place an object at the surface located on the center of the screen. 172 | placeBtn.addEventListener('click', function () { 173 | if (tangoRealitySession) { 174 | placeObject({ x: 0.5, y: 0.5 }); 175 | } 176 | }); 177 | occlusionBtn_1.addEventListener('click', function () { 178 | if (tangoRealitySession) { 179 | tangoRealitySession.request('ar.tango.toggleOcclusion') 180 | .then(function (_a) { 181 | var isOn = _a.result; 182 | occlusionBtn_1.textContent = "Occlusion: " + (isOn ? 'ON' : 'OFF'); 183 | }); 184 | } 185 | }); 186 | } 187 | }); 188 | // Create a cube model of 10 cm size. 189 | var MODEL_SIZE_IN_METERS = 0.1; 190 | var model = new THREE.Mesh(new THREE.ConeBufferGeometry(MODEL_SIZE_IN_METERS / 2, MODEL_SIZE_IN_METERS), new THREE.MeshLambertMaterial({ color: 0x888888 })); 191 | // Apply a rotation to the model so it faces in the direction of the 192 | // normal of the plane when the picking based reorientation is done 193 | model.geometry.applyMatrix(new THREE.Matrix4().makeRotationZ(THREE.Math.degToRad(-90))); 194 | // Set a default position (10 meters above the user) 195 | model.position.set(0, 10, 0); 196 | scene.add(model); 197 | function placeObject(pos2D) { 198 | if (tangoRealitySession) { 199 | tangoRealitySession.request('ar.tango.getPickingPointAndPlaneInPointCloud', { x: pos2D.x, y: pos2D.y }) 200 | .then(function (_a) { 201 | var point = _a.point, plane = _a.plane; 202 | if (point && plane) { 203 | var pointAndPlane = { point: ObjToFloatArray(point, 3), plane: ObjToFloatArray(plane, 4) }; 204 | THREE.WebAR.positionAndRotateObject3DWithPickingPointAndPlaneInPointCloud(pointAndPlane, model, MODEL_SIZE_IN_METERS / 2); 205 | } 206 | else { 207 | console.warn("Point could not be specified in the point cloud."); 208 | } 209 | }); 210 | } 211 | else { 212 | console.warn("Reality not connect. Try again in a moment."); 213 | } 214 | } 215 | function ObjToFloatArray(obj, len) { 216 | var arr = new Float32Array(len); 217 | for (var i = 0; i < len; i++) { 218 | arr[i] = obj[i]; 219 | } 220 | return arr; 221 | } 222 | -------------------------------------------------------------------------------- /code/tango/app.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // set up Argon 6 | const app = Argon.init(null, {'sharedCanvas': true}, null); 7 | 8 | // this app uses geoposed content, so subscribe to geolocation updates 9 | app.context.subscribeGeolocation(); 10 | 11 | // set up THREE. Create a scene, a perspective camera and an object 12 | // for the user's location 13 | const scene = new THREE.Scene(); 14 | const camera = new THREE.PerspectiveCamera(); 15 | const stage = new THREE.Object3D; 16 | scene.add(camera); 17 | scene.add(stage); 18 | 19 | // We use the standard WebGLRenderer when we only need WebGL-based content 20 | const renderer = new THREE.WebGLRenderer({ 21 | alpha: true, 22 | logarithmicDepthBuffer: true, 23 | antialias: Argon.suggestedWebGLContextAntialiasAttribute 24 | }); 25 | 26 | renderer.autoClear = false; 27 | 28 | const hud = new (THREE).CSS3DArgonHUD(); 29 | 30 | // We also move the description box to the left Argon HUD. 31 | // We don't duplicated it because we only use it in mono mode 32 | var holder = document.createElement( 'div' ); 33 | var hudDescription = document.getElementById( 'description' ); 34 | var hudButtons = document.getElementById( 'hud' ); 35 | holder.appendChild(hudDescription); 36 | holder.appendChild(hudButtons); 37 | hud.hudElements[0].appendChild(holder); 38 | 39 | // add a performance stats thing to the display 40 | var stats = new Stats(); 41 | hud.hudElements[0].appendChild(stats.dom); 42 | // app.view.element.appendChild(hud.domElement); 43 | 44 | // set the layers of our view 45 | app.view.setLayers([ 46 | { source: renderer.domElement }, 47 | { source: hud.domElement } 48 | ]); 49 | 50 | // add some ambient so things aren't so harshly illuminated 51 | var ambientlight = new THREE.AmbientLight( 0x909090 ); // soft white ambient light 52 | scene.add(ambientlight); 53 | 54 | // create 6 3D words for the 6 directions. 55 | var loader = new THREE.FontLoader(); 56 | loader.load( '../resources/fonts/helvetiker_regular.typeface.json', function ( font ) { 57 | const textOptions = { 58 | font:font, 59 | size: 0.15, 60 | height: 0.1, 61 | curveSegments: 5, 62 | bevelThickness: 0.01, 63 | bevelSize: 0.01, 64 | bevelEnabled: true 65 | } 66 | 67 | var textMaterial = new THREE.MeshStandardMaterial({ 68 | color: 0x5588ff 69 | }) 70 | 71 | function createDirectionLabel(text, position, rotation) { 72 | var textGeometry = new THREE.TextGeometry(text, textOptions); 73 | textGeometry.center(); 74 | var textMesh = new THREE.Mesh(textGeometry, textMaterial); 75 | if (position.x) textMesh.position.x = position.x; 76 | if (position.y) textMesh.position.y = position.y; 77 | if (position.z) textMesh.position.z = position.z; 78 | if (rotation.x) textMesh.rotation.x = rotation.x; 79 | if (rotation.y) textMesh.rotation.y = rotation.y; 80 | if (rotation.z) textMesh.rotation.z = rotation.z; 81 | stage.add(textMesh); 82 | } 83 | 84 | createDirectionLabel("North", {z:-1}, {}); 85 | createDirectionLabel("South", {z:1}, {y:Math.PI}); 86 | createDirectionLabel("East", {x:1}, {y:-Math.PI/2}); 87 | createDirectionLabel("West", {x:-1}, {y:Math.PI/2}); 88 | createDirectionLabel("Up", {y:1}, {x:Math.PI/2}); 89 | createDirectionLabel("Down", {y:-1}, {x:-Math.PI/2}); 90 | }) 91 | 92 | 93 | // the updateEvent is called each time the 3D world should be 94 | // rendered, before the renderEvent. The state of your application 95 | // should be updated here. 96 | app.updateEvent.addEventListener(() => { 97 | // get the position and orientation of the "stage", 98 | // to anchor our content. The "stage" defines an East-Up-South 99 | // coordinate system (assuming geolocation is available). 100 | const stagePose = app.context.getEntityPose(app.context.stage); 101 | 102 | // assuming we know the user's pose, set the position of our 103 | // THREE user object to match it 104 | if (stagePose.poseStatus & Argon.PoseStatus.KNOWN) { 105 | stage.position.copy(stagePose.position); 106 | stage.quaternion.copy(stagePose.orientation); 107 | } 108 | }) 109 | 110 | // renderEvent is fired whenever argon wants the app to update its display 111 | app.renderEvent.addEventListener(() => { 112 | 113 | if (app.reality.isSharedCanvas) { 114 | // if this is a shared canvas we can't depend on our GL state 115 | // being exactly how we left it last frame 116 | renderer.resetGLState(); 117 | } else { 118 | // not a shared canvas, we need to clear it before rendering 119 | renderer.clear(); 120 | } 121 | 122 | // set the renderer to know the current size of the viewport. 123 | // This is the full size of the viewport, which would include 124 | // both views if we are in stereo viewing mode 125 | const view = app.view; 126 | renderer.setSize(view.renderWidth, view.renderHeight, false); 127 | renderer.setPixelRatio(app.suggestedPixelRatio); 128 | 129 | const viewport = view.viewport; 130 | hud.setSize(viewport.width, viewport.height); 131 | 132 | // There is 1 subview in monocular mode, 2 in stereo mode. 133 | // If we are in mono view, show the description. If not, hide it, 134 | if (app.view.subviews.length > 1) { 135 | holder.style.display = 'none'; 136 | } else { 137 | holder.style.display = 'block'; 138 | } 139 | 140 | // there is 1 subview in monocular mode, 2 in stereo mode 141 | for (let subview of app.view.subviews) { 142 | // set the position and orientation of the camera for 143 | // this subview 144 | camera.position.copy(subview.pose.position); 145 | camera.quaternion.copy(subview.pose.orientation); 146 | // the underlying system provide a full projection matrix 147 | // for the camera. 148 | camera.projectionMatrix.fromArray(subview.frustum.projectionMatrix); 149 | 150 | // set the viewport for this view 151 | var {x,y,width,height} = subview.renderViewport; 152 | renderer.setViewport(x,y,width,height); 153 | 154 | // set the webGL rendering parameters and render this view 155 | renderer.setScissor(x,y,width,height); 156 | renderer.setScissorTest(true); 157 | renderer.render(scene, camera); 158 | 159 | // adjust the hud 160 | var {x,y,width,height} = subview.viewport; 161 | hud.setViewport(x,y,width,height, subview.index); 162 | hud.render(subview.index); 163 | } 164 | stats.update(); 165 | }) 166 | 167 | // Tango functionailities 168 | // -------------------------- 169 | var tangoRealitySession; 170 | 171 | app.reality.connectEvent.addEventListener((session)=>{ 172 | // check if the connected supports our protocol 173 | if (session.supportsProtocol('ar.tango')) { 174 | // save a reference to this session so our buttons can send messages 175 | tangoRealitySession = session; 176 | document.getElementById('menu').style.visibility = 'visible'; 177 | let cloudBtn = document.getElementById('pointcloud-btn'); 178 | let placeBtn = document.getElementById('placeobject-btn'); 179 | let occlusionBtn = document.getElementById('occlusion-btn'); 180 | 181 | // Toggle point cloud vision on/off 182 | cloudBtn.addEventListener('click', ()=>{ 183 | if (tangoRealitySession) { 184 | tangoRealitySession.request('ar.tango.togglePointCloud') 185 | .then(({result: isOn})=>{ 186 | cloudBtn.textContent = "PointCloud: " + (isOn? 'ON' : 'OFF'); 187 | }); 188 | } 189 | }); 190 | 191 | // Place an object at the surface located on the center of the screen. 192 | placeBtn.addEventListener('click', ()=>{ 193 | if (tangoRealitySession) { 194 | placeObject({x: 0.5, y: 0.5}); 195 | } 196 | }); 197 | 198 | occlusionBtn.addEventListener('click', ()=>{ 199 | if (tangoRealitySession) { 200 | tangoRealitySession.request('ar.tango.toggleOcclusion') 201 | .then(({result: isOn})=>{ 202 | occlusionBtn.textContent = "Occlusion: " + (isOn? 'ON' : 'OFF'); 203 | }); 204 | } 205 | }); 206 | } 207 | }) 208 | 209 | // Create a cube model of 10 cm size. 210 | var MODEL_SIZE_IN_METERS = 0.1; 211 | var model = new THREE.Mesh(new THREE.ConeBufferGeometry( 212 | MODEL_SIZE_IN_METERS / 2, MODEL_SIZE_IN_METERS), 213 | new THREE.MeshLambertMaterial({ color: 0x888888 })); 214 | // Apply a rotation to the model so it faces in the direction of the 215 | // normal of the plane when the picking based reorientation is done 216 | model.geometry.applyMatrix( 217 | new THREE.Matrix4().makeRotationZ(THREE.Math.degToRad(-90))); 218 | // Set a default position (10 meters above the user) 219 | model.position.set(0, 10, 0); 220 | scene.add(model); 221 | 222 | function placeObject(pos2D: {x: number, y: number}) { 223 | if (tangoRealitySession) { 224 | tangoRealitySession.request('ar.tango.getPickingPointAndPlaneInPointCloud', {x: pos2D.x, y: pos2D.y}) 225 | .then(({point, plane}) => { 226 | if (point && plane) { 227 | let pointAndPlane = {point: ObjToFloatArray(point, 3), plane: ObjToFloatArray(plane, 4)}; 228 | (THREE).WebAR.positionAndRotateObject3DWithPickingPointAndPlaneInPointCloud( 229 | pointAndPlane, model, MODEL_SIZE_IN_METERS / 2); 230 | } else { 231 | console.warn("Point could not be specified in the point cloud.") 232 | } 233 | }); 234 | } else { 235 | console.warn("Reality not connect. Try again in a moment."); 236 | } 237 | } 238 | 239 | function ObjToFloatArray(obj: Object, len: number): Float32Array { 240 | let arr: Float32Array = new Float32Array(len); 241 | for (let i = 0; i 4 | 5 | Tango demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 59 | 60 | 61 |
62 |
63 | 68 |
69 |
70 |
71 |

Tango demo

72 |
(click to dismiss)
73 |

This example extends the directions example to show how to use the Tango protocols that are supported in the Chromium WebAR browser. 74 | Supporting functionalities have been adapted from the Chromium WebAR browser examples.

75 |
76 |
77 |
78 | 79 | 84 | 85 | 94 | -------------------------------------------------------------------------------- /code/tango/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "es2015" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /code/vuforia-jsartoolkit/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Vuforia-JSARToolKit 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 41 | 42 | 43 |
44 |
45 |

Vuforia-JSARToolKit Demo

46 |
(click to dismiss)
47 |

This example puts a dynamic 3D model of the text "argon.js" on the cover of the GVU Brochure (if Vuforia is available) or the ARToolKit Hiro marker (if WebRTC is available). When the marker is not seen, the text appears directly north.

48 |
49 |
50 | 51 | 56 | 57 | 66 | -------------------------------------------------------------------------------- /code/vuforia-jsartoolkit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "lib": [ 5 | "dom", 6 | "es2015" 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /code/vuforia/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Vuforia 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 41 | 42 | 43 |
44 |
45 |

Vuforia Demo

46 |
(click to dismiss)
47 |

This example puts a dynamic 3D model of the text "argon.js" on the cover of the GVU Brochure. When the target is not seen, the text appears directly north.

48 |

A second dataset with the Vuforia stones and chips targets is also loaded and activated. Up to two targets can be tracked simultaneously.

49 |
50 |
51 | 52 | 57 | 58 | 67 | -------------------------------------------------------------------------------- /code/vuforia/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "lib": [ 5 | "dom", 6 | "es2015" 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /code/vuforiaDecals/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 5 | Vuforia Decals 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 47 | 48 | 49 |
50 |
51 |
52 |

Vuforia Three.js Decal Demo

53 |
(click to dismiss)
54 |

This example repurposes the WebGL Decals demo from three.js and places the model on the cover of the GVU Brochure.

55 |
56 |
57 | 58 | 64 | 65 | 74 | -------------------------------------------------------------------------------- /code/vuforiaDecals/original-decals-example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WebGL decals 5 | 6 | 7 | 18 | 19 | 20 | 21 |
22 |
23 | Decal Splatter
24 | Click or tap to shoot.

25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 350 | 351 | 352 | 353 | -------------------------------------------------------------------------------- /code/vuforiaDecals/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "lib": [ 5 | "dom", 6 | "es2015" 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@argonjs/argon": "^1.4.0-36", 4 | "@types/dat-gui": "^0.5.28", 5 | "@types/googlemaps": "^3.20.30", 6 | "@types/stats": "^0.16.29", 7 | "@types/three": "^0.83.5", 8 | "@types/tween.js": "0.0.27", 9 | "express": "^4.15.2", 10 | "pem": "^1.9.4", 11 | "typescript": "^2.1.4" 12 | }, 13 | "scripts": { 14 | "serve": "npm start", 15 | "devsite": "jekyll build --config _config-develop.yml", 16 | "build": "tsc -p code/geopose && tsc -p code/vuforia && tsc -p code/directionsHTML && tsc -p code/directionsWebGL && tsc -p code/panorama-reality && tsc -p code/panoramas && tsc -p code/vuforia && tsc -p code/vuforiaDecals && tsc -p code/streetview-reality && tsc -p code/jsartoolkit && tsc -p code/vuforia-jsartoolkit && tsc -p code/tango", 17 | "distsite": "jekyll build --config _config-master.yml" 18 | }, 19 | "dependencies": { 20 | "@argonjs/argon": "^1.4.0-0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var http = require('http'); 3 | var https = require('https'); 4 | var pem = require('pem'); 5 | 6 | const httpPort = process.env.PORT||1337; 7 | 8 | pem.createCertificate({ days:1, selfSigned:true }, function(err, keys) { 9 | // Create middleware for a static server 10 | var app = express(); 11 | // app.all('*', (req, res, next) => { 12 | // // always redirect to https 13 | // if (req.secure) return next(); 14 | // res.redirect('https://' + req.hostname + ':' + httpsServer.address().port + req.url); 15 | // }); 16 | app.use(express.static('_site/.')); 17 | 18 | // Create an HTTPS service 19 | var httpsServer = https.createServer({ 20 | key: keys.serviceKey, 21 | cert: keys.certificate 22 | }, app).listen(0); 23 | 24 | // Create an http service 25 | http.createServer(app).listen(httpPort); 26 | 27 | console.log(`serving on http://localhost:${httpPort}`); 28 | }); --------------------------------------------------------------------------------