150行JavaScript代码实现增强现实

增强现实技术(Augmented Reality,简称 AR),是一种实时地计算摄影机影像的位置及角度并加上相应图像、视频、3D模型的技术,这种技术的目标是在屏幕上把虚拟世界套在现实世界并进行互动。这种技术1990年提出。随着随身电子产品CPU运算能力的提升,预期增强现实的用途将会越来越广。

本文介绍使用JavaScript开源框架AR.js实现的增强现实的Hello World例子。

先看效果:

首先在手机浏览器里打开我部署在github page上的这个demo应用:

https://i042416.github.io/FioriODataTestTool2014/WebContent/098_ar.html

我用的是Android手机安装的Chrome浏览器。

打开网页,会提示你是否允许这个网页应用访问您的手机摄像头。点击允许:

用手机上的摄像头扫描这张图片:

神奇的事情就发生了。您会看到,通过手机摄像头望过去,手机屏幕里会出现一个新的不断滚动的3D物体,如下图所示。

下面具体介绍这个最简单的例子是怎么开发出来的。

所有的源代码在我的github上:

https://github.com/i042416/FioriODataTestTool2014/tree/master/WebContent/ar

新建一个html文件,把下列150行代码粘贴进去,然后在服务器上运行,使用之前描述的步骤即可进行AR测试:

<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">

<script src=‘ar/lib/three.min.js‘></script>
<script src="ar/lib/stats.min.js"></script>
<script src="ar/lib/ar.js"></script>

<script>
debugger;
 THREEx.ArToolkitContext.baseURL = ‘‘;
</script>
<body style=‘margin : 0px; overflow: hidden; font-family: Monospace;‘>
<div style=‘position: absolute; top: 10px; width:100%; text-align: center; z-index: 1;‘>

<script>

    var renderer    = new THREE.WebGLRenderer({
        // antialias    : true,
        alpha: true
    });
    renderer.setClearColor(new THREE.Color(‘lightgrey‘), 0)
    // renderer.setPixelRatio( 1/2 );
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.domElement.style.position = ‘absolute‘
    renderer.domElement.style.top = ‘0px‘
    renderer.domElement.style.left = ‘0px‘
    document.body.appendChild( renderer.domElement );

    // array of functions for the rendering loop
    var onRenderFcts= [];

    // init scene and camera
    var scene   = new THREE.Scene();

    var camera = new THREE.Camera();
    scene.add(camera);

    var arToolkitSource = new THREEx.ArToolkitSource({
        // to read from the webcam
        sourceType : ‘webcam‘,

        // to read from an image
        // sourceType : ‘image‘,
        // sourceUrl : THREEx.ArToolkitContext.baseURL + ‘../data/images/img.jpg‘,      

        // to read from a video
        // sourceType : ‘video‘,
        // sourceUrl : THREEx.ArToolkitContext.baseURL + ‘../data/videos/headtracking.mp4‘,
    })

    arToolkitSource.init(function onReady(){
        onResize()
    })

    window.addEventListener(‘resize‘, function(){
        onResize()
    })
    function onResize(){
        arToolkitSource.onResize()
        arToolkitSource.copySizeTo(renderer.domElement)
        if( arToolkitContext.arController !== null ){
            arToolkitSource.copySizeTo(arToolkitContext.arController.canvas)
        }
    }

    var arToolkitContext = new THREEx.ArToolkitContext({
        // cameraParametersUrl: THREEx.ArToolkitContext.baseURL + ‘../data/data/camera_para.dat‘,
        cameraParametersUrl: ‘ar/data/data/camera_para.dat‘,
        detectionMode: ‘mono‘,
        maxDetectionRate: 30,
        canvasWidth: 80*3,
        canvasHeight: 60*3,
    })

    arToolkitContext.init(function onCompleted(){
        camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() );
    })

    onRenderFcts.push(function(){
        if( arToolkitSource.ready === false )
            return;
        arToolkitContext.update( arToolkitSource.domElement )
    })

    var markerRoot = new THREE.Group
    scene.add(markerRoot)
    var artoolkitMarker = new THREEx.ArMarkerControls(arToolkitContext, markerRoot, {
        type : ‘pattern‘,
        patternUrl : THREEx.ArToolkitContext.baseURL + ‘ar/data/data/patt.hiro‘
    })

    // build a smoothedControls
    var smoothedRoot = new THREE.Group()
    scene.add(smoothedRoot)
    var smoothedControls = new THREEx.ArSmoothedControls(smoothedRoot, {
        lerpPosition: 0.4,
        lerpQuaternion: 0.3,
        lerpScale: 1,
    })
    onRenderFcts.push(function(delta){
        smoothedControls.update(markerRoot)
    })

    var arWorldRoot = smoothedRoot

    // add a torus knot
    var geometry    = new THREE.CubeGeometry(1,1,1);
    var material    = new THREE.MeshNormalMaterial({
        transparent : true,
        opacity: 0.5,
        side: THREE.DoubleSide
    });
    var mesh    = new THREE.Mesh( geometry, material );
    mesh.position.y = geometry.parameters.height/2
    arWorldRoot.add( mesh );

    var geometry    = new THREE.TorusKnotGeometry(0.3,0.1,64,16);
    var material    = new THREE.MeshNormalMaterial();
    var mesh    = new THREE.Mesh( geometry, material );
    mesh.position.y = 0.5
    arWorldRoot.add( mesh );

    onRenderFcts.push(function(){
        mesh.rotation.x += 0.1
    })

    var stats = new Stats();
    document.body.appendChild( stats.dom );
    // render the scene
    onRenderFcts.push(function(){
        renderer.render( scene, camera );
        stats.update();
    })

    // run the rendering loop
    var lastTimeMsec= null
    requestAnimationFrame(function animate(nowMsec){
        // keep looping
        requestAnimationFrame( animate );
        // measure time
        lastTimeMsec    = lastTimeMsec || nowMsec-1000/60
        var deltaMsec   = Math.min(200, nowMsec - lastTimeMsec)
        lastTimeMsec    = nowMsec
        // call each update function
        onRenderFcts.forEach(function(onRenderFct){
            onRenderFct(deltaMsec/1000, nowMsec/1000)
        })
    })
