这是一款基于Three.js的3D编辑器,我之前一直喊错,叫人家"牛牛",因为我觉得它真的好牛,其实人家正确拼音喊“努努”!
官网地址:https://www.nunustudio.org/
,里面内容很详细。我也是刚用不久,在这里写个入门教程。
推荐下载他的electron的版本的安装包,本地运行快点!并且可以发布web的运行包,直接可以网页端二次开发,真的不要太方便了!
1.布局介绍
配置一下场景,然后点击上方的run就可以看到预览界面效果了
2.工具栏介绍
选中对象,当然也可以直接在右侧的对象列表里点击选中
移动对象,对应position属性x,y,z,也可以在配置板面直接修改对应数值
缩放对象,对应scale属性x,y,z,也可以在配置板面直接修改对应数值
旋转对象,对应rotation属性的x,y,z,也可以在配置板面直接修改对应数值
其实我感觉这个操作对象,分开一个个点有点鸡肋,很不习惯!
1.2 对象栏
添加形状物体,不同物体的配置板面属性有所不同
添加字体
添加光源,常用的环境光,平行光,点光源等都有,像点光源之类的默认是勾选了产生投影的
添加镜头,有透视镜头和正交镜头,添加后可以看到镜头视角的预览画面,如果需要把这个镜头的画面作为运行画面,需要勾选
use camera
添加控制器,camera记得要勾选
use camera
3.添加脚本(运行时可用,编辑时效果不可见)
可用参数
● self 对象属性 (position, rotation, scale, children等).
● program 当前程序包含当前场景scene,里面的资源resources,可通过(getMaterialByName, getTextureByName等方法获取)
● scene运行场景.
● Keyboard 键盘输入
● Mouse鼠标操作
函数
● initialize在加载场景时调用,它通常用于以编程方式创建新对象、从场景中获取对象、初始化变量等.
● update在将场景绘制到屏幕之前调用每个帧,它可以用于控制对象、获取输入值、更改对象属性等.
● dispose当程序关闭时调用,应用于清理对象、断开与数据流的连接等.
● onMouseOver(objects)当鼠标位于脚本对象的子对象上时调用,可以与鼠标函数组合检查对象是否被单击。接收到对象数组作为参数.
● onResize(x, y) 每次调整程序窗口的大小时调用.
● onAppData(data) 用于从主机页接收数据,数据作为参数接收,用于消息传递
1.操作对象,绕脚本中心点旋转
function initialize()
{
self.position.x += 2;
}
function update()
{
self.rotation.y += 0.01;
}
2.鼠标键盘控制
function update()
{
//鼠标控制旋转
self.rotation.y += Mouse.delta.x * 0.01;
//键盘控制移动
if(Keyboard.keyPressed(Keyboard.LEFT))
{
self.position.x -= 0.1;
}
if(Keyboard.keyPressed(Keyboard.RIGHT))
{
self.position.x += 0.1;
}
}
3.获取场景中对象
var object;
var count=0
function initialize()
{
object = scene.getObjectByName("box");
object.position.y=2;
}
function update()
{
//使用该材质的对象随机变色
if(count%60==0){
object.material.color=new THREE.Color(`rgb(${parseInt(Math.random()*200)},${parseInt(Math.random()*200)},${
parseInt(Math.random()*200)})`);
}
count++;
}
4.获取子对象
var object1,object2;
function initialize()
{
object1 = self.children[0];//cylinder
object2 = self.children[1];//box
}
function update()
{
object1.rotation.x += 0.01;
object2.rotation.y += 0.01;
}
5.右击顶层program,新增一个scene场景,双击那个场景进行编辑,可通过脚本切换场景
//在场景1添加脚本
function update()
{
//按w切换到场景2
if(Keyboard.keyPressed(Keyboard.W))
{
//获取程序里的场景2
program.setScene("scene2");
}
}
6.添加html,注意这个不是CSS2DRender,不会跟着场景元素进行变换
var element = document.createElement("div");
element.style.width = "100px";
element.style.height = "100px";
element.style.position = "absolute";
element.style.top = "100px";
element.style.left = "100px";
element.style.backgroundColor = "#0000FF";
function initialize()
{
//添加html
program.division.appendChild(element);
}
function dispose()
{
//销毁时记得删除对应元素
program.division.removeChild(element);
}
7.引入外部脚本,先把js导入项目,再用include来引入库,进行使用
include("moment.js");
var text;
function initialize()
{
text=program.getObjectByName('text');
console.log(moment)
}
function update(){
text.setText(moment().format('LTS'));
}
网页端和electron有所不同,网页端应该是最新的,有些奇怪的bug已经修复,比如在electron里面是脚本一旦运行错误,你就得重新打开nunuStudio才能再run,网页端就不会这样禁止运行
3.材质与贴图
可以创建需要的材质和贴图,双击对应的资源就可以进入配置界面
贴图可以拖入材质的对应texture属性里面,也可以直接上传图片作为新的贴图
材质可以通过拖拽赋值到对应的对象里面,鼠标悬浮对应材质,对应材质会变色,就知道这个对象用什么材质了。
这个材质和贴图管理有点麻烦,添加贴图和材质莫名生成一堆重复的,一旦材质和贴图资源太多,就会导致很难辨别对象使用的是谁,而且你删除对象的时候,要是对应材质和贴图没有引用,它也不会主动删除,还是会留在资源库里,得手动删除。
4.raycaster拾取对象
先添加一个camera镜头作为射线拾取的视图,然后添加模型,根据点击设置对应的材质
var red, blue;
function initialize()
{
red = program.getMaterialByName("red");
blue = program.getMaterialByName("blue");
}
function update()
{
//获取射线拾取到的对象
var intersects = scene.raycaster.intersectObjects(scene.children);
for(var i = 0; i < intersects.length; i++)
{
//左点击设置为red的材质
if(Mouse.buttonPressed(Mouse.LEFT))
{
intersects[i].object.material = red;
}
//右点击设置为blue的材质
else if(Mouse.buttonPressed(Mouse.RIGHT))
{
intersects[i].object.material = blue;
}
}
}
5.发布web网页和导出模型
调整好在nunuStudio的效果,可以导出一个web网页,就是对应的预览界面了
index.html里面的代码里有Nunu加载的代码,可进行二次开发,里面是直接可以用THREE的,但是控制器推荐用nunu的,估计它里面用改写过controls,自己添加的THREE的control会报错。里面有些bug,比如飞线之类的动态效果,在导出的预览文件无法复现效果,而在编辑器可以正常运行。我也不知道为什么!
var app;
//Initialize app
function run()
{
//Create app object
app = new NunuApp();
//Onload enable the vr and fullscreen buttons
var logo = document.getElementById("logo");
//加载成功后
var onLoad = function()
{
var button = document.getElementById("fullscreen");
button.style.visibility = "visible";
//Check if VR is available
if(app.vrAvailable())
{
//If there are displays available add button
Nunu.getVRDisplays(function(display)
{
button = document.getElementById("vr");
button.style.visibility = "visible";
});
}
//Remove logo and loading bar
document.body.removeChild(logo);
};
//下载进度条
var bar = document.getElementById("bar");
var onProgress = function(event)
{
if(event.lengthComputable)
{
var progress = event.loaded / event.total * 100;
bar.style.width = progress + "%";
}
};
//Load and run nunu app
app.loadRunProgram("app.nsp", onLoad, onProgress);
}
//window resize时调整大小
function resize()
{
app.resize();
}
//全屏
function toggleFullscreen()
{
app.toggleFullscreen(document.body);
}
//Toggle VR mode
function toggleVR()
{
app.toggleVR();
}
调好效果可以导出模型,这个也有点bug,有些格式不能完全导出所有的对象和效果,gltf格式,比如hemisphere光源没跟着导出来,材质里面的emissveMap,alphaMap也没跟着导出来,因此导入模型后要手动代码搞一下。
总结
我这里介绍的都是常用的,官网上还有许多优秀的案例,以及功能介绍,什么动画啊,物理啊,粒子,后期效果啊!还能做游戏!真的太多了!你可以在上面搞得差不多再导出来二次开发,省了很多效果设置的功夫!
总体来说,虽然有些bug和操作的鸡肋,但是真的是很优秀的一款3D编辑器!期待会越来越好!
我基于官方的nunuStudio的github地址fork了一下,根据自己和建模师的使用习惯,修改了一些操作
代码地址:https://github.com/xiaolidan00/nunuStudio/tree/dev-0.9.6