作为一名 AR 开发者,我一直在寻找能够快速构建高质量 3D 场景的开发框架。最近接触到了 Rokid 开源的 JSAR(JavaScript AR) 框架后,被它的易用性和强大功能所吸引。今天,我想分享一个使用 JSAR 创建精致白色飞机模型的实战案例,展示如何通过代码构建复杂的 3D 模型,以及 JSAR 在开发调试中的优秀体验。


什么是 JSAR?

JSAR 是 Rokid 开源的一款基于 JavaScript 的 AR 开发框架,它让开发者可以使用熟悉的 Web 技术栈来创建 AR 应用。

JSAR 的核心优势包括:

特性 说明
低门槛 使用 JavaScript + XSML(类似 HTML)即可开发 AR 应用
强大的 3D 引擎 内置 Babylon.js,提供丰富的 3D 图形能力
完善的工具链 支持 Chrome DevTools 远程调试,开发体验极佳
标准化开发 采用类似 npm package 的项目结构,易于管理和分发
跨平台 一次开发,可在多种 AR 设备上运行

项目需求

这次我们要创建一个精致的白色飞机模型,具体要求如下:

  1. 占地比例:飞机模型应占据场景平面的 70% 左右

  2. 主色调:纯白色,具有真实飞机的质感

  3. 细节丰富:包含机身、机翼、引擎、起落架、驾驶舱、窗户等完整结构

  4. 动态效果:航行灯闪烁、引擎风扇旋转、轻微飘动效果


JSAR 项目结构

JSAR 项目采用简洁的文件结构,类似于 npm package:

JSAR1/
├── package.json          # 项目配置文件
├── airplane.xsml         # 场景描述文件
├── airplane.js           # 主逻辑代码
└── icon.png             # 项目图标

package.json 配置

{ "name": "airplane-model", "version": "1.0.0", "main": "airplane.xsml", "files": ["airplane.xsml","airplane.js","icon.png"] }

这种标准化的配置方式让项目管理变得非常简单。

airplane.xsml 场景文件

XSML 是 JSAR 的场景描述语言,语法类似 HTML:

<xsml version="1.0">
<head> 
    <title>精致白色飞机模型 - Rokid AR</title>
    <script src="./airplane.js"></script>
</head>
<space></space>
</xsml>

简洁明了的声明式语法,<space> 元素代表 AR 空间场景。


核心开发:利用 JSAR 的 3D 能力

① 初始化场景

JSAR 通过 spatialDocument 全局对象提供场景访问能力:

const { MeshBuilder, Vector3, Color3, StandardMaterial } = BABYLON; 
const scene = spatialDocument.scene; // 设置天空背景 
scene.clearColor = new Color4(0.5, 0.7, 0.95, 1);

JSAR 内置了 Babylon.js 引擎,可以直接使用其强大的 3D API。

② 相机控制

const camera = scene.activeCamera; if (camera) { 
camera.position = new Vector3(200, 150, 300); 
const target = new Vector3(0, 50, 0); 
if ('setTarget' in camera) { camera.setTarget(target); } }

JSAR 自动管理相机,我们只需要设置位置和目标点即可。

③ 构建地面和跑道

// 草地
const ground = MeshBuilder.CreateGround('ground',
    { width: 600, height: 600 }, scene);
const groundMat = new StandardMaterial('ground-mat', scene);
groundMat.diffuseColor = new Color3(0.35, 0.55, 0.35);
ground.material = groundMat;

// 跑道
const runway = MeshBuilder.CreateGround('runway',
    { width: 80, height: 500 }, scene);
runway.position = new Vector3(0, 0.2, 0);

通过 Babylon.js 的 MeshBuilder,创建几何体非常简单直观。

④ 飞机建模策略

飞机是一个复杂的 3D 模型,我们将其拆解为多个组件:

机身主体
  • 机头:使用圆锥体(CreateCylinder 配合不同的顶底直径)

  • 机身:圆柱体

  • 机尾:收窄的圆锥体

