#ThreeJS学习笔记( 二) 您所在的位置:网站首页 外部模型导入romax #ThreeJS学习笔记( 二)

#ThreeJS学习笔记( 二)

2023-12-12 00:43| 来源: 网络整理| 查看: 265

#ThreeJS学习笔记( 二)——导入外部模型 ubee 作者: ubee 日期: 2016-08-03 214503 外部模型格式

Threejs支持了许多格式的3D模型导入,包括*.obj、 *.sea、*.3mf 、*.amf、*.sea、*.pmd、*.json等。 这里主要讲解一下obj模型的导入,及将obj文件转成文件更小的json格式导入。

导入obj模型 3Dmax格式转换成obj格式

美术提供的一般为3Dmax项目文件夹,里面包含了.max文件以及贴图图片等资源,用3DMAX打开.max文件可以看到3D模型 如图:

1469608235365.png

点击菜单里的导出,选择obj格式,点击保存后出现选项 导出比例:几何体选项里的输出比例,默认是1.0,我们根据模型的分辨率,以及需要在网页上呈现的分辨率设置一下比例输出即可。简单的说,你直接按1.0比例输出的如果在浏览器看的时候大小差距太大了,可以在这里导出比例设置一下,另外也可以设置mesh的scale,直接缩放。这个模型需要将比例设置为0.1。几何体的其他选项都不需要修改。 材质:点击材质导出,勾选使用材质路径,选择保存材质的路径。格式为jpg,格式设置中可以设置导出jpg的质量,无特殊要求默认即可,并勾选转换位图,关闭材质设置。 点击导出,导出过程有可能会提示找不到材质,设置材质路径为美术提供的文件夹目录即可 最后会得到一个*.obj文件、一个*mtl文件、若干材质图,包括多个不同通道的贴图jpg和法线贴图jpg

1469608270416.png

1469608312275.png

1469608413927.png

1469610128497.png

导出obj后的二次处理

导出后的文件如图所示

1469613142241.png

其中,test.mtl文件定义了test.obj模型与各贴图间的对应关系。 由于示例中的模型是由多个子模型组成的模型组,同时设置了多通道贴图,每一个子模型都对应四张贴图。 打开mtl文件,我们可以看到每个子模型都有一组贴图数据

# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware # 创建的文件:27.07.2016 17:00:50 newmtl JZ2012_jz_l_1 Ns 20.0000 Ni 1.5000 d 1.0000 Tr 0.0000 Tf 1.0000 1.0000 1.0000 illum 2 Ka 0.5882 0.5882 0.5882 Kd 0.5882 0.5882 0.5882 Ks 0.4500 0.4500 0.4500 Ke 0.0000 0.0000 0.0000 map_Ka JZ2012_jz_d.jpg map_Kd JZ2012_jz_d.jpg map_Ks JZ2012_jz_s.jpg map_Ke JZ2012_jz_e.jpg map_bump Map__171_法线凹凸.jpg newmtl JZ2030_jz_l_1 ......

例如上面例子中关于子模型JZ2012_jz_l_1 贴图描述,其中map_Ka,map_Kd,map_Ks,map_Ke指定了各通道对应的贴图,map_bump则指定了法线贴图:

1469613671197.png

在使用threejs的mtlLoader解析mtl贴图并渲染为模型材质时,threejs仅调用map_Ka通道图片和map_bump法线贴图进行材质渲染。而基于图片数量及文件大小的控制,项目中采用的方法是让设计师将 JZ2012_jz_d.jpg、JZ2012_jz_s.jpg、JZ2012_jz_e.jpg三张图合成并调色后作为map_Ka通道贴图:

1469623501953.png

注:目前未查到threeJS 的mtl_loader是否能自动载入多通道贴图,待研究。 另外由于自动导出的法线贴图名称中带有中文,需要将mtl中map_bump和对应的法向贴图名称改成非中文命名。 在做以上图片处理时,需要同时将图片资源做压缩处理,以免资源加载时间过长。

使用mtlLoader和objLoaer加载obj模型及贴图