</script></body>

当然,这个效果来自大神jeromeetienne开源的AR.js:

https://github.com/jeromeetienne/AR.js/

当然大神自己也很谦虚地提到,他这个开源的增强现实框架也是建立在巨人的肩膀上开发的:比如其中3D效果的绘制,使用到了另一个开源框架three.js:

要获取更多Jerry的原创文章,请关注公众号"汪子熙":

原文地址:https://www.cnblogs.com/sap-jerry/p/10273112.html

时间: 2024-08-02 23:51:50

150行JavaScript代码实现增强现实的相关文章

60行JavaScript代码俄罗斯方块

教你看懂网上流传的60行JavaScript代码俄罗斯方块游戏 早就听说网上有人仅仅用60行JavaScript代码写出了一个俄罗斯方块游戏,最近看了看,今天在这篇文章里面我把我做的分析整理一下(主要是以注释的形式). 我用C写一个功能基本齐全的俄罗斯方块的话,大约需要1000行代码的样子.所以60行乍一看还是很让人吃惊的. 但是读懂了代码之后发现其实整个程序并没有使用什么神秘的技术,只不过是利用一些工具或者JavaScript本身的技巧大大简化了代码. 总结起来主要是以下三点 1.使用eval

教你看懂网上流传的60行JavaScript代码俄罗斯方块游戏

早就听说网上有人仅仅用60行JavaScript代码写出了一个俄罗斯方块游戏,最近看了看,今天在这篇文章里面我把我做的分析整理一下(主要是以注释的形式). 我用C写一个功能基本齐全的俄罗斯方块的话,大约需要1000行代码的样子.所以60行乍一看还是很让人吃惊的. 但是读懂了代码之后发现其实整个程序并没有使用什么神秘的技术,只不过是利用一些工具或者JavaScript本身的技巧大大简化了代码. 总结起来主要是以下三点 1.使用eval来产生JavaScript代码,减小了代码体积 2.以字符串作为

265行 JavaScript 代码实现第一人称引擎

