@ -0,0 +1,2 @@ |
|||||||
|
/node_modules/ |
||||||
|
/uploads/ |
@ -0,0 +1,24 @@ |
|||||||
|
var express = require('express'); |
||||||
|
var multer = require('multer'); |
||||||
|
var upload = multer({ dest: 'uploads/' }); |
||||||
|
var app = express(); |
||||||
|
|
||||||
|
app.use(express.static('static')); |
||||||
|
|
||||||
|
//主页加载
|
||||||
|
app.get('/', function (req, res) { |
||||||
|
res.sendFile(__dirname + "/views/createScheme.html"); |
||||||
|
}); |
||||||
|
|
||||||
|
//接受文件上传,并且返回文件名
|
||||||
|
app.post('/upload', upload.single('file'), function (req, res) { |
||||||
|
//console.info(req.file)
|
||||||
|
res.send(req.file); |
||||||
|
}); |
||||||
|
|
||||||
|
app.get('/files/:filename', function (req, res) { |
||||||
|
var filename = req.params['filename']; |
||||||
|
res.sendFile(__dirname + "/uploads/" + filename); |
||||||
|
}) |
||||||
|
|
||||||
|
app.listen(80); |
@ -0,0 +1,3 @@ |
|||||||
|
{ |
||||||
|
"lockfileVersion": 1 |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
{ |
||||||
|
"name": "3dmodelos", |
||||||
|
"version": "1.0.0", |
||||||
|
"description": "", |
||||||
|
"main": "index.js", |
||||||
|
"scripts": { |
||||||
|
"test": "echo \"Error: no test specified\" && exit 1" |
||||||
|
}, |
||||||
|
"author": "", |
||||||
|
"license": "ISC", |
||||||
|
"dependencies": { |
||||||
|
"express": "^4.16.4", |
||||||
|
"multer": "^1.4.1" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 1.5 MiB |
@ -0,0 +1,266 @@ |
|||||||
|
var renderer, scene, camera; |
||||||
|
|
||||||
|
//整个页面维护的数据
|
||||||
|
var data = { name: '默认方案', components: [] }; |
||||||
|
|
||||||
|
//当前选择的部件
|
||||||
|
var componentIndex = -1; |
||||||
|
|
||||||
|
$().ready(function () { |
||||||
|
initData(); |
||||||
|
initUi(); |
||||||
|
initThree(); |
||||||
|
loadmodel(); |
||||||
|
initEvent(); |
||||||
|
}); |
||||||
|
//初始化Threejs
|
||||||
|
function initThree() { |
||||||
|
initScene(); |
||||||
|
initCamera(); |
||||||
|
initRenderer(); |
||||||
|
render(); |
||||||
|
} |
||||||
|
//获取数据
|
||||||
|
function initData() { |
||||||
|
//todo ajax请求数据
|
||||||
|
} |
||||||
|
//刷新主Ui
|
||||||
|
function initUi() { |
||||||
|
//方案名
|
||||||
|
$('#schemeName').val(data.name); |
||||||
|
//组件列表
|
||||||
|
freshComponentItem(); |
||||||
|
} |
||||||
|
|
||||||
|
function freshComponentItem() { |
||||||
|
//清空原有列表
|
||||||
|
$('.componentItem').remove(); |
||||||
|
for (var index in data.components) { |
||||||
|
//添加一个item并注册了click监听
|
||||||
|
$('#componentList').prepend("<li class='componentItem' onclick='selectComponent(" + index + ")'><a>" + data.components[index].name + "</a></li>"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//选择部件
|
||||||
|
function selectComponent(index) { |
||||||
|
componentIndex = index; |
||||||
|
$('#componentTitle').text(data.components[componentIndex].name); |
||||||
|
$('#delComponent').show(); |
||||||
|
$('#upload').removeClass("disabled"); |
||||||
|
//加载模型列表
|
||||||
|
freshmodelList(); |
||||||
|
} |
||||||
|
|
||||||
|
//选择模型列表
|
||||||
|
function freshmodelList() { |
||||||
|
$('.list-group-item').remove(); |
||||||
|
if (data.components[componentIndex].models.length == 0) { |
||||||
|
$('#modelList').append('<a class="list-group-item">暂无模型</a>') |
||||||
|
} else { |
||||||
|
// if (data.components[componentIndex].modelIndex == -1)
|
||||||
|
// data.components[componentIndex].modelIndex = 0;
|
||||||
|
for (var index in data.components[componentIndex].models) { |
||||||
|
if (index == data.components[componentIndex].modelIndex) { |
||||||
|
data.components[componentIndex].models[index].modelObj.visible = true; |
||||||
|
$('#modelList').append("<a class='list-group-item active' onclick='selectModel(" + index + ")'>" + data.components[componentIndex].models[index].name + "</a>") |
||||||
|
} else { |
||||||
|
data.components[componentIndex].models[index].modelObj.visible = false; |
||||||
|
$('#modelList').append("<a class='list-group-item' onclick='selectModel(" + index + ")'>" + data.components[componentIndex].models[index].name + "</a>") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//选择模型
|
||||||
|
function selectModel(index) { |
||||||
|
data.components[componentIndex].modelIndex = index; |
||||||
|
freshmodelList(); |
||||||
|
} |
||||||
|
|
||||||
|
//初始化模型
|
||||||
|
function loadmodel() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function initScene() { |
||||||
|
//场景设置
|
||||||
|
scene = new THREE.Scene(); |
||||||
|
//设置天空盒
|
||||||
|
scene.background = new THREE.CubeTextureLoader() |
||||||
|
.setPath('/img/skybox/') |
||||||
|
.load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']); |
||||||
|
//场景灯光
|
||||||
|
//环境光
|
||||||
|
var light = new THREE.HemisphereLight(0xffffff, 0x444444); |
||||||
|
light.position.set(0, 2, 0); |
||||||
|
scene.add(light); |
||||||
|
//直射光
|
||||||
|
light = new THREE.DirectionalLight(0xffffff); |
||||||
|
light.position.set(0, 2, 1); |
||||||
|
light.castShadow = true; |
||||||
|
light.shadow.camera.top = 180; |
||||||
|
light.shadow.camera.bottom = - 100; |
||||||
|
light.shadow.camera.left = - 120; |
||||||
|
light.shadow.camera.right = 120; |
||||||
|
scene.add(light); |
||||||
|
//grid
|
||||||
|
var grid = new THREE.GridHelper(20, 20, 0x0000ff, 0xff0000); |
||||||
|
grid.material.opacity = 0.2; |
||||||
|
grid.material.transparent = true; |
||||||
|
scene.add(grid); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function initCamera() { |
||||||
|
//相机设置
|
||||||
|
camera = new THREE.PerspectiveCamera(45, $('#viewField').innerWidth() / $('#viewField').innerHeight()); |
||||||
|
camera.position.set(0, 5, 10); |
||||||
|
//让相机对着场景中央
|
||||||
|
camera.lookAt(scene.position); |
||||||
|
//相机控制,控制的相机和监听的dom
|
||||||
|
controls = new THREE.OrbitControls(camera, $('#viewField')[0]); |
||||||
|
controls.target.set(0, 0, 0); |
||||||
|
controls.update(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function initRenderer() { |
||||||
|
//初始化渲染器
|
||||||
|
renderer = new THREE.WebGLRenderer(); |
||||||
|
//设置像素值
|
||||||
|
renderer.setPixelRatio(window.devicePixelRatio); |
||||||
|
//设置渲染范围为屏幕的大小
|
||||||
|
renderer.setSize($('#viewField').innerWidth(), $('#viewField').innerHeight()); |
||||||
|
//将渲染结果放到页面中
|
||||||
|
$('#viewField').append(renderer.domElement); |
||||||
|
} |
||||||
|
|
||||||
|
function render() { |
||||||
|
requestAnimationFrame(render); |
||||||
|
renderer.render(scene, camera); |
||||||
|
} |
||||||
|
|
||||||
|
//初始化所有事件
|
||||||
|
function initEvent() { |
||||||
|
//方案名变动监听
|
||||||
|
$('#schemeName').change(function () { |
||||||
|
data.name = $('#schemeName').val(); |
||||||
|
}); |
||||||
|
|
||||||
|
//将fileinput事件注册到uploadbtn上
|
||||||
|
$("#upload").click(function () { |
||||||
|
$("#file").click(); |
||||||
|
}); |
||||||
|
|
||||||
|
//只要file发生改变就上传文件
|
||||||
|
$("#file").change(function () { |
||||||
|
if ($(this).val().length > 0) { |
||||||
|
var formData = new FormData($('#uploadForm')[0]); |
||||||
|
$.ajax({ |
||||||
|
type: 'post', |
||||||
|
url: "/upload", |
||||||
|
data: formData, |
||||||
|
cache: false, |
||||||
|
processData: false, |
||||||
|
contentType: false, |
||||||
|
success: function (fileData) { |
||||||
|
//上传成功后加载模型
|
||||||
|
//加载是异步的
|
||||||
|
var addModelItem = function (modelObj) { |
||||||
|
data.components[componentIndex].models.push({ |
||||||
|
name: fileData.originalname, |
||||||
|
fileId: fileData.filename, |
||||||
|
modelObj: modelObj |
||||||
|
}); |
||||||
|
selectModel(data.components[componentIndex].models.length - 1); |
||||||
|
} |
||||||
|
addModel('/files/' + fileData.filename, addModelItem); |
||||||
|
}, |
||||||
|
error: function () { |
||||||
|
alert("上传失败") |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
//当浏览器大小变化时
|
||||||
|
$(window).resize(function () { |
||||||
|
camera.aspect = $('#viewField').innerWidth() / $('#viewField').innerHeight(); |
||||||
|
camera.updateProjectionMatrix(); |
||||||
|
renderer.setSize($('#viewField').innerWidth(), $('#viewField').innerHeight()); |
||||||
|
}); |
||||||
|
|
||||||
|
//当模态框消失的时候清空text
|
||||||
|
$('#addComponentModal').on('hidden.zui.modal', function () { |
||||||
|
$("#componentName").val("") |
||||||
|
}); |
||||||
|
|
||||||
|
//添加一个部件
|
||||||
|
$('#addComponent').click(function () { |
||||||
|
var componentName = $("#componentName").val().trim(); |
||||||
|
if (componentName.length > 0) { |
||||||
|
var component = { |
||||||
|
name: componentName, |
||||||
|
models: [], |
||||||
|
modelIndex: -1 |
||||||
|
} |
||||||
|
data.components.push(component); |
||||||
|
freshComponentItem(); |
||||||
|
$('#addComponentModal').modal('hide'); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
//删除部件
|
||||||
|
$('#delComponent').click(function () { |
||||||
|
new $.zui.Messager('你确定要删除该部件吗,该部件的所有模型将会被清空!', { |
||||||
|
type: 'danger', |
||||||
|
close: false, |
||||||
|
actions: [{ |
||||||
|
icon: 'ok-sign', |
||||||
|
text: '确定', |
||||||
|
action: function () { // 点击该操作按钮的回调函数
|
||||||
|
if (componentIndex >= 0) { |
||||||
|
for (var index in data.components[componentIndex].models) |
||||||
|
scene.remove(data.components[componentIndex].models[index].modelObj); |
||||||
|
data.components.splice(componentIndex, 1); |
||||||
|
freshComponentItem(); |
||||||
|
componentIndex = -1; |
||||||
|
$('#componentTitle').text('请先选择部件'); |
||||||
|
$('#delComponent').hide(); |
||||||
|
$('#upload').addClass("disabled"); |
||||||
|
$('.list-group-item').remove(); |
||||||
|
//todo 还需要发送ajax清空模型文件
|
||||||
|
} |
||||||
|
} |
||||||
|
}] |
||||||
|
}).show(); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function addModel(url, callBack) { |
||||||
|
var map = new THREE.TextureLoader().load('/img/texture/001.jpg'); |
||||||
|
//加载obj模型
|
||||||
|
// loader = new THREE.OBJLoader();
|
||||||
|
// loader.load(url, function (object) {
|
||||||
|
// object.position.set(0, -1, 0);
|
||||||
|
// object.scale.set(0.01, 0.01, 0.01);
|
||||||
|
// scene.add(object);
|
||||||
|
// });
|
||||||
|
//加载fbx模型
|
||||||
|
var loader = new THREE.FBXLoader(); |
||||||
|
loader.load(url, function (object) { |
||||||
|
object.traverse(function (child) { |
||||||
|
if (child instanceof THREE.Mesh) { |
||||||
|
//child.material.map = map;
|
||||||
|
child.material.castShadow = true; |
||||||
|
child.material.receiveShadow = true; |
||||||
|
child.material.needsUpdate = true; |
||||||
|
} |
||||||
|
}); |
||||||
|
scene.add(object); |
||||||
|
callBack(object); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
@ -0,0 +1,797 @@ |
|||||||
|
/** |
||||||
|
* @author mrdoob / http://mrdoob.com/
|
||||||
|
*/ |
||||||
|
|
||||||
|
THREE.OBJLoader = ( function () { |
||||||
|
|
||||||
|
// o object_name | g group_name
|
||||||
|
var object_pattern = /^[og]\s*(.+)?/; |
||||||
|
// mtllib file_reference
|
||||||
|
var material_library_pattern = /^mtllib /; |
||||||
|
// usemtl material_name
|
||||||
|
var material_use_pattern = /^usemtl /; |
||||||
|
|
||||||
|
function ParserState() { |
||||||
|
|
||||||
|
var state = { |
||||||
|
objects: [], |
||||||
|
object: {}, |
||||||
|
|
||||||
|
vertices: [], |
||||||
|
normals: [], |
||||||
|
colors: [], |
||||||
|
uvs: [], |
||||||
|
|
||||||
|
materialLibraries: [], |
||||||
|
|
||||||
|
startObject: function ( name, fromDeclaration ) { |
||||||
|
|
||||||
|
// If the current object (initial from reset) is not from a g/o declaration in the parsed
|
||||||
|
// file. We need to use it for the first parsed g/o to keep things in sync.
|
||||||
|
if ( this.object && this.object.fromDeclaration === false ) { |
||||||
|
|
||||||
|
this.object.name = name; |
||||||
|
this.object.fromDeclaration = ( fromDeclaration !== false ); |
||||||
|
return; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); |
||||||
|
|
||||||
|
if ( this.object && typeof this.object._finalize === 'function' ) { |
||||||
|
|
||||||
|
this.object._finalize( true ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
this.object = { |
||||||
|
name: name || '', |
||||||
|
fromDeclaration: ( fromDeclaration !== false ), |
||||||
|
|
||||||
|
geometry: { |
||||||
|
vertices: [], |
||||||
|
normals: [], |
||||||
|
colors: [], |
||||||
|
uvs: [] |
||||||
|
}, |
||||||
|
materials: [], |
||||||
|
smooth: true, |
||||||
|
|
||||||
|
startMaterial: function ( name, libraries ) { |
||||||
|
|
||||||
|
var previous = this._finalize( false ); |
||||||
|
|
||||||
|
// New usemtl declaration overwrites an inherited material, except if faces were declared
|
||||||
|
// after the material, then it must be preserved for proper MultiMaterial continuation.
|
||||||
|
if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { |
||||||
|
|
||||||
|
this.materials.splice( previous.index, 1 ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
var material = { |
||||||
|
index: this.materials.length, |
||||||
|
name: name || '', |
||||||
|
mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), |
||||||
|
smooth: ( previous !== undefined ? previous.smooth : this.smooth ), |
||||||
|
groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), |
||||||
|
groupEnd: - 1, |
||||||
|
groupCount: - 1, |
||||||
|
inherited: false, |
||||||
|
|
||||||
|
clone: function ( index ) { |
||||||
|
|
||||||
|
var cloned = { |
||||||
|
index: ( typeof index === 'number' ? index : this.index ), |
||||||
|
name: this.name, |
||||||
|
mtllib: this.mtllib, |
||||||
|
smooth: this.smooth, |
||||||
|
groupStart: 0, |
||||||
|
groupEnd: - 1, |
||||||
|
groupCount: - 1, |
||||||
|
inherited: false |
||||||
|
}; |
||||||
|
cloned.clone = this.clone.bind( cloned ); |
||||||
|
return cloned; |
||||||
|
|
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
this.materials.push( material ); |
||||||
|
|
||||||
|
return material; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
currentMaterial: function () { |
||||||
|
|
||||||
|
if ( this.materials.length > 0 ) { |
||||||
|
|
||||||
|
return this.materials[ this.materials.length - 1 ]; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return undefined; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
_finalize: function ( end ) { |
||||||
|
|
||||||
|
var lastMultiMaterial = this.currentMaterial(); |
||||||
|
if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { |
||||||
|
|
||||||
|
lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; |
||||||
|
lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; |
||||||
|
lastMultiMaterial.inherited = false; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// Ignore objects tail materials if no face declarations followed them before a new o/g started.
|
||||||
|
if ( end && this.materials.length > 1 ) { |
||||||
|
|
||||||
|
for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { |
||||||
|
|
||||||
|
if ( this.materials[ mi ].groupCount <= 0 ) { |
||||||
|
|
||||||
|
this.materials.splice( mi, 1 ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// Guarantee at least one empty material, this makes the creation later more straight forward.
|
||||||
|
if ( end && this.materials.length === 0 ) { |
||||||
|
|
||||||
|
this.materials.push( { |
||||||
|
name: '', |
||||||
|
smooth: this.smooth |
||||||
|
} ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return lastMultiMaterial; |
||||||
|
|
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
// Inherit previous objects material.
|
||||||
|
// Spec tells us that a declared material must be set to all objects until a new material is declared.
|
||||||
|
// If a usemtl declaration is encountered while this new object is being parsed, it will
|
||||||
|
// overwrite the inherited material. Exception being that there was already face declarations
|
||||||
|
// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
|
||||||
|
|
||||||
|
if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { |
||||||
|
|
||||||
|
var declared = previousMaterial.clone( 0 ); |
||||||
|
declared.inherited = true; |
||||||
|
this.object.materials.push( declared ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
this.objects.push( this.object ); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
finalize: function () { |
||||||
|
|
||||||
|
if ( this.object && typeof this.object._finalize === 'function' ) { |
||||||
|
|
||||||
|
this.object._finalize( true ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
parseVertexIndex: function ( value, len ) { |
||||||
|
|
||||||
|
var index = parseInt( value, 10 ); |
||||||
|
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
parseNormalIndex: function ( value, len ) { |
||||||
|
|
||||||
|
var index = parseInt( value, 10 ); |
||||||
|
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
parseUVIndex: function ( value, len ) { |
||||||
|
|
||||||
|
var index = parseInt( value, 10 ); |
||||||
|
return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addVertex: function ( a, b, c ) { |
||||||
|
|
||||||
|
var src = this.vertices; |
||||||
|
var dst = this.object.geometry.vertices; |
||||||
|
|
||||||
|
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||||
|
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); |
||||||
|
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addVertexPoint: function ( a ) { |
||||||
|
|
||||||
|
var src = this.vertices; |
||||||
|
var dst = this.object.geometry.vertices; |
||||||
|
|
||||||
|
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addVertexLine: function ( a ) { |
||||||
|
|
||||||
|
var src = this.vertices; |
||||||
|
var dst = this.object.geometry.vertices; |
||||||
|
|
||||||
|
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addNormal: function ( a, b, c ) { |
||||||
|
|
||||||
|
var src = this.normals; |
||||||
|
var dst = this.object.geometry.normals; |
||||||
|
|
||||||
|
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||||
|
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); |
||||||
|
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addColor: function ( a, b, c ) { |
||||||
|
|
||||||
|
var src = this.colors; |
||||||
|
var dst = this.object.geometry.colors; |
||||||
|
|
||||||
|
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||||
|
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); |
||||||
|
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addUV: function ( a, b, c ) { |
||||||
|
|
||||||
|
var src = this.uvs; |
||||||
|
var dst = this.object.geometry.uvs; |
||||||
|
|
||||||
|
dst.push( src[ a + 0 ], src[ a + 1 ] ); |
||||||
|
dst.push( src[ b + 0 ], src[ b + 1 ] ); |
||||||
|
dst.push( src[ c + 0 ], src[ c + 1 ] ); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addUVLine: function ( a ) { |
||||||
|
|
||||||
|
var src = this.uvs; |
||||||
|
var dst = this.object.geometry.uvs; |
||||||
|
|
||||||
|
dst.push( src[ a + 0 ], src[ a + 1 ] ); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { |
||||||
|
|
||||||
|
var vLen = this.vertices.length; |
||||||
|
|
||||||
|
var ia = this.parseVertexIndex( a, vLen ); |
||||||
|
var ib = this.parseVertexIndex( b, vLen ); |
||||||
|
var ic = this.parseVertexIndex( c, vLen ); |
||||||
|
|
||||||
|
this.addVertex( ia, ib, ic ); |
||||||
|
|
||||||
|
if ( ua !== undefined && ua !== '' ) { |
||||||
|
|
||||||
|
var uvLen = this.uvs.length; |
||||||
|
ia = this.parseUVIndex( ua, uvLen ); |
||||||
|
ib = this.parseUVIndex( ub, uvLen ); |
||||||
|
ic = this.parseUVIndex( uc, uvLen ); |
||||||
|
this.addUV( ia, ib, ic ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if ( na !== undefined && na !== '' ) { |
||||||
|
|
||||||
|
// Normals are many times the same. If so, skip function call and parseInt.
|
||||||
|
var nLen = this.normals.length; |
||||||
|
ia = this.parseNormalIndex( na, nLen ); |
||||||
|
|
||||||
|
ib = na === nb ? ia : this.parseNormalIndex( nb, nLen ); |
||||||
|
ic = na === nc ? ia : this.parseNormalIndex( nc, nLen ); |
||||||
|
|
||||||
|
this.addNormal( ia, ib, ic ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if ( this.colors.length > 0 ) { |
||||||
|
|
||||||
|
this.addColor( ia, ib, ic ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addPointGeometry: function ( vertices ) { |
||||||
|
|
||||||
|
this.object.geometry.type = 'Points'; |
||||||
|
|
||||||
|
var vLen = this.vertices.length; |
||||||
|
|
||||||
|
for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { |
||||||
|
|
||||||
|
this.addVertexPoint( this.parseVertexIndex( vertices[ vi ], vLen ) ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
addLineGeometry: function ( vertices, uvs ) { |
||||||
|
|
||||||
|
this.object.geometry.type = 'Line'; |
||||||
|
|
||||||
|
var vLen = this.vertices.length; |
||||||
|
var uvLen = this.uvs.length; |
||||||
|
|
||||||
|
for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { |
||||||
|
|
||||||
|
this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { |
||||||
|
|
||||||
|
this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
state.startObject( '', false ); |
||||||
|
|
||||||
|
return state; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
function OBJLoader( manager ) { |
||||||
|
|
||||||
|
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; |
||||||
|
|
||||||
|
this.materials = null; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
OBJLoader.prototype = { |
||||||
|
|
||||||
|
constructor: OBJLoader, |
||||||
|
|
||||||
|
load: function ( url, onLoad, onProgress, onError ) { |
||||||
|
|
||||||
|
var scope = this; |
||||||
|
|
||||||
|
var loader = new THREE.FileLoader( scope.manager ); |
||||||
|
loader.setPath( this.path ); |
||||||
|
loader.load( url, function ( text ) { |
||||||
|
|
||||||
|
onLoad( scope.parse( text ) ); |
||||||
|
|
||||||
|
}, onProgress, onError ); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
setPath: function ( value ) { |
||||||
|
|
||||||
|
this.path = value; |
||||||
|
|
||||||
|
return this; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
setMaterials: function ( materials ) { |
||||||
|
|
||||||
|
this.materials = materials; |
||||||
|
|
||||||
|
return this; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
parse: function ( text ) { |
||||||
|
|
||||||
|
console.time( 'OBJLoader' ); |
||||||
|
|
||||||
|
var state = new ParserState(); |
||||||
|
|
||||||
|
if ( text.indexOf( '\r\n' ) !== - 1 ) { |
||||||
|
|
||||||
|
// This is faster than String.split with regex that splits on both
|
||||||
|
text = text.replace( /\r\n/g, '\n' ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if ( text.indexOf( '\\\n' ) !== - 1 ) { |
||||||
|
|
||||||
|
// join lines separated by a line continuation character (\)
|
||||||
|
text = text.replace( /\\\n/g, '' ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
var lines = text.split( '\n' ); |
||||||
|
var line = '', lineFirstChar = ''; |
||||||
|
var lineLength = 0; |
||||||
|
var result = []; |
||||||
|
|
||||||
|
// Faster to just trim left side of the line. Use if available.
|
||||||
|
var trimLeft = ( typeof ''.trimLeft === 'function' ); |
||||||
|
|
||||||
|
for ( var i = 0, l = lines.length; i < l; i ++ ) { |
||||||
|
|
||||||
|
line = lines[ i ]; |
||||||
|
|
||||||
|
line = trimLeft ? line.trimLeft() : line.trim(); |
||||||
|
|
||||||
|
lineLength = line.length; |
||||||
|
|
||||||
|
if ( lineLength === 0 ) continue; |
||||||
|
|
||||||
|
lineFirstChar = line.charAt( 0 ); |
||||||
|
|
||||||
|
// @todo invoke passed in handler if any
|
||||||
|
if ( lineFirstChar === '#' ) continue; |
||||||
|
|
||||||
|
if ( lineFirstChar === 'v' ) { |
||||||
|
|
||||||
|
var data = line.split( /\s+/ ); |
||||||
|
|
||||||
|
switch ( data[ 0 ] ) { |
||||||
|
|
||||||
|
case 'v': |
||||||
|
state.vertices.push( |
||||||
|
parseFloat( data[ 1 ] ), |
||||||
|
parseFloat( data[ 2 ] ), |
||||||
|
parseFloat( data[ 3 ] ) |
||||||
|
); |
||||||
|
if ( data.length === 8 ) { |
||||||
|
|
||||||
|
state.colors.push( |
||||||
|
parseFloat( data[ 4 ] ), |
||||||
|
parseFloat( data[ 5 ] ), |
||||||
|
parseFloat( data[ 6 ] ) |
||||||
|
|
||||||
|
); |
||||||
|
|
||||||
|
} |
||||||
|
break; |
||||||
|
case 'vn': |
||||||
|
state.normals.push( |
||||||
|
parseFloat( data[ 1 ] ), |
||||||
|
parseFloat( data[ 2 ] ), |
||||||
|
parseFloat( data[ 3 ] ) |
||||||
|
); |
||||||
|
break; |
||||||
|
case 'vt': |
||||||
|
state.uvs.push( |
||||||
|
parseFloat( data[ 1 ] ), |
||||||
|
parseFloat( data[ 2 ] ) |
||||||
|
); |
||||||
|
break; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} else if ( lineFirstChar === 'f' ) { |
||||||
|
|
||||||
|
var lineData = line.substr( 1 ).trim(); |
||||||
|
var vertexData = lineData.split( /\s+/ ); |
||||||
|
var faceVertices = []; |
||||||
|
|
||||||
|
// Parse the face vertex data into an easy to work with format
|
||||||
|
|
||||||
|
for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { |
||||||
|
|
||||||
|
var vertex = vertexData[ j ]; |
||||||
|
|
||||||
|
if ( vertex.length > 0 ) { |
||||||
|
|
||||||
|
var vertexParts = vertex.split( '/' ); |
||||||
|
faceVertices.push( vertexParts ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// Draw an edge between the first vertex and all subsequent vertices to form an n-gon
|
||||||
|
|
||||||
|
var v1 = faceVertices[ 0 ]; |
||||||
|
|
||||||
|
for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { |
||||||
|
|
||||||
|
var v2 = faceVertices[ j ]; |
||||||
|
var v3 = faceVertices[ j + 1 ]; |
||||||
|
|
||||||
|
state.addFace( |
||||||
|
v1[ 0 ], v2[ 0 ], v3[ 0 ], |
||||||
|
v1[ 1 ], v2[ 1 ], v3[ 1 ], |
||||||
|
v1[ 2 ], v2[ 2 ], v3[ 2 ] |
||||||
|
); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} else if ( lineFirstChar === 'l' ) { |
||||||
|
|
||||||
|
var lineParts = line.substring( 1 ).trim().split( " " ); |
||||||
|
var lineVertices = [], lineUVs = []; |
||||||
|
|
||||||
|
if ( line.indexOf( "/" ) === - 1 ) { |
||||||
|
|
||||||
|
lineVertices = lineParts; |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { |
||||||
|
|
||||||
|
var parts = lineParts[ li ].split( "/" ); |
||||||
|
|
||||||
|
if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] ); |
||||||
|
if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
state.addLineGeometry( lineVertices, lineUVs ); |
||||||
|
|
||||||
|
} else if ( lineFirstChar === 'p' ) { |
||||||
|
|
||||||
|
var lineData = line.substr( 1 ).trim(); |
||||||
|
var pointData = lineData.split( " " ); |
||||||
|
|
||||||
|
state.addPointGeometry( pointData ); |
||||||
|
|
||||||
|
} else if ( ( result = object_pattern.exec( line ) ) !== null ) { |
||||||
|
|
||||||
|
// o object_name
|
||||||
|
// or
|
||||||
|
// g group_name
|
||||||
|
|
||||||
|
// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
|
||||||
|
// var name = result[ 0 ].substr( 1 ).trim();
|
||||||
|
var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); |
||||||
|
|
||||||
|
state.startObject( name ); |
||||||
|
|
||||||
|
} else if ( material_use_pattern.test( line ) ) { |
||||||
|
|
||||||
|
// material
|
||||||
|
|
||||||
|
state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); |
||||||
|
|
||||||
|
} else if ( material_library_pattern.test( line ) ) { |
||||||
|
|
||||||
|
// mtl file
|
||||||
|
|
||||||
|
state.materialLibraries.push( line.substring( 7 ).trim() ); |
||||||
|
|
||||||
|
} else if ( lineFirstChar === 's' ) { |
||||||
|
|
||||||
|
result = line.split( ' ' ); |
||||||
|
|
||||||
|
// smooth shading
|
||||||
|
|
||||||
|
// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
|
||||||
|
// but does not define a usemtl for each face set.
|
||||||
|
// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
|
||||||
|
// This requires some care to not create extra material on each smooth value for "normal" obj files.
|
||||||
|
// where explicit usemtl defines geometry groups.
|
||||||
|
// Example asset: examples/models/obj/cerberus/Cerberus.obj
|
||||||
|
|
||||||
|
/* |
||||||
|
* http://paulbourke.net/dataformats/obj/
|
||||||
|
* or |
||||||
|
* http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
|
||||||
|
* |
||||||
|
* From chapter "Grouping" Syntax explanation "s group_number": |
||||||
|
* "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. |
||||||
|
* Polygonal elements use group numbers to put elements in different smoothing groups. For free-form |
||||||
|
* surfaces, smoothing groups are either turned on or off; there is no difference between values greater |
||||||
|
* than 0." |
||||||
|
*/ |
||||||
|
if ( result.length > 1 ) { |
||||||
|
|
||||||
|
var value = result[ 1 ].trim().toLowerCase(); |
||||||
|
state.object.smooth = ( value !== '0' && value !== 'off' ); |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
// ZBrush can produce "s" lines #11707
|
||||||
|
state.object.smooth = true; |
||||||
|
|
||||||
|
} |
||||||
|
var material = state.object.currentMaterial(); |
||||||
|
if ( material ) material.smooth = state.object.smooth; |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
// Handle null terminated files without exception
|
||||||
|
if ( line === '\0' ) continue; |
||||||
|
|
||||||
|
throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
state.finalize(); |
||||||
|
|
||||||
|
var container = new THREE.Group(); |
||||||
|
container.materialLibraries = [].concat( state.materialLibraries ); |
||||||
|
|
||||||
|
for ( var i = 0, l = state.objects.length; i < l; i ++ ) { |
||||||
|
|
||||||
|
var object = state.objects[ i ]; |
||||||
|
var geometry = object.geometry; |
||||||
|
var materials = object.materials; |
||||||
|
var isLine = ( geometry.type === 'Line' ); |
||||||
|
var isPoints = ( geometry.type === 'Points' ); |
||||||
|
var hasVertexColors = false; |
||||||
|
|
||||||
|
// Skip o/g line declarations that did not follow with any faces
|
||||||
|
if ( geometry.vertices.length === 0 ) continue; |
||||||
|
|
||||||
|
var buffergeometry = new THREE.BufferGeometry(); |
||||||
|
|
||||||
|
buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); |
||||||
|
|
||||||
|
if ( geometry.normals.length > 0 ) { |
||||||
|
|
||||||
|
buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
buffergeometry.computeVertexNormals(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if ( geometry.colors.length > 0 ) { |
||||||
|
|
||||||
|
hasVertexColors = true; |
||||||
|
buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if ( geometry.uvs.length > 0 ) { |
||||||
|
|
||||||
|
buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// Create materials
|
||||||
|
|
||||||
|
var createdMaterials = []; |
||||||
|
|
||||||
|
for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { |
||||||
|
|
||||||
|
var sourceMaterial = materials[ mi ]; |
||||||
|
var material = undefined; |
||||||
|
|
||||||
|
if ( this.materials !== null ) { |
||||||
|
|
||||||
|
material = this.materials.create( sourceMaterial.name ); |
||||||
|
|
||||||
|
// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
|
||||||
|
if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { |
||||||
|
|
||||||
|
var materialLine = new THREE.LineBasicMaterial(); |
||||||
|
THREE.Material.prototype.copy.call( materialLine, material ); |
||||||
|
materialLine.color.copy( material.color ); |
||||||
|
materialLine.lights = false; |
||||||
|
material = materialLine; |
||||||
|
|
||||||
|
} else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) { |
||||||
|
|
||||||
|
var materialPoints = new THREE.PointsMaterial( { size: 10, sizeAttenuation: false } ); |
||||||
|
THREE.Material.prototype.copy.call( materialPoints, material ); |
||||||
|
materialPoints.color.copy( material.color ); |
||||||
|
materialPoints.map = material.map; |
||||||
|
materialPoints.lights = false; |
||||||
|
material = materialPoints; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if ( ! material ) { |
||||||
|
|
||||||
|
if ( isLine ) { |
||||||
|
|
||||||
|
material = new THREE.LineBasicMaterial(); |
||||||
|
|
||||||
|
} else if ( isPoints ) { |
||||||
|
|
||||||
|
material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } ); |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
material = new THREE.MeshPhongMaterial(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
material.name = sourceMaterial.name; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
material.flatShading = sourceMaterial.smooth ? false : true; |
||||||
|
material.vertexColors = hasVertexColors ? THREE.VertexColors : THREE.NoColors; |
||||||
|
|
||||||
|
createdMaterials.push( material ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// Create mesh
|
||||||
|
|
||||||
|
var mesh; |
||||||
|
|
||||||
|
if ( createdMaterials.length > 1 ) { |
||||||
|
|
||||||
|
for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { |
||||||
|
|
||||||
|
var sourceMaterial = materials[ mi ]; |
||||||
|
buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if ( isLine ) { |
||||||
|
|
||||||
|
mesh = new THREE.LineSegments( buffergeometry, createdMaterials ); |
||||||
|
|
||||||
|
} else if ( isPoints ) { |
||||||
|
|
||||||
|
mesh = new THREE.Points( buffergeometry, createdMaterials ); |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
mesh = new THREE.Mesh( buffergeometry, createdMaterials ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
if ( isLine ) { |
||||||
|
|
||||||
|
mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ); |
||||||
|
|
||||||
|
} else if ( isPoints ) { |
||||||
|
|
||||||
|
mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] ); |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
mesh.name = object.name; |
||||||
|
|
||||||
|
container.add( mesh ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
console.timeEnd( 'OBJLoader' ); |
||||||
|
|
||||||
|
return container; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
return OBJLoader; |
||||||
|
|
||||||
|
} )(); |
@ -0,0 +1,548 @@ |
|||||||
|
/* |
||||||
|
* @author Daosheng Mu / https://github.com/DaoshengMu/
|
||||||
|
* @author mrdoob / http://mrdoob.com/
|
||||||
|
* @author takahirox / https://github.com/takahirox/
|
||||||
|
*/ |
||||||
|
|
||||||
|
THREE.TGALoader = function ( manager ) { |
||||||
|
|
||||||
|
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
THREE.TGALoader.prototype = { |
||||||
|
|
||||||
|
constructor: THREE.TGALoader, |
||||||
|
|
||||||
|
load: function ( url, onLoad, onProgress, onError ) { |
||||||
|
|
||||||
|
var scope = this; |
||||||
|
|
||||||
|
var texture = new THREE.Texture(); |
||||||
|
|
||||||
|
var loader = new THREE.FileLoader( this.manager ); |
||||||
|
loader.setResponseType( 'arraybuffer' ); |
||||||
|
loader.setPath( this.path ); |
||||||
|
|
||||||
|
loader.load( url, function ( buffer ) { |
||||||
|
|
||||||
|
texture.image = scope.parse( buffer ); |
||||||
|
texture.needsUpdate = true; |
||||||
|
|
||||||
|
if ( onLoad !== undefined ) { |
||||||
|
|
||||||
|
onLoad( texture ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}, onProgress, onError ); |
||||||
|
|
||||||
|
return texture; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
parse: function ( buffer ) { |
||||||
|
|
||||||
|
// reference from vthibault, https://github.com/vthibault/roBrowser/blob/master/src/Loaders/Targa.js
|
||||||
|
|
||||||
|
function tgaCheckHeader( header ) { |
||||||
|
|
||||||
|
switch ( header.image_type ) { |
||||||
|
|
||||||
|
// check indexed type
|
||||||
|
|
||||||
|
case TGA_TYPE_INDEXED: |
||||||
|
case TGA_TYPE_RLE_INDEXED: |
||||||
|
if ( header.colormap_length > 256 || header.colormap_size !== 24 || header.colormap_type !== 1 ) { |
||||||
|
|
||||||
|
console.error( 'THREE.TGALoader: Invalid type colormap data for indexed type.' ); |
||||||
|
|
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
// check colormap type
|
||||||
|
|
||||||
|
case TGA_TYPE_RGB: |
||||||
|
case TGA_TYPE_GREY: |
||||||
|
case TGA_TYPE_RLE_RGB: |
||||||
|
case TGA_TYPE_RLE_GREY: |
||||||
|
if ( header.colormap_type ) { |
||||||
|
|
||||||
|
console.error( 'THREE.TGALoader: Invalid type colormap data for colormap type.' ); |
||||||
|
|
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
// What the need of a file without data ?
|
||||||
|
|
||||||
|
case TGA_TYPE_NO_DATA: |
||||||
|
console.error( 'THREE.TGALoader: No data.' ); |
||||||
|
|
||||||
|
// Invalid type ?
|
||||||
|
|
||||||
|
default: |
||||||
|
console.error( 'THREE.TGALoader: Invalid type "%s".', header.image_type ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// check image width and height
|
||||||
|
|
||||||
|
if ( header.width <= 0 || header.height <= 0 ) { |
||||||
|
|
||||||
|
console.error( 'THREE.TGALoader: Invalid image size.' ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// check image pixel size
|
||||||
|
|
||||||
|
if ( header.pixel_size !== 8 && header.pixel_size !== 16 && |
||||||
|
header.pixel_size !== 24 && header.pixel_size !== 32 ) { |
||||||
|
|
||||||
|
console.error( 'THREE.TGALoader: Invalid pixel size "%s".', header.pixel_size ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// parse tga image buffer
|
||||||
|
|
||||||
|
function tgaParse( use_rle, use_pal, header, offset, data ) { |
||||||
|
|
||||||
|
var pixel_data, |
||||||
|
pixel_size, |
||||||
|
pixel_total, |
||||||
|
palettes; |
||||||
|
|
||||||
|
pixel_size = header.pixel_size >> 3; |
||||||
|
pixel_total = header.width * header.height * pixel_size; |
||||||
|
|
||||||
|
// read palettes
|
||||||
|
|
||||||
|
if ( use_pal ) { |
||||||
|
|
||||||
|
palettes = data.subarray( offset, offset += header.colormap_length * ( header.colormap_size >> 3 ) ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// read RLE
|
||||||
|
|
||||||
|
if ( use_rle ) { |
||||||
|
|
||||||
|
pixel_data = new Uint8Array( pixel_total ); |
||||||
|
|
||||||
|
var c, count, i; |
||||||
|
var shift = 0; |
||||||
|
var pixels = new Uint8Array( pixel_size ); |
||||||
|
|
||||||
|
while ( shift < pixel_total ) { |
||||||
|
|
||||||
|
c = data[ offset ++ ]; |
||||||
|
count = ( c & 0x7f ) + 1; |
||||||
|
|
||||||
|
// RLE pixels
|
||||||
|
|
||||||
|
if ( c & 0x80 ) { |
||||||
|
|
||||||
|
// bind pixel tmp array
|
||||||
|
|
||||||
|
for ( i = 0; i < pixel_size; ++ i ) { |
||||||
|
|
||||||
|
pixels[ i ] = data[ offset ++ ]; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// copy pixel array
|
||||||
|
|
||||||
|
for ( i = 0; i < count; ++ i ) { |
||||||
|
|
||||||
|
pixel_data.set( pixels, shift + i * pixel_size ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
shift += pixel_size * count; |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
// raw pixels
|
||||||
|
|
||||||
|
count *= pixel_size; |
||||||
|
for ( i = 0; i < count; ++ i ) { |
||||||
|
|
||||||
|
pixel_data[ shift + i ] = data[ offset ++ ]; |
||||||
|
|
||||||
|
} |
||||||
|
shift += count; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
// raw pixels
|
||||||
|
|
||||||
|
pixel_data = data.subarray( |
||||||
|
offset, offset += ( use_pal ? header.width * header.height : pixel_total ) |
||||||
|
); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
pixel_data: pixel_data, |
||||||
|
palettes: palettes |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function tgaGetImageData8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image, palettes ) { |
||||||
|
|
||||||
|
var colormap = palettes; |
||||||
|
var color, i = 0, x, y; |
||||||
|
var width = header.width; |
||||||
|
|
||||||
|
for ( y = y_start; y !== y_end; y += y_step ) { |
||||||
|
|
||||||
|
for ( x = x_start; x !== x_end; x += x_step, i ++ ) { |
||||||
|
|
||||||
|
color = image[ i ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 3 ] = 255; |
||||||
|
imageData[ ( x + width * y ) * 4 + 2 ] = colormap[ ( color * 3 ) + 0 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 1 ] = colormap[ ( color * 3 ) + 1 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 0 ] = colormap[ ( color * 3 ) + 2 ]; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return imageData; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function tgaGetImageData16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { |
||||||
|
|
||||||
|
var color, i = 0, x, y; |
||||||
|
var width = header.width; |
||||||
|
|
||||||
|
for ( y = y_start; y !== y_end; y += y_step ) { |
||||||
|
|
||||||
|
for ( x = x_start; x !== x_end; x += x_step, i += 2 ) { |
||||||
|
|
||||||
|
color = image[ i + 0 ] + ( image[ i + 1 ] << 8 ); // Inversed ?
|
||||||
|
imageData[ ( x + width * y ) * 4 + 0 ] = ( color & 0x7C00 ) >> 7; |
||||||
|
imageData[ ( x + width * y ) * 4 + 1 ] = ( color & 0x03E0 ) >> 2; |
||||||
|
imageData[ ( x + width * y ) * 4 + 2 ] = ( color & 0x001F ) >> 3; |
||||||
|
imageData[ ( x + width * y ) * 4 + 3 ] = ( color & 0x8000 ) ? 0 : 255; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return imageData; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function tgaGetImageData24bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { |
||||||
|
|
||||||
|
var i = 0, x, y; |
||||||
|
var width = header.width; |
||||||
|
|
||||||
|
for ( y = y_start; y !== y_end; y += y_step ) { |
||||||
|
|
||||||
|
for ( x = x_start; x !== x_end; x += x_step, i += 3 ) { |
||||||
|
|
||||||
|
imageData[ ( x + width * y ) * 4 + 3 ] = 255; |
||||||
|
imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ]; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return imageData; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function tgaGetImageData32bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { |
||||||
|
|
||||||
|
var i = 0, x, y; |
||||||
|
var width = header.width; |
||||||
|
|
||||||
|
for ( y = y_start; y !== y_end; y += y_step ) { |
||||||
|
|
||||||
|
for ( x = x_start; x !== x_end; x += x_step, i += 4 ) { |
||||||
|
|
||||||
|
imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 3 ]; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return imageData; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function tgaGetImageDataGrey8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { |
||||||
|
|
||||||
|
var color, i = 0, x, y; |
||||||
|
var width = header.width; |
||||||
|
|
||||||
|
for ( y = y_start; y !== y_end; y += y_step ) { |
||||||
|
|
||||||
|
for ( x = x_start; x !== x_end; x += x_step, i ++ ) { |
||||||
|
|
||||||
|
color = image[ i ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 0 ] = color; |
||||||
|
imageData[ ( x + width * y ) * 4 + 1 ] = color; |
||||||
|
imageData[ ( x + width * y ) * 4 + 2 ] = color; |
||||||
|
imageData[ ( x + width * y ) * 4 + 3 ] = 255; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return imageData; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function tgaGetImageDataGrey16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { |
||||||
|
|
||||||
|
var i = 0, x, y; |
||||||
|
var width = header.width; |
||||||
|
|
||||||
|
for ( y = y_start; y !== y_end; y += y_step ) { |
||||||
|
|
||||||
|
for ( x = x_start; x !== x_end; x += x_step, i += 2 ) { |
||||||
|
|
||||||
|
imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 0 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 0 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; |
||||||
|
imageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 1 ]; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return imageData; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function getTgaRGBA( data, width, height, image, palette ) { |
||||||
|
|
||||||
|
var x_start, |
||||||
|
y_start, |
||||||
|
x_step, |
||||||
|
y_step, |
||||||
|
x_end, |
||||||
|
y_end; |
||||||
|
|
||||||
|
switch ( ( header.flags & TGA_ORIGIN_MASK ) >> TGA_ORIGIN_SHIFT ) { |
||||||
|
|
||||||
|
default: |
||||||
|
case TGA_ORIGIN_UL: |
||||||
|
x_start = 0; |
||||||
|
x_step = 1; |
||||||
|
x_end = width; |
||||||
|
y_start = 0; |
||||||
|
y_step = 1; |
||||||
|
y_end = height; |
||||||
|
break; |
||||||
|
|
||||||
|
case TGA_ORIGIN_BL: |
||||||
|
x_start = 0; |
||||||
|
x_step = 1; |
||||||
|
x_end = width; |
||||||
|
y_start = height - 1; |
||||||
|
y_step = - 1; |
||||||
|
y_end = - 1; |
||||||
|
break; |
||||||
|
|
||||||
|
case TGA_ORIGIN_UR: |
||||||
|
x_start = width - 1; |
||||||
|
x_step = - 1; |
||||||
|
x_end = - 1; |
||||||
|
y_start = 0; |
||||||
|
y_step = 1; |
||||||
|
y_end = height; |
||||||
|
break; |
||||||
|
|
||||||
|
case TGA_ORIGIN_BR: |
||||||
|
x_start = width - 1; |
||||||
|
x_step = - 1; |
||||||
|
x_end = - 1; |
||||||
|
y_start = height - 1; |
||||||
|
y_step = - 1; |
||||||
|
y_end = - 1; |
||||||
|
break; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if ( use_grey ) { |
||||||
|
|
||||||
|
switch ( header.pixel_size ) { |
||||||
|
|
||||||
|
case 8: |
||||||
|
tgaGetImageDataGrey8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); |
||||||
|
break; |
||||||
|
|
||||||
|
case 16: |
||||||
|
tgaGetImageDataGrey16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
console.error( 'THREE.TGALoader: Format not supported.' ); |
||||||
|
break; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
switch ( header.pixel_size ) { |
||||||
|
|
||||||
|
case 8: |
||||||
|
tgaGetImageData8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image, palette ); |
||||||
|
break; |
||||||
|
|
||||||
|
case 16: |
||||||
|
tgaGetImageData16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); |
||||||
|
break; |
||||||
|
|
||||||
|
case 24: |
||||||
|
tgaGetImageData24bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); |
||||||
|
break; |
||||||
|
|
||||||
|
case 32: |
||||||
|
tgaGetImageData32bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
console.error( 'THREE.TGALoader: Format not supported.' ); |
||||||
|
break; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// Load image data according to specific method
|
||||||
|
// var func = 'tgaGetImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits';
|
||||||
|
// func(data, y_start, y_step, y_end, x_start, x_step, x_end, width, image, palette );
|
||||||
|
return data; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// TGA constants
|
||||||
|
|
||||||
|
var TGA_TYPE_NO_DATA = 0, |
||||||
|
TGA_TYPE_INDEXED = 1, |
||||||
|
TGA_TYPE_RGB = 2, |
||||||
|
TGA_TYPE_GREY = 3, |
||||||
|
TGA_TYPE_RLE_INDEXED = 9, |
||||||
|
TGA_TYPE_RLE_RGB = 10, |
||||||
|
TGA_TYPE_RLE_GREY = 11, |
||||||
|
|
||||||
|
TGA_ORIGIN_MASK = 0x30, |
||||||
|
TGA_ORIGIN_SHIFT = 0x04, |
||||||
|
TGA_ORIGIN_BL = 0x00, |
||||||
|
TGA_ORIGIN_BR = 0x01, |
||||||
|
TGA_ORIGIN_UL = 0x02, |
||||||
|
TGA_ORIGIN_UR = 0x03; |
||||||
|
|
||||||
|
if ( buffer.length < 19 ) console.error( 'THREE.TGALoader: Not enough data to contain header.' ); |
||||||
|
|
||||||
|
var content = new Uint8Array( buffer ), |
||||||
|
offset = 0, |
||||||
|
header = { |
||||||
|
id_length: content[ offset ++ ], |
||||||
|
colormap_type: content[ offset ++ ], |
||||||
|
image_type: content[ offset ++ ], |
||||||
|
colormap_index: content[ offset ++ ] | content[ offset ++ ] << 8, |
||||||
|
colormap_length: content[ offset ++ ] | content[ offset ++ ] << 8, |
||||||
|
colormap_size: content[ offset ++ ], |
||||||
|
origin: [ |
||||||
|
content[ offset ++ ] | content[ offset ++ ] << 8, |
||||||
|
content[ offset ++ ] | content[ offset ++ ] << 8 |
||||||
|
], |
||||||
|
width: content[ offset ++ ] | content[ offset ++ ] << 8, |
||||||
|
height: content[ offset ++ ] | content[ offset ++ ] << 8, |
||||||
|
pixel_size: content[ offset ++ ], |
||||||
|
flags: content[ offset ++ ] |
||||||
|
}; |
||||||
|
|
||||||
|
// check tga if it is valid format
|
||||||
|
|
||||||
|
tgaCheckHeader( header ); |
||||||
|
|
||||||
|
if ( header.id_length + offset > buffer.length ) { |
||||||
|
|
||||||
|
console.error( 'THREE.TGALoader: No data.' ); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// skip the needn't data
|
||||||
|
|
||||||
|
offset += header.id_length; |
||||||
|
|
||||||
|
// get targa information about RLE compression and palette
|
||||||
|
|
||||||
|
var use_rle = false, |
||||||
|
use_pal = false, |
||||||
|
use_grey = false; |
||||||
|
|
||||||
|
switch ( header.image_type ) { |
||||||
|
|
||||||
|
case TGA_TYPE_RLE_INDEXED: |
||||||
|
use_rle = true; |
||||||
|
use_pal = true; |
||||||
|
break; |
||||||
|
|
||||||
|
case TGA_TYPE_INDEXED: |
||||||
|
use_pal = true; |
||||||
|
break; |
||||||
|
|
||||||
|
case TGA_TYPE_RLE_RGB: |
||||||
|
use_rle = true; |
||||||
|
break; |
||||||
|
|
||||||
|
case TGA_TYPE_RGB: |
||||||
|
break; |
||||||
|
|
||||||
|
case TGA_TYPE_RLE_GREY: |
||||||
|
use_rle = true; |
||||||
|
use_grey = true; |
||||||
|
break; |
||||||
|
|
||||||
|
case TGA_TYPE_GREY: |
||||||
|
use_grey = true; |
||||||
|
break; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
var canvas = document.createElement( 'canvas' ); |
||||||
|
canvas.width = header.width; |
||||||
|
canvas.height = header.height; |
||||||
|
|
||||||
|
var context = canvas.getContext( '2d' ); |
||||||
|
var imageData = context.createImageData( header.width, header.height ); |
||||||
|
|
||||||
|
var result = tgaParse( use_rle, use_pal, header, offset, content ); |
||||||
|
var rgbaData = getTgaRGBA( imageData.data, header.width, header.height, result.pixel_data, result.palettes ); |
||||||
|
|
||||||
|
context.putImageData( imageData, 0, 0 ); |
||||||
|
|
||||||
|
return canvas; |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
setPath: function ( value ) { |
||||||
|
|
||||||
|
this.path = value; |
||||||
|
return this; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}; |
@ -0,0 +1,15 @@ |
|||||||
|
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var l=void 0,aa=this;function r(c,d){var a=c.split("."),b=aa;!(a[0]in b)&&b.execScript&&b.execScript("var "+a[0]);for(var e;a.length&&(e=a.shift());)!a.length&&d!==l?b[e]=d:b=b[e]?b[e]:b[e]={}};var t="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function v(c){var d=c.length,a=0,b=Number.POSITIVE_INFINITY,e,f,g,h,k,m,n,p,s,x;for(p=0;p<d;++p)c[p]>a&&(a=c[p]),c[p]<b&&(b=c[p]);e=1<<a;f=new (t?Uint32Array:Array)(e);g=1;h=0;for(k=2;g<=a;){for(p=0;p<d;++p)if(c[p]===g){m=0;n=h;for(s=0;s<g;++s)m=m<<1|n&1,n>>=1;x=g<<16|p;for(s=m;s<e;s+=k)f[s]=x;++h}++g;h<<=1;k<<=1}return[f,a,b]};function w(c,d){this.g=[];this.h=32768;this.d=this.f=this.a=this.l=0;this.input=t?new Uint8Array(c):c;this.m=!1;this.i=y;this.r=!1;if(d||!(d={}))d.index&&(this.a=d.index),d.bufferSize&&(this.h=d.bufferSize),d.bufferType&&(this.i=d.bufferType),d.resize&&(this.r=d.resize);switch(this.i){case A:this.b=32768;this.c=new (t?Uint8Array:Array)(32768+this.h+258);break;case y:this.b=0;this.c=new (t?Uint8Array:Array)(this.h);this.e=this.z;this.n=this.v;this.j=this.w;break;default:throw Error("invalid inflate mode"); |
||||||
|
}}var A=0,y=1,B={t:A,s:y}; |
||||||
|
w.prototype.k=function(){for(;!this.m;){var c=C(this,3);c&1&&(this.m=!0);c>>>=1;switch(c){case 0:var d=this.input,a=this.a,b=this.c,e=this.b,f=d.length,g=l,h=l,k=b.length,m=l;this.d=this.f=0;if(a+1>=f)throw Error("invalid uncompressed block header: LEN");g=d[a++]|d[a++]<<8;if(a+1>=f)throw Error("invalid uncompressed block header: NLEN");h=d[a++]|d[a++]<<8;if(g===~h)throw Error("invalid uncompressed block header: length verify");if(a+g>d.length)throw Error("input buffer is broken");switch(this.i){case A:for(;e+ |
||||||
|
g>b.length;){m=k-e;g-=m;if(t)b.set(d.subarray(a,a+m),e),e+=m,a+=m;else for(;m--;)b[e++]=d[a++];this.b=e;b=this.e();e=this.b}break;case y:for(;e+g>b.length;)b=this.e({p:2});break;default:throw Error("invalid inflate mode");}if(t)b.set(d.subarray(a,a+g),e),e+=g,a+=g;else for(;g--;)b[e++]=d[a++];this.a=a;this.b=e;this.c=b;break;case 1:this.j(ba,ca);break;case 2:for(var n=C(this,5)+257,p=C(this,5)+1,s=C(this,4)+4,x=new (t?Uint8Array:Array)(D.length),S=l,T=l,U=l,u=l,M=l,F=l,z=l,q=l,V=l,q=0;q<s;++q)x[D[q]]= |
||||||
|
C(this,3);if(!t){q=s;for(s=x.length;q<s;++q)x[D[q]]=0}S=v(x);u=new (t?Uint8Array:Array)(n+p);q=0;for(V=n+p;q<V;)switch(M=E(this,S),M){case 16:for(z=3+C(this,2);z--;)u[q++]=F;break;case 17:for(z=3+C(this,3);z--;)u[q++]=0;F=0;break;case 18:for(z=11+C(this,7);z--;)u[q++]=0;F=0;break;default:F=u[q++]=M}T=t?v(u.subarray(0,n)):v(u.slice(0,n));U=t?v(u.subarray(n)):v(u.slice(n));this.j(T,U);break;default:throw Error("unknown BTYPE: "+c);}}return this.n()}; |
||||||
|
var G=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],D=t?new Uint16Array(G):G,H=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],I=t?new Uint16Array(H):H,J=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],K=t?new Uint8Array(J):J,L=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],da=t?new Uint16Array(L):L,ea=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12, |
||||||
|
13,13],N=t?new Uint8Array(ea):ea,O=new (t?Uint8Array:Array)(288),P,fa;P=0;for(fa=O.length;P<fa;++P)O[P]=143>=P?8:255>=P?9:279>=P?7:8;var ba=v(O),Q=new (t?Uint8Array:Array)(30),R,ga;R=0;for(ga=Q.length;R<ga;++R)Q[R]=5;var ca=v(Q);function C(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h;b<d;){if(f>=g)throw Error("input buffer is broken");a|=e[f++]<<b;b+=8}h=a&(1<<d)-1;c.f=a>>>d;c.d=b-d;c.a=f;return h} |
||||||
|
function E(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h=d[0],k=d[1],m,n;b<k&&!(f>=g);)a|=e[f++]<<b,b+=8;m=h[a&(1<<k)-1];n=m>>>16;if(n>b)throw Error("invalid code length: "+n);c.f=a>>n;c.d=b-n;c.a=f;return m&65535} |
||||||
|
w.prototype.j=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length-258,f,g,h,k;256!==(f=E(this,c));)if(256>f)b>=e&&(this.b=b,a=this.e(),b=this.b),a[b++]=f;else{g=f-257;k=I[g];0<K[g]&&(k+=C(this,K[g]));f=E(this,d);h=da[f];0<N[f]&&(h+=C(this,N[f]));b>=e&&(this.b=b,a=this.e(),b=this.b);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b}; |
||||||
|
w.prototype.w=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length,f,g,h,k;256!==(f=E(this,c));)if(256>f)b>=e&&(a=this.e(),e=a.length),a[b++]=f;else{g=f-257;k=I[g];0<K[g]&&(k+=C(this,K[g]));f=E(this,d);h=da[f];0<N[f]&&(h+=C(this,N[f]));b+k>e&&(a=this.e(),e=a.length);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b}; |
||||||
|
w.prototype.e=function(){var c=new (t?Uint8Array:Array)(this.b-32768),d=this.b-32768,a,b,e=this.c;if(t)c.set(e.subarray(32768,c.length));else{a=0;for(b=c.length;a<b;++a)c[a]=e[a+32768]}this.g.push(c);this.l+=c.length;if(t)e.set(e.subarray(d,d+32768));else for(a=0;32768>a;++a)e[a]=e[d+a];this.b=32768;return e}; |
||||||
|
w.prototype.z=function(c){var d,a=this.input.length/this.a+1|0,b,e,f,g=this.input,h=this.c;c&&("number"===typeof c.p&&(a=c.p),"number"===typeof c.u&&(a+=c.u));2>a?(b=(g.length-this.a)/this.o[2],f=258*(b/2)|0,e=f<h.length?h.length+f:h.length<<1):e=h.length*a;t?(d=new Uint8Array(e),d.set(h)):d=h;return this.c=d}; |
||||||
|
w.prototype.n=function(){var c=0,d=this.c,a=this.g,b,e=new (t?Uint8Array:Array)(this.l+(this.b-32768)),f,g,h,k;if(0===a.length)return t?this.c.subarray(32768,this.b):this.c.slice(32768,this.b);f=0;for(g=a.length;f<g;++f){b=a[f];h=0;for(k=b.length;h<k;++h)e[c++]=b[h]}f=32768;for(g=this.b;f<g;++f)e[c++]=d[f];this.g=[];return this.buffer=e}; |
||||||
|
w.prototype.v=function(){var c,d=this.b;t?this.r?(c=new Uint8Array(d),c.set(this.c.subarray(0,d))):c=this.c.subarray(0,d):(this.c.length>d&&(this.c.length=d),c=this.c);return this.buffer=c};function W(c,d){var a,b;this.input=c;this.a=0;if(d||!(d={}))d.index&&(this.a=d.index),d.verify&&(this.A=d.verify);a=c[this.a++];b=c[this.a++];switch(a&15){case ha:this.method=ha;break;default:throw Error("unsupported compression method");}if(0!==((a<<8)+b)%31)throw Error("invalid fcheck flag:"+((a<<8)+b)%31);if(b&32)throw Error("fdict flag is not supported");this.q=new w(c,{index:this.a,bufferSize:d.bufferSize,bufferType:d.bufferType,resize:d.resize})} |
||||||
|
W.prototype.k=function(){var c=this.input,d,a;d=this.q.k();this.a=this.q.a;if(this.A){a=(c[this.a++]<<24|c[this.a++]<<16|c[this.a++]<<8|c[this.a++])>>>0;var b=d;if("string"===typeof b){var e=b.split(""),f,g;f=0;for(g=e.length;f<g;f++)e[f]=(e[f].charCodeAt(0)&255)>>>0;b=e}for(var h=1,k=0,m=b.length,n,p=0;0<m;){n=1024<m?1024:m;m-=n;do h+=b[p++],k+=h;while(--n);h%=65521;k%=65521}if(a!==(k<<16|h)>>>0)throw Error("invalid adler-32 checksum");}return d};var ha=8;r("Zlib.Inflate",W);r("Zlib.Inflate.prototype.decompress",W.prototype.k);var X={ADAPTIVE:B.s,BLOCK:B.t},Y,Z,$,ia;if(Object.keys)Y=Object.keys(X);else for(Z in Y=[],$=0,X)Y[$++]=Z;$=0;for(ia=Y.length;$<ia;++$)Z=Y[$],r("Zlib.Inflate.BufferType."+Z,X[Z]);}).call(this); |
@ -0,0 +1,110 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="utf-8" /> |
||||||
|
<title>创建方案</title> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||||
|
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> |
||||||
|
<!-- three.js --> |
||||||
|
<script src="/js/three/three.js"></script> |
||||||
|
<script src="/js/three/OrbitControls.js"></script> |
||||||
|
<!-- 加载器 --> |
||||||
|
<script src="/js/three/OBJLoader.js"></script> |
||||||
|
<script src="/js/three/FBXLoader.js"></script> |
||||||
|
<script src="/js/three/TGALoader.js"></script> |
||||||
|
<script src='/js/three/inflate.min.js'></script> |
||||||
|
<!-- ZUI --> |
||||||
|
<link rel="stylesheet" href="//cdn.bootcss.com/zui/1.8.1/css/zui.min.css"> |
||||||
|
<script src="//cdn.bootcss.com/zui/1.8.1/js/zui.min.js"></script> |
||||||
|
<style> |
||||||
|
* { |
||||||
|
margin: 0px; |
||||||
|
padding: 0px; |
||||||
|
} |
||||||
|
html, |
||||||
|
body { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
overflow: hidden; |
||||||
|
} |
||||||
|
#viewField { |
||||||
|
width: 80%; |
||||||
|
height: 100%; |
||||||
|
position: absolute; |
||||||
|
top: 0px; |
||||||
|
right: 0px; |
||||||
|
} |
||||||
|
#editField { |
||||||
|
background-color: #fafafa; |
||||||
|
padding: 10px; |
||||||
|
width: 20%; |
||||||
|
height: 100%; |
||||||
|
position: absolute; |
||||||
|
top: 0px; |
||||||
|
left: 0px; |
||||||
|
} |
||||||
|
</style> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
<!-- threejs容器 --> |
||||||
|
<div id="viewField"></div> |
||||||
|
<!-- 编辑栏 --> |
||||||
|
<div id="editField"> |
||||||
|
<div class="panel"> |
||||||
|
<div class="panel-heading"> |
||||||
|
<div class="input-control has-label-left"> |
||||||
|
<input id="schemeName" type="text" class="form-control" placeholder=""> |
||||||
|
<label for="schemeName" class="input-control-label-left"><i class="icon icon-edit"></i>方案名</label> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="panel-body"> |
||||||
|
<div class="dropdown"> |
||||||
|
<button class="btn btn-block" data-toggle="dropdown">组件选择 <span class="caret"></span></button> |
||||||
|
<ul class="dropdown-menu" id="componentList"> |
||||||
|
<li><a data-toggle="modal" data-target="#addComponentModal"><i class="icon icon-plus"></i> 添加新组件</a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div style="margin-top:20px"> |
||||||
|
<div class="page-header"> |
||||||
|
<h3 id="componentTitle">请先选择部件</h3> |
||||||
|
</div> |
||||||
|
<div class="list-group" id="modelList"> |
||||||
|
|
||||||
|
</div> |
||||||
|
<button id="delComponent" class="btn btn-danger pull-right" style="display: none">删除该组件</button> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
<div class="panel-footer"> |
||||||
|
<form id="uploadForm" enctype="multipart/form-data"> |
||||||
|
<input type="file" name="file" id="file" style="display: none" /> |
||||||
|
</form> |
||||||
|
<button class="btn btn-primary btn-block disabled" id="upload">上传模型</button> |
||||||
|
<button class="btn btn-success btn-block" id="saveScheme">保存方案</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<!-- 模态框:添加组件 --> |
||||||
|
<div class="modal fade" id="addComponentModal"> |
||||||
|
<div class="modal-dialog modal-sm"> |
||||||
|
<div class="modal-content"> |
||||||
|
<div class="modal-header"> |
||||||
|
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span |
||||||
|
class="sr-only">关闭</span></button> |
||||||
|
<h4 class="modal-title">添加新组件</h4> |
||||||
|
</div> |
||||||
|
<div class="modal-body"> |
||||||
|
<input type="text" class="form-control" id="componentName" placeholder="组件名称"> |
||||||
|
</div> |
||||||
|
<div class="modal-footer"> |
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> |
||||||
|
<button type="button" class="btn btn-primary" id="addComponent">添加</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<script src="/js/createScheme.js"></script> |
||||||
|
</body> |
||||||
|
|
||||||
|
</html> |