加载带mtl材质的obj模型,需要先定义mtl对象并加载mtl之外再加载obj模型。此时需要引用threejs两个js库

THREE.MTLLoader()函数说明:

mtlLoader.setBaseUrl():设置材质路径 mtlLoader.setPath():设置mtl文件所在路径 mtlLoader.load(filename,onSuccess(materials ),onProgress(xhr),onError(error)):mtl文件名、 加载成功后回调处理(参数为生成的材质库)、加载过程中回调处理(xhr对象属性可计算出已完成加载百分比)、失败回调处理

THREE.OBJLoader() 函数说明:

objLoader.setMaterials( materials ):设置obj使用的材质贴图 objLoader.setPath( options.objPath ):设置obj文件所在路径 objLoader.load( filename,onSuccess(object ),onProgress(xhr),onError(error)):obj文件名、 加载成功后回调处理(参数为生成的三维对象)、加载过程中回调处理(xhr对象属性可计算出已完成加载百分比)、失败回调处理。

在onSuccess(object ){}回调里我们可以对生成的三维对象做一些处理:对材质进行调色、设置透明度、设置贴图模式等,对设置旋转、缩放、位置摆放、自发光颜色、环境光颜色。 如果obj文件代表的三维对象是由多个子模型构成的模型组合,我们可以调用object.traverse(function(child){})来对每个子模型进行处理。 以下简单封装成一个函数