原文:A first-person engine in 265 lines(2014-6-11)翻译:Jaward华仔 今天,让我们进入一个可以伸手触摸的世界吧.在这篇文章里,我们将从零开始快速完成一次第一人称探索.本文没有涉及复杂的数学计算,只用到了光线投射技术.你可能已经见识过这种技术了,比如<上古卷轴2 : 匕首雨>.<毁灭公爵3D>还有 Notch Persson 最近在 ludum dare 上的参赛作品.Notch 认为它够好,我就认为它够好! [Demo (arrow

大神手把手教你写一个页面模板引擎,只需20行Javascript代码!

只用20行Javascript代码就写出一个页面模板引擎的大神是AbsurdJS的作者,下面是他分享的全文,转需. 不知道你有木有听说过一个基于Javascript的Web页面预处理器,叫做AbsurdJS.我是它的作者,目前我还在不断地完善它.最初我只是打算写一个CSS的预处理器,不过后来扩展到了CSS和HTML,可以用来把Javascript代码转成CSS和HTML代码.当然,由于可以生成HTML代码,你也可以把它当成一个模板引擎,用于在标记语言中填充数据. 于是我又想着能不能写一些简单的代

这几行 javascript 代码能让你的浏览器崩溃?

先上Demo,有兴趣的可以先试一下: http://www.zeakhold.com/crash/ (温馨提示:访问前请保存好浏览器其他窗口的任务,整人被打概不负责嘿嘿~) 事情还是得从 IT Security Tweets ™   的一篇推文说起: 也就是说,这段 javascript 代码,能让浏览器崩溃并且能让iPhone重启?! 于是打开电脑跃跃欲试,当满怀好奇地在浏览器上执行了这段代码后发现: Chrome 立马陷入了卡死的状态,更要命的是点击关闭窗口没响应!! 打开任务管理器,发现C

150+行Python代码实现带界面的数独游戏

150行代码实现图形化数独游戏 Github地址,欢迎各位大佬们fork.star啥的,感谢: 今天闲着没事干,以前做过html+js版的数独,这次做个python版本的,界面由pygame完成,数独生成由递归算法实现,由shuffle保证每次游戏都是不一样的情况,have fun: 功能列表: 图形化的数独游戏: python实现,依赖pygame库: 随机生成游戏,每次运行都不一样: 数字填入后的正确性判断以及颜色提示: 显示剩余需填入的空格,已经操作的次数: 难度可选,通过修改需要填入的空

150+行Python代码实现带界面的数独游戏!益智烧脑了解一下!

150行代码实现图形化数独游戏 Github地址 ,欢迎各位大佬们fork.star啥的,感谢: 今天闲着没事干,以前做过html+js版的数独,这次做个python版本的,界面由pygame完成,数独生成由递归算法实现,由shuffle保证每次游戏都是不一样的情况,have fun: 功能列表: 图形化的数独游戏: python实现,依赖pygame库: 随机生成游戏,每次运行都不一样: 数字填入后的正确性判断以及颜色提示: 显示剩余需填入的空格,已经操作的次数: 难度可选,通过修改需要填入的

【转】265行JavaScript代码的第一人称3D H5游戏Demo

译文:http://blog.jobbole.com/70956/ 原文:http://www.playfuljs.com/a-first-person-engine-in-265-lines/ 这是一篇关于利用 Canvas 实现3D 游戏场景绘制的文章,看完感觉很受启发,所以自己准备总结一下.我们先看下最终效果: 很酷是不是.原作者只使用了265行代码就实现了这么炫酷的效果.代码写的也很清晰明了,并且原文也对原理也进行了解释.本篇就直接将原作者的代码全部贴上来大家观赏观赏. 1 <!doct

30行JavaScript代码实现一个比特币量化策略

精简极致的均线策略 30行打造一个正向收益系统 原帖地址:https://www.fmz.com/bbs-topic-new/262 没错!你听的没错是30行代码!仅仅30行小编我习惯先通篇来看看 代码,这样能有个宏观的了解! 策略参数如下 参数 描述 类型 默认值 FastPeriod 入市快线周期 数字型(number) 3 SlowPeriod 入市慢线周期 数字型(number) 7 EnterPeriod 入市观察期 数字型(number) 3 ExitFastPeriod 离市快线周