// 草地
const ground = MeshBuilder.CreateGround('ground',
    { width: 600, height: 600 }, scene);
const groundMat = new StandardMaterial('ground-mat', scene);
groundMat.diffuseColor = new Color3(0.35, 0.55, 0.35);
ground.material = groundMat;

// 跑道
const runway = MeshBuilder.CreateGround('runway',
    { width: 80, height: 500 }, scene);
runway.position = new Vector3(0, 0.2, 0);
驾驶舱

    使用扁平化的球体创建驾驶舱,配合半透明材质模拟玻璃:

    const cockpit = MeshBuilder.CreateSphere('cockpit', {
        diameter: fuselageRadius * 1.4,
        segments: 16
    }, scene);
    cockpit.scaling = new Vector3(1.5, 0.8, 1); // 拉伸变形
    const cockpitMat = new StandardMaterial('cockpit-mat', scene);
    cockpitMat.diffuseColor = new Color3(0.2, 0.3, 0.4);
    cockpitMat.alpha = 0.6; // 半透明
    cockpitMat.specularPower = 128; // 高光
    窗户系统

    通过循环创建左右对称的窗户,展示 JSAR 的批量创建能力:

    const windowCount = 24;
    for (let i = 0; i < windowCount; i++) {
        const windowL = MeshBuilder.CreateBox(`window-left-${i}`, {
            width: 4, height: 3.2, depth: 1
        }, scene);
    
        const windowMat = new StandardMaterial(`window-mat-${i}`, scene);
        windowMat.emissiveColor = new Color3(0.3, 0.4, 0.5); // 发光效果
        windowL.material = windowMat;
    
        // 右侧窗户克隆
        const windowR = windowL.clone(`window-right-${i}`);
    }
    引擎系统

    这是飞机最复杂的部分,包含外壳、进气口、排气口和风扇叶片:

    function createEngine(name, position) {
        // 引擎外壳
        const engineCasing = MeshBuilder.CreateCylinder(/*...*/);
    
        // 风扇叶片(12片)for (let i = 0; i < 12; i++) {
            const blade = MeshBuilder.CreateBox(/*...*/);
            const angle = (i / 12) * Math.PI * 2;
            blade.rotation.z = angle; // 放射状排列
        }
    
        return { casing, intake, exhaust };
    }
    起落架系统

    包含前起落架和两个主起落架:

    function createMainLandingGear(name, position) {
        const strut = MeshBuilder.CreateCylinder(/*支柱*/);
        const wheel1 = MeshBuilder.CreateCylinder(/*轮子*/);
        const wheel2 = wheel1.clone(/*双轮结构*/);
        return { strut, wheel1, wheel2 };
    }

    材质系统:打造真实感

    JSAR 支持 Babylon.js 的完整材质系统:

    const whiteMat = new StandardMaterial('white-mat', scene);
    whiteMat.diffuseColor = new Color3(0.95, 0.95, 0.98);  // 漫反射
    whiteMat.specularColor = new Color3(0.8, 0.8, 0.8);    // 镜面反射
    whiteMat.specularPower = 64;                            // 高光强度

    通过调整这些参数,可以实现金属、塑料、玻璃等不同材质效果。

    动画系统:赋予生命

    JSAR 支持场景级别的动画循环:

    const whiteMat = new StandardMaterial('white-mat', scene);
    whiteMat.diffuseColor = new Color3(0.95, 0.95, 0.98);  // 漫反射
    whiteMat.specularColor = new Color3(0.8, 0.8, 0.8);    // 镜面反射
    whiteMat.specularPower = 64;                            // 高光强度

    registerBeforeRender 是 JSAR 提供的核心动画 API,每帧执行一次,可以实现各种动态效果。


    真机调试:Chrome DevTools 调试

    这是 JSAR 最令人惊喜的特性之一!你可以使用 Chrome DevTools 远程调试 AR 应用

    调试步骤

    1. 连接设备:将 Rokid AR 设备通过 USB 连接到电脑

    2. 打开调试页面:Chrome 访问 chrome://inspect

    3. 发现设备:在 Remote Target 中找到你的 JSAR 应用

    4. 开始调试:点击 inspect 打开 DevTools

    调试功能

    功能模块 说明
    ✅ Console 实时查看 console.log 输出,查看报错信息
    ✅ Sources 设置断点,单步调试代码
    ✅ Network 监控资源加载情况
    ✅ Performance 分析性能瓶颈,优化渲染帧率
    ✅ Memory 检查内存使用,查找内存泄漏

    实际调试案例

    在开发飞机模型时,我遇到了窗户位置不对齐的问题。通过 Chrome DevTools:

    1. 在 Console 中输入 scene.meshes.filter(m => m.name.includes('window')) 查看所有窗户对象

    2. 选择某个窗户,在 Console 修改位置:scene.getMeshByName('window-left-0').position.y = 30

    3. 实时看到效果,确认正确位置后修改代码

    4. 使用 Sources 面板设置断点,检查循环中的变量值

    这种即时反馈的开发体验,大大提升了开发效率!


    性能优化技巧

    JSAR 场景中对象数量较多时,需要注意性能:

    ① 合理使用 Clone

    // 好的做法:克隆已有对象
    const window2 = window1.clone('window-2');
    
    // 避免:重复创建相同对象
    const window2 = MeshBuilder.CreateBox(/*...*/); // 重复创建

    ② 共享材质

    // 多个对象使用同一材质
    const whiteMat = new StandardMaterial('white-mat', scene);
    noseCone.material = whiteMat;
    fuselageMain.material = whiteMat;
    fuselageTail.material = whiteMat;

    ③ 控制动画更新范围

    scene.registerBeforeRender(() => { 
    // 只更新需要动画的对象
    // 避免更新所有对象 
    });

    ④ 使用 Chrome DevTools 监控

    通过 Performance 面板查看帧率,找出性能瓶颈:

    • FPS < 30:场景过于复杂,需要优化

    • FPS 30-60:良好

    • FPS = 60:完美

    最终效果

    正面:

    侧面:

    通过 Console 可以看到统计信息:

    ✈️ 飞机尺寸: 294 x 336 x 63
    📐 占地比例: 56.0%
    🪟 窗户数量: 48
    ✨ 细节包含: 驾驶舱、引擎系统、起落架、航行灯、舱门等
    📦 总对象数: 180+

    JSAR 开发心得

    经过这个项目的实战,我总结了 JSAR 的几个核心优势:

    优点 说明
    学习曲线平缓 如果你熟悉 JavaScript 和基本的 3D 概念,上手 JSAR 非常快。Babylon.js 的 API 设计直观,文档完善。
    开发工具完善 Chrome DevTools 的支持是杀手级特性,让 AR 开发也能享受 Web 开发的便捷调试体验。
    代码即场景 不需要导入外部 3D 模型,纯代码构建场景。这种方式虽然初期需要较多代码,但后期维护和动态生成非常灵活。
    性能表现优秀 基于 Babylon.js 的 JSAR 在移动 AR 设备上表现出色,即使有 180+ 个对象和多个动画,依然能保持流畅的帧率。
    社区和文档 Rokid 论坛活跃,官方文档详细,遇到问题能快速找到解决方案。

    总结

    JSAR 为 AR 开发者提供了一个强大而易用的开发框架。通过这个飞机模型项目,我们看到了:

    • 使用 JavaScript 构建复杂 3D 场景的能力

    • Chrome DevTools 带来的出色调试体验

    • Babylon.js 引擎提供的丰富图形能力

    • JSAR 标准化的项目结构和开发流程

    如果你也对 AR 开发感兴趣,不妨试试 JSAR。从简单的立方体开始,逐步构建你的 3D 世界,相信你会和我一样,被它的优雅和强大所打动。


    相关资源

    更多推荐