function createMtlObj(options){ // options={ // mtlBaseUrl:"", // mtlPath:"", // mtlFileName:"", // objPath:"", // objFileName:"", // completeCallback:function(object){ // } // progress:function(persent){ // // } // } THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() ); var mtlLoader = new THREE.MTLLoader(); mtlLoader.setBaseUrl( options.mtlBaseUrl );//设置材质路径 mtlLoader.setPath( options.mtlPath );//设置mtl文件路径 mtlLoader.load( options.mtlFileName, function( materials ) { materials.preload(); var objLoader = new THREE.OBJLoader(); objLoader.setMaterials( materials );//设置三维对象材质库 objLoader.setPath( options.objPath );//设置obj文件所在目录 objLoader.load( options.objFileName, function ( object ) { if(typeof options.completeCallback=="function"){ options.completeCallback(object); } }, function ( xhr ) { if ( xhr.lengthComputable ) { var percentComplete = xhr.loaded / xhr.total * 100; if(typeof options.progress =="function"){ options.progress( Math.round(percentComplete, 2)); } //console.log( Math.round(percentComplete, 2) + '% downloaded' ); } }, function(error){ }); }); }

调用示例:

createMtlObj({ mtlBaseUrl:"../resource/haven/", mtlPath: "../resource/haven/", mtlFileName:"threejs.mtl", objPath:"../resource/haven/", objFileName:"threejs.obj", completeCallback:function(object){ object.traverse(function(child) { if (child instanceof THREE.Mesh) { child.material.side = THREE.DoubleSide;//设置贴图模式为双面贴图 child.material.emissive.r=0;//设置rgb通道R通道颜色 child.material.emissive.g=0.01;//设置rgb通道G通道颜色 child.material.emissive.b=0.05;//设置rgb通道B通道颜色 child.material.transparent=true;//材质允许透明 //child.material.opacity=0;//材质默认透明度 //child.material.shading=THREE.SmoothShading;//平滑渲染 } }); object.emissive=0x00ffff;//自发光颜色 object.ambient=0x00ffff;//环境光颜色 // object.rotation.x= 0;//x轴方向旋转角度 object.position.y = 0;//位置坐标X object.position.z = 0;//位置坐标y object.scale.x=1;//缩放级别 object.scale.y=1;//缩放级别 object.scale.z=1;//缩放级别 object.name="haven";//刚体名称 object.rotation.y=-Math.PI;//初始Y轴方向旋转角度 scene.add(object);//添加到场景中 }, progress:function(persent){ $("#havenloading .progress").css("width",persent+"%"); } })

此时如果在之前没有添加光源,在浏览器上看到的可能是一片黑色,通过增加光源可以将物体显现出来。比例添加一个全局光

var ambient = new THREE.AmbientLight( 0xffffff ); scene.add( ambient );

此时在浏览器看到是这样的效果: 1470037673302.png

导入obj模型的后期渲染

如上图看到,我们导入的模型经过调色虽然比3Dmax显示效果好些,但仍然一片灰蒙蒙,丑不拉叽的。所以后期需要适当添加各种光源来渲染出更好的效果。 添加一个平行光做为主光源营造反射光面,并添加三个点光源对暗部适当补光后效果如下:

var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( -5, 5, 5).normalize(); scene.add( directionalLight ); var pointlight = new THREE.PointLight(0x63d5ff, 1, 200); pointlight.position.set(0, 0, 200); scene.add( pointlight ); var pointlight2 = new THREE.PointLight(0xffffff, 1, 200); pointlight2.position.set(-200, 200, 200); scene.add( pointlight2 ); var pointlight3 = new THREE.PointLight(0xffffff, 1.5, 200); pointlight3.position.set(-200, 200, 0); scene.add( pointlight3 );

1470039562664.png

接下再添加一个4000*4000*4000的天空盒子作为背景,并适当调整camera的可视范围,最后显示结果如下:

1470039862826.png

在设置点光源位置时可借助Threejs提供的helper来查看设置的点光源位置,方便调整光源位置

scene.add( new THREE.PointLightHelper( pointlight3 ) ); scene.add( new THREE.PointLightHelper( pointlight2 ) ); scene.add( new THREE.PointLightHelper( pointlight ) );

1470041255056.png

DEMO:

var container, stats; var camera, scene, renderer; var mouseX = 0, mouseY = 0; var windowHalfX = window.innerWidth / 2; var windowHalfY = window.innerHeight / 2; init(); animate(); var mesh; function init() { container = document.getElementById("space") camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 8000 ); camera.position.set(0, 0, 1500); scene = new THREE.Scene(); var ambient = new THREE.AmbientLight( 0xffffff ); scene.add( ambient ); var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( -5, 5, 5).normalize(); scene.add( directionalLight ); var pointlight = new THREE.PointLight(0x63d5ff, 1, 200); pointlight.position.set(0, 0, 200); scene.add( pointlight ); var pointlight2 = new THREE.PointLight(0xffffff, 1, 200); pointlight2.position.set(-200, 200, 200); scene.add( pointlight2 ); var pointlight3 = new THREE.PointLight(0xffffff, 1.5, 200); pointlight3.position.set(-200, 200, 0); scene.add( pointlight3 ); scene.add( new THREE.PointLightHelper( pointlight3 ) ); scene.add( new THREE.PointLightHelper( pointlight2 ) ); scene.add( new THREE.PointLightHelper( pointlight ) ); var path = "../resource/sky/"; var format = '.jpg'; var urls = [ path + 'px' + format, path + 'nx' + format, path + 'py' + format, path + 'ny' + format, path + 'pz' + format, path + 'nz' + format ]; var skyMaterials = []; for (var i = 0; i < urls.length; ++i) { var loader = new THREE.TextureLoader(); loader.setCrossOrigin( this.crossOrigin ); var texture = loader.load( urls[i], function(){}, undefined, function(){} ); skyMaterials.push(new THREE.MeshBasicMaterial({ //map: THREE.ImageUtils.loadTexture(urls[i], {},function() { }), map: texture, overdraw: true, side: THREE.BackSide, //transparent: true, //needsUpdate:true, premultipliedAlpha: true //depthWrite:true, // wireframe:false, }) ); } var cube = new THREE.Mesh(new THREE.CubeGeometry(4000, 4000,4000), new THREE.MeshFaceMaterial(skyMaterials)); cube.name="sky"; scene.add(cube); createMtlObj({ mtlBaseUrl:"../resource/haven/", mtlPath: "../resource/haven/", mtlFileName:"threejs.mtl", objPath:"../resource/haven/", objFileName:"threejs.obj", completeCallback:function(object){ object.traverse(function(child) { if (child instanceof THREE.Mesh) { child.material.side = THREE.DoubleSide; child.material.emissive.r=0; child.material.emissive.g=0.01; child.material.emissive.b=0.05; child.material.transparent=true; //child.material.opacity=0; //child.material.shading=THREE.SmoothShading; } }); object.emissive=0x00ffff; object.ambient=0x00ffff; //object.rotation.x= 10/180*Math.PI; object.position.y = 0; object.position.z = 0; object.scale.x=1; object.scale.y=1; object.scale.z=1; object.name="haven"; object.rotation.y=-Math.PI; scene.add(object); }, progress:function(persent){ $("#havenloading .progress").css("width",persent+"%"); } }) renderer = new THREE.WebGLRenderer(); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); document.addEventListener( 'mousemove', onDocumentMouseMove, false ); window.addEventListener( 'resize', onWindowResize, false ); } var controls = new THREE.OrbitControls(camera,container); //controls.maxPolarAngle=1.5; //controls.minPolarAngle=1; controls.enableDamping=true; controls.enableKeys=false; controls.enablePan=false; controls.dampingFactor = 0.1; controls.rotateSpeed=0.1; // controls.enabled = false; //controls.minDistance=1000; //controls.maxDistance=3000; function createMtlObj(options){ // options={ // mtlBaseUrl:"", // mtlPath:"", // mtlFileName:"", // objPath:"", // objFileName:"", // completeCallback:function(object){ // } // progress:function(persent){ // // } // } //THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() ); var mtlLoader = new THREE.MTLLoader(); mtlLoader.setBaseUrl( options.mtlBaseUrl ); mtlLoader.setPath( options.mtlPath ); mtlLoader.load( options.mtlFileName, function( materials ) { materials.preload(); var objLoader = new THREE.OBJLoader(); objLoader.setMaterials( materials ); objLoader.setPath( options.objPath ); objLoader.load( options.objFileName, function ( object ) { if(typeof options.completeCallback=="function"){ options.completeCallback(object); } }, function ( xhr ) { if ( xhr.lengthComputable ) { var percentComplete = xhr.loaded / xhr.total * 100; if(typeof options.progress =="function"){ options.progress( Math.round(percentComplete, 2)); } //console.log( Math.round(percentComplete, 2) + '% downloaded' ); } }, function(error){ } ); }); } function onWindowResize() { windowHalfX = window.innerWidth / 2; windowHalfY = window.innerHeight / 2; camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } function onDocumentMouseMove( event ) { mouseX = ( event.clientX - windowHalfX ) / 2; mouseY = ( event.clientY - windowHalfY ) / 2; } function animate() { requestAnimationFrame( animate ); render(); } function render() { // camera.position.x += ( mouseX - camera.position.x ) ; // camera.position.y += ( mouseY - camera.position.y ) ; camera.lookAt( scene.position ); renderer.render( scene, camera ); } 使用jsonLoader加载3D模型

threejs提供了对json格式的支持,相对obj格式的文件来说要小很多,可以提高模型的加载速度。 将obj文件转为了json格式需要借助一个软件:blender以及THREEJS提供的插件io_three; 软件下载地址:https://www.blender.org/ io_three插件在three代码包里的路径:three.js-master/utils/exporters/blender/addons

安装插件的方法 将io_three 复制到blender安装目录下的addons目录中,如:D:\blender-2.77a-windows64\2.77\scripts\addons 打开blender,点击菜单->用户设置,向下拖动保存用户设置按钮所在的区域,会显示所有的用户设置内容 选择add-ons选项卡,在左侧搜索框输入three ,将右侧出现的结果勾选上,到此则已经启用该插件。

1470192336842.png

转换格式 在blender中新建 一个项目,删除默认添加的正方体等对象 切换回info菜单栏,点击文件->导入->*.obj,选择obj之后,blender中会显示模型 点击文件->导出->Threejs(.json),保存为haven.json,存储到材质所在的路径。导出设置如下:

1470209341377.png

使用JsonLoader载入json var loader = new THREE.JSONLoader(); loader.load( '../resource/haven/haven.json', function ( geometry, materials ) { var object = new THREE.Mesh( geometry, materials[0] ); object.material.side = THREE.DoubleSide; object.material.emissive.r=0; object.material.emissive.g=0.01; object.material.emissive.b=0.05; object.material.transparent=true; //object.material.opacity=0; object.material.shading=THREE.SmoothShading; object.position.y = 0; object.position.z = 0; object.scale.x=1; object.scale.y=1; object.scale.z=1; scene.add(object); })

这时我们看到的图像是这样的

1470209408071.png

是的,没错,blender只能将当前选中的单个模型导出json文件,我们使用的obj文件是由多个子模型构成的模型组合,需要对每个子模型单独导出为json文件,并在页面中使用jsonLoader单独载入。

手机阅读请扫描下方二维码:

none 上一篇:图册组件优化之路(一)   下一篇:HTML5的history API和浏览器历史记录管理 已有 36 条评论 王其征 2017-01-11 17:10:49

有在线预览地址吗? 我教程走 根本没用啊…… 报错 Uncaught TypeError: Cannot read property 'visible' of undefined at p (three.min.js:134) at p (three.min.js:134) at Xd.render (three.min.js:173) at render (main.js?v=fsd:195) at animate (main.js?v=fsd:189)

回复 ubee 2017-03-10 17:42:26

我的代码里没有设置visible属性的,看一下是否你自己的代码里main属性里的animate方法里的脚本是否有多余的设置

回复 h.g. 2017-01-17 16:47:52

咨询一个问题,向blender导入文件的时候,为什么就只导入模型,没有图片。这样模型没有皮肤。很奇怪。

回复 金石小镇移动端项目总结R11;WebGL应用 R11; 北京唯幻科技有限公司 2017-01-19 10:18:39

[...]http://feg.netease.com/archives/301.html[...]

回复 无赖泽 2017-01-20 11:15:48

test

回复 bjzhangzhilei 2017-03-06 10:44:32

你好,我是北京网易传媒的,有个3dmax方面的问题请教一下,你们3dmax贴图的材质球是用的默认扫描线渲染器下的材质球吗?但是看你们的mtl文件中的代码,是newmtl,这个应该是mental rey或v-rey渲染器下的名字,我用这两个渲染器下的材质球,导出obj时,贴图导不出来,只能在默认扫描线渲染器下的材质球导出obj才能导出贴图。这是我遇到的问题以及总结http://jingyan.baidu.com/article/fec7a1e5d9e7011190b4e7b6.html,我觉得您是用插件渲染器导出的贴图,求指教,谢谢啦!

回复 bjzhangzhilei 2017-03-07 11:30:38

找到答案了,已经解决!

回复 ubee 2017-03-10 17:44:42

3Dmax是由美术同学提供的。具体用哪个渲染器我就不知道了

回复 yang61591 2017-05-18 14:12:53

找到什么答案可以分享么~最近也踩了你说的坑 ali-43.gif

回复 JsonDiv 2017-10-19 14:34:26

天啦噜,找到答案了也不说一下,还出来炫耀一下。。。 ali-45.gif

回复 ubee 2017-08-28 17:15:38

这个问题,obj本身不带贴图,需要mtl同时导入,另外导出obj+mtl时,如果贴图路径没设置正确,可以用文本编辑器打开mtl文件,把图片路径修改为项目的相对路径。 单独导入obj是没有贴图的。如果只有obj可以用threejs的textureload导入贴图,并在导入obj后, 把obj的mesh.materital设置为导入的贴图。

回复 zm10 2018-02-25 10:15:58

您好,我导出obj格式后,没有导出贴图文件,mtl文件中也没有贴图路径是为什么呢

回复 张志龙 2019-08-19 10:42:07

你好,请问将单独的obj文件导入threejs中,贴图的时候只会改变obj 的颜色而看不到实际的纹理,可能在那些方面出问题?

回复 ubee 2017-03-10 17:42:17

我的代码里没有设置visible属性的,看一下是否你自己的代码里main属性里的animate方法里的脚本是否有多余的设置

回复 翟浩 2017-04-12 10:55:32

能否给demo包,新手求老司机领路 ali-52.gif

回复 ubee 2017-08-28 17:26:48

直接上threejs.org上找就可以了 加载obj的是这个 demo https://threejs.org/examples/?q=obj#webgl_loader_obj_mtl

回复 leovan 2017-05-26 15:09:45

能否给个demo包,新手求老司机带路

回复 ubee 2017-08-28 17:26:43

直接上threejs.org上找就可以了 加载obj的是这个 demo https://threejs.org/examples/?q=obj#webgl_loader_obj_mtl

回复 inuyasha1981 2017-06-21 14:15:04

想请教一个问题,three.js 导入 Obj 时,如果 Obj 本身是带有分组的,会把分组下的原件重复添加进去。比如在3D建模中,Room作为一个模型,编组下面有 Desk 对象。那么 three.js 导入 obj 后,Desk 这个对象会被导入两次,生成一个 Desk_1。这个怎么解决?如果不在建模时分组,那么我又怎么样在导入 Obj 之后把 Desk 和 Room 重新编组呢?例如 Room.add(Desk); 这样的形式。希望有时间的话可以回复,谢谢。

回复 ubee 2017-08-28 17:12:31

你这个room应该只是一个group,你可以只循环mesh添加,或者只添加group,这样就只会导入一次,重新编组,可以var g=new THREE.Group(); g.add(mesh1);g.add(mesh2),这样子,mesh1 和mesh2的position参考系就以g的中心点为原点。

回复 zhang 2017-07-30 23:54:49

问一下,max2012导出obj包含贴图并转换格式之后,如dds转tga。dds转xxx,导出的贴图都变暗了。用2010的倒是没问题。另外 使用obj导出的贴图不能带通道吗?源贴图是有通道的,导出之后通道就消失了? ali-45.gif

回复 ubee 2017-08-28 17:09:52

我之前也遇过这个问题,后来发现threejs只贴了一个通道的图,最后我只能把所有的通道都合并成一张图,或者使用lightMAP来贴光影图。

回复 ubee 2017-08-28 17:33:23

用ligthMAP还需要把UV展开,搞2层uv,在原来的uv上贴上默认贴图,在uv2上贴光影图。而obj不支持2UV,只能blender加载包含2uv的模型,然后导出带2uv信息的json,再用threejs导入json。

回复 不吃火锅底料 2017-08-29 14:32:47

你好,请问下如果我要加载不同的obj模型,建模出来的obj模型大小位置都不统一,这时候不能把camera的位置写死吧,该如何做到设置camera位置适配不同的模型啊

回复 ubee 2017-10-19 14:41:55

建议调整模型的position 和scale 来统一,而不调整camera。调camera的位置更难统一视觉效果。。

回复 Tusi 2019-08-19 17:18:59

好厉害呀,学习一下

回复 D_R_M 2020-02-24 08:28:29

好文

回复 weqe 2020-04-15 15:20:03

asd

回复 阿辛 2020-04-21 10:08:17

非常感谢 ali-43.gif

回复 guagua123 2020-04-24 20:11:43

你好,我最近刚学threejs,在加载了包含贴图的mtl时爆了错误,Handlers.get() has been removed. Use LoadingManager.getHandler() instead.和这个错误Cannot read property 'setCrossOrigin' of undefined,这个错误是什么原因导致的呢?我怀疑是贴图路径的原因,但是路径我已经改为英文的了,还是报这个错误,有哪位大佬能帮我解惑 ali-61.gif

回复 guoguo 2021-01-07 11:40:45

我也遇到了这个问题 求问怎么解决

回复 1 2023-01-25 13:28:40

1 ali-40.gif ali-40.gif ali-41.gif ali-41.gif ali-42.gif ali-42.gif ali-43.gif ali-43.gif ali-44.gif ali-44.gif ali-45.gif ali-45.gif ali-46.gif ali-46.gif ali-47.gif ali-47.gif ali-48.gif ali-48.gif ali-49.gif ali-49.gif ali-50.gif ali-50.gif ali-51.gif ali-51.gif ali-52.gif ali-52.gif ali-53.gif ali-53.gif ali-54.gif ali-54.gif ali-55.gif ali-55.gif ali-56.gif ali-56.gif ali-57.gif ali-57.gif ali-58.gif ali-58.gif ali-59.gif ali-59.gif ali-60.gif ali-60.gif ali-61.gif ali-61.gif

回复 1 2023-01-25 13:28:40

1 ali-40.gif ali-40.gif ali-41.gif ali-41.gif ali-42.gif ali-42.gif ali-43.gif ali-43.gif ali-44.gif ali-44.gif ali-45.gif ali-45.gif ali-46.gif ali-46.gif ali-47.gif ali-47.gif ali-48.gif ali-48.gif ali-49.gif ali-49.gif ali-50.gif ali-50.gif ali-51.gif ali-51.gif ali-52.gif ali-52.gif ali-53.gif ali-53.gif ali-54.gif ali-54.gif ali-55.gif ali-55.gif ali-56.gif ali-56.gif ali-57.gif ali-57.gif ali-58.gif ali-58.gif ali-59.gif ali-59.gif ali-60.gif ali-60.gif ali-61.gif ali-61.gif

回复 1 2023-01-25 13:28:40

1 ali-40.gif ali-40.gif ali-41.gif ali-41.gif ali-42.gif ali-42.gif ali-43.gif ali-43.gif ali-44.gif ali-44.gif ali-45.gif ali-45.gif ali-46.gif ali-46.gif ali-47.gif ali-47.gif ali-48.gif ali-48.gif ali-49.gif ali-49.gif ali-50.gif ali-50.gif ali-51.gif ali-51.gif ali-52.gif ali-52.gif ali-53.gif ali-53.gif ali-54.gif ali-54.gif ali-55.gif ali-55.gif ali-56.gif ali-56.gif ali-57.gif ali-57.gif ali-58.gif ali-58.gif ali-59.gif ali-59.gif ali-60.gif ali-60.gif ali-61.gif ali-61.gif

回复 1 2023-01-25 13:27:18

1 ali-40.gif ali-40.gif ali-41.gif ali-41.gif ali-42.gif ali-42.gif ali-43.gif ali-43.gif ali-44.gif ali-44.gif ali-45.gif ali-45.gif ali-46.gif ali-46.gif ali-47.gif ali-47.gif ali-48.gif ali-48.gif ali-49.gif ali-49.gif ali-50.gif ali-50.gif ali-51.gif ali-51.gif ali-52.gif ali-52.gif ali-53.gif ali-53.gif ali-54.gif ali-54.gif ali-55.gif ali-55.gif ali-56.gif ali-56.gif ali-57.gif ali-57.gif ali-58.gif ali-58.gif ali-59.gif ali-59.gif ali-60.gif ali-60.gif ali-61.gif ali-61.gif

回复 1 2023-01-25 13:27:18

1 ali-40.gif ali-40.gif ali-41.gif ali-41.gif ali-42.gif ali-42.gif ali-43.gif ali-43.gif ali-44.gif ali-44.gif ali-45.gif ali-45.gif ali-46.gif ali-46.gif ali-47.gif ali-47.gif ali-48.gif ali-48.gif ali-49.gif ali-49.gif ali-50.gif ali-50.gif ali-51.gif ali-51.gif ali-52.gif ali-52.gif ali-53.gif ali-53.gif ali-54.gif ali-54.gif ali-55.gif ali-55.gif ali-56.gif ali-56.gif ali-57.gif ali-57.gif ali-58.gif ali-58.gif ali-59.gif ali-59.gif ali-60.gif ali-60.gif ali-61.gif ali-61.gif

回复 取消回复 添加新评论


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有