调整模型

dev
laozt 2 years ago
parent b68bde385a
commit 6a16ccdd2f

@ -56,6 +56,7 @@
"screenfull": "5.0.2",
"sortablejs": "1.10.2",
"vue": "2.6.12",
"vue-3d-model": "^1.4.1",
"vue-count-to": "1.0.13",
"vue-cropper": "0.5.5",
"vue-meta": "2.4.0",

Binary file not shown.

@ -1,42 +0,0 @@
# 3ds Max Wavefront OBJ Exporter v0.99 - (c)2007 guruware
# ´´½¨µÄÎļþ:27.10.2023 13:44:57
newmtl wire_214228153
Ns 32
d 1
Tr 0
Tf 1 1 1
illum 2
Ka 0.8392 0.8941 0.6000
Kd 0.8392 0.8941 0.6000
Ks 0.3500 0.3500 0.3500
newmtl wire_006135113
Ns 32
d 1
Tr 0
Tf 1 1 1
illum 2
Ka 0.0235 0.5294 0.4431
Kd 0.0235 0.5294 0.4431
Ks 0.3500 0.3500 0.3500
newmtl wire_087224143
Ns 32
d 1
Tr 0
Tf 1 1 1
illum 2
Ka 0.3412 0.8784 0.5608
Kd 0.3412 0.8784 0.5608
Ks 0.3500 0.3500 0.3500
newmtl wire_166229229
Ns 32
d 1
Tr 0
Tf 1 1 1
illum 2
Ka 0.6510 0.8980 0.8980
Kd 0.6510 0.8980 0.8980
Ks 0.3500 0.3500 0.3500

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,117 +0,0 @@
## [1.4.1](https://github.com/hujiulong/vue-3d-model/compare/v1.4.0...v1.4.1) (2022-08-15)
### Bug Fixes
* fix order of calculations ([f58bf72](https://github.com/hujiulong/vue-3d-model/commit/f58bf72be93c7c088c73e64919deaea3f20301a1))
# [1.4.0](https://github.com/hujiulong/vue-3d-model/compare/v1.3.1...v1.4.0) (2021-06-26)
### Bug Fixes
* **demo:** fix json loader demo ([3236bc2](https://github.com/hujiulong/vue-3d-model/commit/3236bc2c990905f812835a81f1c96c318d06a3d5))
* remove calls to removed methods ([ff01a19](https://github.com/hujiulong/vue-3d-model/commit/ff01a19d8715d0b44b9cb98ae4e51e070ad44915))
* the default props should return a new object ([e5cf0e1](https://github.com/hujiulong/vue-3d-model/commit/e5cf0e106c3cb95738c7201ee322b41a28d824a6))
### Features
* loaders should use setRequestHeader ([#267](https://github.com/hujiulong/vue-3d-model/issues/267)) ([40b077a](https://github.com/hujiulong/vue-3d-model/commit/40b077a3513f0830d1ba28a3c653b401b7ac97b2))
## [1.3.1](https://github.com/hujiulong/vue-3d-model/compare/v1.3.0...v1.3.1) (2020-06-30)
# [1.3.0](https://github.com/hujiulong/vue-3d-model/compare/v1.2.0...v1.3.0) (2020-06-30)
### Bug Fixes
* fix controlsOptions ([be18b78](https://github.com/hujiulong/vue-3d-model/commit/be18b783eee5fca2fceacc42ec002a80478f50e0))
* publicPath ([b69a2c7](https://github.com/hujiulong/vue-3d-model/commit/b69a2c7a6146c43849640926a97dbf11f65b75cb))
* resolve gammaOutput removed warning and update the README.md ([#172](https://github.com/hujiulong/vue-3d-model/issues/172)) ([f4ab34b](https://github.com/hujiulong/vue-3d-model/commit/f4ab34bc7663be40be122def73c7dcbed636eeb8))
### Features
* model-fbx and update three.js ([#167](https://github.com/hujiulong/vue-3d-model/issues/167)) ([c700a0f](https://github.com/hujiulong/vue-3d-model/commit/c700a0f9181ef5f1bb8f474cbf59c079a41e2b33))
# [1.2.0](https://github.com/hujiulong/vue-3d-model/compare/v1.1.0...v1.2.0) (2019-10-23)
### Bug Fixes
* dispose objects before component destroy ([02adf5b](https://github.com/hujiulong/vue-3d-model/commit/02adf5bc53f9911daa46c8dc0daa0aa3a61e396a))
### Features
* add a new prop: glOptions. closes [#111](https://github.com/hujiulong/vue-3d-model/issues/111) ([7d3448e](https://github.com/hujiulong/vue-3d-model/commit/7d3448eee51ebbf603c859ba62bc28efd9f4ec89))
* allow override OrbitControls Properties ([#123](https://github.com/hujiulong/vue-3d-model/issues/123)) ([55e29f6](https://github.com/hujiulong/vue-3d-model/commit/55e29f678b7278bd36ae52b67c028182931b871a))
# [1.1.0-alpha.0](https://github.com/hujiulong/vue-3d-model/compare/v1.0.2...1.1.0-alpha.0) (2019-06-21)
### Bug Fixes
* fix camera options ([#67](https://github.com/hujiulong/vue-3d-model/issues/67)) ([f5a0fe5](https://github.com/hujiulong/vue-3d-model/commit/f5a0fe5fea94774437c215a47008157637edc43e))
* fix props check ([693295b](https://github.com/hujiulong/vue-3d-model/commit/693295b764bd780732f420ad7e2d19881ceef8f1))
* updated background example ([#68](https://github.com/hujiulong/vue-3d-model/issues/68)) ([3760535](https://github.com/hujiulong/vue-3d-model/commit/3760535879ea71dbf92e647bd393d27e2b133d38))
### Features
* **gltf:** set the default value of gammaOutput to true ([e609c91](https://github.com/hujiulong/vue-3d-model/commit/e609c9145a95c425a4de1ba6e2d866881b7ecb73))
## [1.0.2](https://github.com/hujiulong/vue-3d-model/compare/v1.0.1...v1.0.2) (2018-08-11)
### Bug Fixes
* fix the config of dev(close [#43](https://github.com/hujiulong/vue-3d-model/issues/43)) ([e0468c0](https://github.com/hujiulong/vue-3d-model/commit/e0468c0736a2db001e4a1c4a8747ed0c3bad4a32))
### Features
* add crossOrigin option(fix [#33](https://github.com/hujiulong/vue-3d-model/issues/33)) ([1c815de](https://github.com/hujiulong/vue-3d-model/commit/1c815de53fea93f5e787c7c8ed3eb58ef610b164))
## [1.0.1](https://github.com/hujiulong/vue-3d-model/compare/v1.0.0...v1.0.1) (2018-05-01)
# [1.0.0](https://github.com/hujiulong/vue-3d-model/compare/v0.0.15...v1.0.0) (2018-02-08)
## [0.0.15](https://github.com/hujiulong/vue-3d-model/compare/3dc003e51745d500d8e7faed945088e70664d029...v0.0.15) (2018-01-03)
### Bug Fixes
* export `model-ply`.([#22](https://github.com/hujiulong/vue-3d-model/issues/22)) ([945930c](https://github.com/hujiulong/vue-3d-model/commit/945930c427e8a9d7c753e3c326b71a56ec78f07d))
* fix `on-error` event and add `on-progress` event([#15](https://github.com/hujiulong/vue-3d-model/issues/15)). ([0a92d7b](https://github.com/hujiulong/vue-3d-model/commit/0a92d7b160bdf495dbda47385e83e688874e14a0))
* fix `PointLight` not imported in `vue-mixin`([#16](https://github.com/hujiulong/vue-3d-model/issues/16)). ([01427f6](https://github.com/hujiulong/vue-3d-model/commit/01427f6c90159e0e87939e454831b96e0a81347a))
* fix rotate example ([5b5535e](https://github.com/hujiulong/vue-3d-model/commit/5b5535e43f8e3b07a43ff90aa7a7a30a064e937d))
* update OBJLoader to fix som bugs([#19](https://github.com/hujiulong/vue-3d-model/issues/19)). ([1889732](https://github.com/hujiulong/vue-3d-model/commit/1889732f7bc5055d4ed3c2da5e7accb70dd31d5c))
### Features
* add `model-gltf` to support the gltf format model. ([ad952a5](https://github.com/hujiulong/vue-3d-model/commit/ad952a58ede84c754e3dc7a5b9be9f462f30d703))
* model-obj supports MTL file ([3dc003e](https://github.com/hujiulong/vue-3d-model/commit/3dc003e51745d500d8e7faed945088e70664d029))

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2017-present, Jiulong Hu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

@ -1,120 +0,0 @@
# vue-3d-model
<p align="center">
<a href="https://www.npmjs.com/package/vue-3d-model"><img src="https://img.shields.io/npm/v/vue-3d-model.svg" alt="Version"></a>
<a href="https://travis-ci.org/hujiulong/vue-3d-model"><img src="https://travis-ci.org/hujiulong/vue-3d-model.svg?branch=master" alt="Build"></a>
<a href="https://www.npmjs.com/package/vue-3d-model"><img src="https://img.shields.io/npm/l/vue-3d-model.svg" alt="License"></a>
<a href="https://996.icu"><img src="https://img.shields.io/badge/link-996.icu-red.svg" alt="996.icu"></a>
</p>
vue.js 3D model viewer component, based on threejs, inspired by [model-tag](https://github.com/mrdoob/model-tag)
一个展示三维模型的Vue组件支持模型操作和模型点击事件能自动缩放模型到合适大小并校正偏移支持多种格式的模型。
<p align="center">
<img src="./preview.gif">
</p>
## Example
[DEMO](https://hujiulong.github.io/vue-3d-model/#/demo-basic)
## Install
using npm
```
npm install vue-3d-model --save
```
Or using script tag for global use
```html
<script src="https://unpkg.com/vue-3d-model/dist/vue-3d-model.umd.js"></script>
```
Or Download <a href="https://unpkg.com/vue-3d-model/dist/vue-3d-model.umd.js">vue-3d-model.js</a> and include it in your html
## Usage
```vue
<template>
<model-obj src="example/models/obj/LeePerrySmith.obj"></model-obj>
</template>
<script>
import { ModelObj } from 'vue-3d-model';
export default {
components: { ModelObj }
}
</script>
```
Or
```vue
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"></head>
<body>
<div id="app">
<model-obj src="example/models/obj/LeePerrySmith.obj"></model-obj>
</div>
<script src="vue.js"></script>
<script src="vue-3d-model.js"></script>
<script>
new Vue({ el: '#app' });
</script>
</body>
```
## Documents
### props
| prop | type | default | example |
| --------------- |---------------|----------------------|--------------------------------------------|
| src | string | - | './exapmle.obj' |
| width | number | - | 300 |
| height | number | - | 300 |
| position | object | { x: 0, y: 0, z: 0 } | { x: 100, y: 20, z: -10 } |
| rotation | object | { x: 0, y: 0, z: 0 } | { x: Math.PI / 2, y: 0, z: - Math.PI / 4 } |
| cameraPosition | object | { x: 0, y: 0, z: 0 } | { x: 1, y: 2, z: -3 } |
| cameraRotation | object | { x: 0, y: 0, z: 0 } | { x: 3, y: 2, z: -1 } |
| scale | object | { x: 1, y: 1, z: 1 } | { x: 2, y: 2, z: 3 } |
| lights | array | - | |
| backgroundColor | number/string | 0xffffff | 0xffffff/'#f00'/'rgb(255,255,255)' |
| backgroundAlpha | number | 1 | 0.5 |
| controlsOptions | object | - | see [OrbitControls Properties](https://threejs.org/docs/#examples/en/controls/OrbitControls) |
| crossOrigin | string | anonymous | anonymous/use-credentials |
| requestHeader | object | - | { 'Authorization: Bearer token' } |
| outputEncoding | number | THREE.LinearEncoding | see [WebGLRenderer OutputEncoding](https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderer.outputEncoding) |
| glOptions | object | { antialias: true, alpha: true } | see [WebGLRenderer Parameters](https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderer) |
### events
| event |
| ------------- |
| on-mousedown |
| on-mousemove |
| on-mouseup |
| on-click |
| on-load |
| on-progress |
| on-error |
## Model Format Support
| model format | component tag |
| ------------- |-------------------|
| obj | \<model-obj> |
| json | \<model-three> |
| stl | \<model-stl> |
| dae | \<model-collada> |
| ply | \<model-ply> |
| fbx | \<model-fbx> |
| gltf(2.0) | \<model-gltf> |
## Browser Support
Modern browsers and IE 11.
You can click on [this](http://caniuse.com/#search=webgl) for more information.
## TODO List
* Support for more model formats
* Animation
* Post-processing
## LICENSE
MIT

@ -1,93 +0,0 @@
{
"_from": "vue-3d-model",
"_id": "vue-3d-model@1.4.1",
"_inBundle": false,
"_integrity": "sha512-IQjpqEjK1OLF/0XgF6O++IvOPLinLQ2aWZQFHxPFoTfPlB4vQW2sgv8EJSqpsIYC/wSCdGlP3CEnv9L3aZHlow==",
"_location": "/vue-3d-model",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "vue-3d-model",
"name": "vue-3d-model",
"escapedName": "vue-3d-model",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmmirror.com/vue-3d-model/-/vue-3d-model-1.4.1.tgz",
"_shasum": "3d3e415e42ce32520dcc42f5d9e1ddb5e022f3eb",
"_spec": "vue-3d-model",
"_where": "D:\\ZtProject\\SuzhouVolunteer\\volunteer-pc",
"author": {
"name": "Jiulong Hu",
"email": "me@hujiulong.com"
},
"bundleDependencies": false,
"dependencies": {
"three": "^0.135.0"
},
"deprecated": false,
"description": "3D models viewer with vue.js",
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.8",
"@vue/cli-plugin-eslint": "~4.5.8",
"@vue/cli-plugin-unit-jest": "~4.5.8",
"@vue/cli-service": "~4.5.8",
"@vue/eslint-config-airbnb": "^5.0.2",
"@vue/test-utils": "^1.0.3",
"babel-eslint": "^10.1.0",
"chalk": "^4.1.1",
"conventional-changelog-cli": "^2.1.1",
"enquirer": "^2.3.6",
"eslint": "^7.5.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-vue": "^7.1.0",
"execa": "^5.1.1",
"less": "^4.1.1",
"less-loader": "^10.0.0",
"minimist": "^1.2.5",
"semver": "^7.3.5",
"vue": "^2.6.11",
"vue-router": "^3.3.4",
"vue-template-compiler": "^2.6.11",
"yorkie": "^2.0.0"
},
"files": [
"dist",
"src",
"LICENSE",
"package.json",
"preview.gif",
"README.md"
],
"gitHooks": {
"commit-msg": "node scripts/verify-commit.js"
},
"keywords": [
"vue",
"three.js",
"component"
],
"main": "dist/vue-3d-model.umd.js",
"name": "vue-3d-model",
"peerDependencies": {
"vue": ">=2.0.0"
},
"scripts": {
"build": "vue-cli-service build --target lib --name vue-3d-model src/index.js",
"build-examples": "vue-cli-service build examples/index.js --dest examples-dist",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"dev": "vue-cli-service serve examples/index.js",
"gpr-setup": "node scripts/gpr-setup.js",
"lint": "vue-cli-service lint src/ tests/ examples/",
"lint:fix": "npm run lint -- --fix",
"release": "node scripts/release.js",
"test": "vue-cli-service test:unit"
},
"version": "1.4.1"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

@ -1,67 +0,0 @@
import Vue from "vue";
import ModelObj from "./model-obj.vue";
import ModelFbx from "./model-fbx.vue";
import ModelThree from "./model-three.vue";
import ModelStl from "./model-stl.vue";
import ModelPly from "./model-ply.vue";
import ModelCollada from "./model-collada.vue";
import ModelGltf from "./model-gltf.vue";
// alias
const ModelJson = Vue.extend(ModelThree, {
name: "model-json",
});
const ModelDae = Vue.extend(ModelCollada, {
name: "model-dae",
});
const components = [
ModelObj,
ModelFbx,
ModelThree,
ModelJson,
ModelStl,
ModelPly,
ModelCollada,
ModelDae,
ModelGltf,
];
/* eslint-disable no-shadow */
const install = (Vue) => {
components.forEach((component) => {
Vue.component(component.name, component);
});
};
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue);
}
export default {
install,
ModelObj,
ModelFbx,
ModelThree,
ModelJson,
ModelStl,
ModelPly,
ModelCollada,
ModelDae,
ModelGltf,
};
export {
install,
ModelObj,
ModelFbx,
ModelThree,
ModelJson,
ModelStl,
ModelPly,
ModelCollada,
ModelDae,
ModelGltf,
};

@ -1,48 +0,0 @@
<script>
import { ColladaLoader } from 'three/examples/jsm/loaders/ColladaLoader';
import mixin from './model-mixin.vue';
export default {
name: 'model-collada',
mixins: [mixin],
props: {
lights: {
type: Array,
default() {
return [
{
type: 'HemisphereLight',
position: { x: 0, y: 1, z: 0 },
skyColor: 0xaaaaff,
groundColor: 0x806060,
intensity: 0.2,
},
{
type: 'DirectionalLight',
position: { x: 1, y: 1, z: 1 },
color: 0xffffff,
intensity: 0.8,
},
];
},
},
smoothing: {
type: Boolean,
default: false,
},
},
data() {
const loader = new ColladaLoader();
loader.setCrossOrigin(this.crossOrigin);
return {
loader,
};
},
methods: {
getObject(collada) {
return collada.scene;
},
},
};
</script>

@ -1,42 +0,0 @@
<script>
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader';
import mixin from './model-mixin.vue';
export default {
name: 'model-fbx',
mixins: [mixin],
props: {
lights: {
type: Array,
default() {
return [
{
type: 'HemisphereLight',
position: { x: 0, y: 1, z: 0 },
skyColor: 0xffffff,
groundColor: 0xffffff,
intensity: 0.8,
},
{
type: 'DirectionalLight',
position: { x: 1, y: 1, z: 1 },
color: 0xffffff,
intensity: 0.8,
},
];
},
},
},
data() {
return {
loader: new FBXLoader(),
};
},
methods: {
getObject(geometry) {
this.animations = geometry.animations;
return geometry;
},
},
};
</script>

@ -1,60 +0,0 @@
<script>
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import mixin from './model-mixin.vue';
export default {
name: 'model-gltf',
mixins: [mixin],
props: {
lights: {
type: Array,
default() {
return [
{
type: 'AmbientLight',
color: 0xaaaaaa,
},
{
type: 'DirectionalLight',
position: { x: 1, y: 1, z: 1 },
color: 0xffffff,
intensity: 0.8,
},
];
},
},
gammaOutput: {
type: Boolean,
default: true,
},
},
data() {
const loader = new GLTFLoader();
loader.setCrossOrigin(this.crossOrigin);
loader.setRequestHeader(this.requestHeader);
return {
loader,
};
},
methods: {
load() {
if (!this.src) return;
if (this.object) {
this.wrapper.remove(this.object);
}
this.loader.load(this.src, (data) => {
this.addObject(data.scene);
this.$emit('on-load');
}, (xhr) => {
this.$emit('on-progress', xhr);
}, (err) => {
this.$emit('on-error', err);
});
},
},
};
</script>

@ -1,475 +0,0 @@
<template>
<div style="width: 100%; height: 100%; margin: 0; border: 0; padding: 0;">
<canvas v-if="suportWebGL" ref="canvas" style="width: 100%; height: 100%;"></canvas>
<div v-else>
<slot>
Your browser does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br/>'
</slot>
</div>
</div>
</template>
<script>
import {
Object3D,
Vector2,
Vector3,
Color,
Scene,
Raycaster,
WebGLRenderer,
PerspectiveCamera,
AmbientLight,
PointLight,
HemisphereLight,
DirectionalLight,
LinearEncoding,
} from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { getSize, getCenter } from './util';
const suportWebGL = (() => {
try {
const canvas = document.createElement('canvas');
return !!(window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
} catch (e) {
return false;
}
})();
const DEFAULT_GL_OPTIONS = {
antialias: true,
alpha: true,
};
export default {
props: {
src: {
type: String,
},
width: {
type: Number,
},
height: {
type: Number,
},
position: {
type: Object,
default() {
return { x: 0, y: 0, z: 0 };
},
},
rotation: {
type: Object,
default() {
return { x: 0, y: 0, z: 0 };
},
},
scale: {
type: Object,
default() {
return { x: 1, y: 1, z: 1 };
},
},
lights: {
type: Array,
default() {
return [];
},
},
cameraPosition: {
type: Object,
default() {
return { x: 0, y: 0, z: 0 };
},
},
cameraRotation: {
type: Object,
default() {
return { x: 0, y: 0, z: 0 };
},
},
cameraUp: {
type: Object,
},
cameraLookAt: {
type: Object,
},
backgroundColor: {
default: 0xffffff,
},
backgroundAlpha: {
type: Number,
default: 1,
},
controlsOptions: {
type: Object,
},
crossOrigin: {
default: 'anonymous',
},
requestHeader: {
default: () => {},
},
outputEncoding: {
type: Number,
default: LinearEncoding,
},
glOptions: {
type: Object,
},
},
data() {
return {
suportWebGL,
size: {
width: this.width,
height: this.height,
},
object: null,
raycaster: new Raycaster(),
mouse: new Vector2(),
camera: new PerspectiveCamera(45, 1, 0.01, 100000),
scene: new Scene(),
wrapper: new Object3D(),
renderer: null,
controls: null,
allLights: [],
clock: typeof performance === 'undefined' ? Date : performance,
reqId: null, // requestAnimationFrame id
};
},
computed: {
hasListener() {
//
/* eslint-disable no-underscore-dangle */
const events = this._events;
const result = {};
['on-mousemove', 'on-mouseup', 'on-mousedown', 'on-click'].forEach((name) => {
result[name] = !!events[name] && events[name].length > 0;
});
return result;
},
},
mounted() {
if (this.width === undefined || this.height === undefined) {
this.size = {
width: this.$el.offsetWidth,
height: this.$el.offsetHeight,
};
}
const options = Object.assign({}, DEFAULT_GL_OPTIONS, this.glOptions, {
canvas: this.$refs.canvas,
});
this.renderer = new WebGLRenderer(options);
this.renderer.shadowMap.enabled = true;
this.renderer.outputEncoding = this.outputEncoding;
this.controls = new OrbitControls(this.camera, this.$el);
this.controls.type = 'orbit';
this.scene.add(this.wrapper);
this.load();
this.update();
this.$el.addEventListener('mousedown', this.onMouseDown, false);
this.$el.addEventListener('mousemove', this.onMouseMove, false);
this.$el.addEventListener('mouseup', this.onMouseUp, false);
this.$el.addEventListener('click', this.onClick, false);
window.addEventListener('resize', this.onResize, false);
this.animate();
},
beforeDestroy() {
cancelAnimationFrame(this.reqId);
this.renderer.dispose();
if (this.controls) {
this.controls.dispose();
}
this.$el.removeEventListener('mousedown', this.onMouseDown, false);
this.$el.removeEventListener('mousemove', this.onMouseMove, false);
this.$el.removeEventListener('mouseup', this.onMouseUp, false);
this.$el.removeEventListener('click', this.onClick, false);
window.removeEventListener('resize', this.onResize, false);
},
watch: {
src() {
this.load();
},
rotation: {
deep: true,
handler(val) {
if (!this.object) return;
this.object.rotation.set(val.x, val.y, val.z);
},
},
position: {
deep: true,
handler(val) {
if (!this.object) return;
this.object.position.set(val.x, val.y, val.z);
},
},
scale: {
deep: true,
handler(val) {
if (!this.object) return;
this.object.scale.set(val.x, val.y, val.z);
},
},
lights: {
deep: true,
handler() {
this.updateLights();
},
},
size: {
deep: true,
handler() {
this.updateCamera();
this.updateRenderer();
},
},
controlsOptions: {
deep: true,
handler() {
this.updateControls();
},
},
backgroundAlpha() {
this.updateRenderer();
},
backgroundColor() {
this.updateRenderer();
},
},
methods: {
onResize() {
if (this.width === undefined || this.height === undefined) {
this.$nextTick(() => {
this.size = {
width: this.$el.offsetWidth,
height: this.$el.offsetHeight,
};
});
}
},
onMouseDown(event) {
if (!this.hasListener['on-mousedown']) return;
const intersected = this.pick(event.clientX, event.clientY);
this.$emit('on-mousedown', intersected);
},
onMouseMove(event) {
if (!this.hasListener['on-mousemove']) return;
const intersected = this.pick(event.clientX, event.clientY);
this.$emit('on-mousemove', intersected);
},
onMouseUp(event) {
if (!this.hasListener['on-mouseup']) return;
const intersected = this.pick(event.clientX, event.clientY);
this.$emit('on-mouseup', intersected);
},
onClick(event) {
if (!this.hasListener['on-click']) return;
const intersected = this.pick(event.clientX, event.clientY);
this.$emit('on-click', intersected);
},
pick(x, y) {
if (!this.object) return null;
const rect = this.$el.getBoundingClientRect();
x -= rect.left;
y -= rect.top;
this.mouse.x = (x / this.size.width) * 2 - 1;
this.mouse.y = -(y / this.size.height) * 2 + 1;
this.raycaster.setFromCamera(this.mouse, this.camera);
const intersects = this.raycaster.intersectObject(this.object, true);
return (intersects && intersects.length) > 0 ? intersects[0] : null;
},
update() {
this.updateRenderer();
this.updateCamera();
this.updateLights();
this.updateControls();
},
updateModel() {
const { object } = this;
if (!object) return;
const { position } = this;
const { rotation } = this;
const { scale } = this;
object.position.set(position.x, position.y, position.z);
object.rotation.set(rotation.x, rotation.y, rotation.z);
object.scale.set(scale.x, scale.y, scale.z);
},
updateRenderer() {
const { renderer } = this;
renderer.setSize(this.size.width, this.size.height);
renderer.setPixelRatio(window.devicePixelRatio || 1);
renderer.setClearColor(new Color(this.backgroundColor).getHex());
renderer.setClearAlpha(this.backgroundAlpha);
},
updateCamera() {
const { camera } = this;
const { object } = this;
camera.aspect = this.size.width / this.size.height;
camera.updateProjectionMatrix();
if (!this.cameraLookAt && !this.cameraUp) {
if (!object) return;
const distance = getSize(object).length();
camera.position.set(this.cameraPosition.x, this.cameraPosition.y, this.cameraPosition.z);
camera.rotation.set(this.cameraRotation.x, this.cameraRotation.y, this.cameraRotation.z);
if (this.cameraPosition.x === 0 && this.cameraPosition.y === 0 && this.cameraPosition.z === 0) {
camera.position.z = distance;
}
camera.lookAt(new Vector3());
} else {
camera.position.set(this.cameraPosition.x, this.cameraPosition.y, this.cameraPosition.z);
camera.rotation.set(this.cameraRotation.x, this.cameraRotation.y, this.cameraRotation.z);
camera.up.set(this.cameraUp.x, this.cameraUp.y, this.cameraUp.z);
camera.lookAt(new Vector3(this.cameraLookAt.x, this.cameraLookAt.y, this.cameraLookAt.z));
}
},
updateLights() {
this.scene.remove(...this.allLights);
this.allLights = [];
this.lights.forEach((item) => {
if (!item.type) return;
const type = item.type.toLowerCase();
let light = null;
if (type === 'ambient' || type === 'ambientlight') {
const color = item.color === 0x000000 ? item.color : item.color || 0x404040;
const intensity = item.intensity === 0 ? item.intensity : item.intensity || 1;
light = new AmbientLight(color, intensity);
} else if (type === 'point' || type === 'pointlight') {
const color = item.color === 0x000000 ? item.color : item.color || 0xffffff;
const intensity = item.intensity === 0 ? item.intensity : item.intensity || 1;
const distance = item.distance || 0;
const decay = item.decay === 0 ? item.decay : item.decay || 1;
light = new PointLight(color, intensity, distance, decay);
if (item.position) {
light.position.copy(item.position);
}
} else if (type === 'directional' || type === 'directionallight') {
const color = item.color === 0x000000 ? item.color : item.color || 0xffffff;
const intensity = item.intensity === 0 ? item.intensity : item.intensity || 1;
light = new DirectionalLight(color, intensity);
if (item.position) {
light.position.copy(item.position);
}
if (item.target) {
light.target.copy(item.target);
}
} else if (type === 'hemisphere' || type === 'hemispherelight') {
const skyColor = item.skyColor === 0x000000 ? item.skyColor : item.skyColor || 0xffffff;
const groundColor = item.groundColor === 0x000000 ? item.groundColor : item.groundColor || 0xffffff;
const intensity = item.intensity === 0 ? item.intensity : item.intensity || 1;
light = new HemisphereLight(skyColor, groundColor, intensity);
if (item.position) {
light.position.copy(item.position);
}
}
this.allLights.push(light);
this.scene.add(light);
});
},
updateControls() {
if (this.controlsOptions) {
Object.assign(this.controls, this.controlsOptions);
}
},
load() {
if (!this.src) return;
if (this.object) {
this.wrapper.remove(this.object);
}
this.loader.setRequestHeader(this.requestHeader);
this.loader.load(this.src, (...args) => {
const object = this.getObject(...args);
if (this.process) {
this.process(object);
}
this.addObject(object);
this.$emit('on-load');
}, (xhr) => {
this.$emit('on-progress', xhr);
}, (err) => {
this.$emit('on-error', err);
});
},
getObject(object) {
return object;
},
addObject(object) {
this.object = object;
this.wrapper.add(object);
this.updateCamera();
this.updateModel();
const center = getCenter(object);
// correct position
this.wrapper.position.copy(center.negate());
},
animate() {
this.reqId = requestAnimationFrame(this.animate);
this.render();
},
render() {
this.renderer.render(this.scene, this.camera);
},
},
};
</script>

@ -1,137 +0,0 @@
<script>
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
import { DDSLoader } from "three/examples/jsm/loaders/DDSLoader";
import { LoadingManager } from "three/src/loaders/LoadingManager";
import { toIndexed } from "./util";
import mixin from "./model-mixin.vue";
// TODO: Better way to handle texture formats
const manager = new LoadingManager(); // 0.122+ new api
manager.addHandler(/\.dds$/i, new DDSLoader());
export default {
name: "model-obj",
mixins: [mixin],
props: {
lights: {
type: Array,
default() {
return [
{
type: "HemisphereLight",
position: { x: 0, y: 1, z: 0 },
skyColor: 0xaaaaff,
groundColor: 0x806060,
intensity: 0.2,
},
{
type: "DirectionalLight",
position: { x: 1, y: 1, z: 1 },
color: 0xffffff,
intensity: 0.8,
},
];
},
},
smoothing: {
type: Boolean,
default: false,
},
mtlPath: {
type: String,
},
mtl: {
type: String,
},
},
data() {
const objLoader = new OBJLoader(manager);
const mtlLoader = new MTLLoader(manager);
mtlLoader.setCrossOrigin(this.crossOrigin);
mtlLoader.setRequestHeader(this.requestHeader);
objLoader.setRequestHeader(this.requestHeader);
return {
loader: objLoader,
mtlLoader,
};
},
watch: {
mtl() {
this.load();
},
},
methods: {
process(object) {
if (this.smoothing) {
object.traverse((child) => {
if (child.geometry) {
child.geometry = toIndexed(child.geometry);
child.geometry.computeVertexNormals();
}
});
}
},
load() {
if (!this.src) return;
if (this.object) {
this.wrapper.remove(this.object);
}
const onLoad = (object) => {
if (this.process) {
this.process(object);
}
this.addObject(object);
this.$emit("on-load");
};
const onProgress = (xhr) => {
this.$emit("on-progress", xhr);
};
const onError = (err) => {
this.$emit("on-error", err);
};
if (this.mtl) {
let { mtlPath } = this;
let mtlSrc = this.mtl;
if (!this.mtlPath) {
const result = /^(.*\/)([^/]*)$/.exec(this.mtl);
if (result) {
mtlPath = result[1];
mtlSrc = result[2];
}
}
if (mtlPath) {
this.mtlLoader.setPath(mtlPath);
}
this.mtlLoader.load(
mtlSrc,
(materials) => {
materials.preload();
this.loader
.setMaterials(materials)
.load(this.src, onLoad, onProgress, onError);
},
() => {},
onError
);
} else {
this.loader.load(this.src, onLoad, onProgress, onError);
}
},
},
};
</script>

@ -1,47 +0,0 @@
<script>
import { PLYLoader } from 'three/examples/jsm/loaders/PLYLoader';
import {
Mesh,
MeshStandardMaterial,
} from 'three';
import mixin from './model-mixin.vue';
export default {
name: 'model-ply',
mixins: [mixin],
props: {
lights: {
type: Array,
default() {
return [
{
type: 'HemisphereLight',
position: { x: 0, y: 1, z: 0 },
skyColor: 0xaaaaff,
groundColor: 0x806060,
intensity: 0.2,
},
{
type: 'DirectionalLight',
position: { x: 1, y: 1, z: 1 },
color: 0xffffff,
intensity: 0.8,
},
];
},
},
},
data() {
return {
loader: new PLYLoader(),
};
},
methods: {
getObject(geometry) {
geometry.computeVertexNormals();
return new Mesh(geometry, new MeshStandardMaterial());
},
},
};
</script>

@ -1,45 +0,0 @@
<script>
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader';
import {
Mesh,
MeshPhongMaterial,
} from 'three';
import mixin from './model-mixin.vue';
export default {
name: 'model-stl',
mixins: [mixin],
props: {
lights: {
type: Array,
default() {
return [
{
type: 'HemisphereLight',
position: { x: 0, y: 1, z: 0 },
skyColor: 0xaaaaff,
groundColor: 0x806060,
intensity: 0.2,
},
{
type: 'DirectionalLight',
position: { x: 1, y: 1, z: 1 },
color: 0xffffff,
intensity: 0.8,
},
];
},
},
},
data() {
return {
loader: new STLLoader(),
};
},
methods: {
getObject(geometry) {
return new Mesh(geometry, new MeshPhongMaterial());
},
},
};
</script>

@ -1,18 +0,0 @@
<script>
import { ObjectLoader } from 'three';
import mixin from './model-mixin.vue';
export default {
name: 'model-three',
mixins: [mixin],
data() {
const loader = new ObjectLoader();
loader.setCrossOrigin(this.crossOrigin);
loader.setRequestHeader(this.requestHeader);
return {
loader,
};
},
};
</script>

@ -1,160 +0,0 @@
import {
Box3, Vector3, Vector2, BufferAttribute,
} from 'three';
/* eslint-disable */
const box = new Box3();
function getSize(object) {
box.setFromObject(object);
return box.getSize(new Vector3());
}
function getCenter(object) {
box.setFromObject(object);
return box.getCenter(new Vector3());
}
// function lightsDiff(lights, oldLights) {
// }
function toIndexed(bufferGeometry) {
const rawPositions = bufferGeometry.getAttribute('position').array;
let rawUvs;
const hasUV = bufferGeometry.getAttribute('uv') !== undefined;
if (hasUV) rawUvs = bufferGeometry.getAttribute('uv').array;
let rawNormals;
const hasNormal = bufferGeometry.getAttribute('normal') !== undefined;
if (hasNormal) rawNormals = bufferGeometry.getAttribute('normal').array;
const indices = [];
const vertices = [];
const normals = [];
const uvs = [];
let face; let faceNormalss; let faceUvs; let
tmpIndices;
const v0 = new Vector3();
const v1 = new Vector3();
const v2 = new Vector3();
const n0 = new Vector3();
const n1 = new Vector3();
const n2 = new Vector3();
const uv0 = new Vector2();
const uv1 = new Vector2();
const uv2 = new Vector2();
for (let i = 0; i < rawPositions.length; i += 9) {
v0.x = rawPositions[i];
v0.y = rawPositions[i + 1];
v0.z = rawPositions[i + 2];
v1.x = rawPositions[i + 3];
v1.y = rawPositions[i + 4];
v1.z = rawPositions[i + 5];
v2.x = rawPositions[i + 6];
v2.y = rawPositions[i + 7];
v2.z = rawPositions[i + 8];
face = [v0, v1, v2];
if (hasNormal) {
n0.x = rawNormals[i];
n0.y = rawNormals[i + 1];
n0.z = rawNormals[i + 2];
n1.x = rawNormals[i + 3];
n1.y = rawNormals[i + 4];
n1.z = rawNormals[i + 5];
n2.x = rawNormals[i + 6];
n2.y = rawNormals[i + 7];
n2.z = rawNormals[i + 8];
faceNormalss = [n0, n1, n2];
}
if (hasUV) {
uv0.x = rawUvs[i];
uv0.y = rawUvs[i + 1];
uv1.x = rawUvs[i + 2];
uv1.y = rawUvs[i + 3];
uv2.x = rawUvs[i + 4];
uv2.y = rawUvs[i + 5];
faceUvs = [uv0, uv1, uv2];
}
tmpIndices = [];
face.forEach((v, i) => {
let id = exists(v, vertices);
if (id === -1) {
id = vertices.length;
vertices.push(v.clone());
if (hasNormal) normals.push(faceNormalss[i].clone());
if (hasUV) uvs.push(faceUvs[i].clone());
}
tmpIndices.push(id);
});
indices.push(tmpIndices[0], tmpIndices[1], tmpIndices[2]);
}
const positionBuffer = new Float32Array(vertices.length * 3);
let normalBuffer; let
uvBuffer;
if (hasNormal) normalBuffer = new Float32Array(vertices.length * 3);
if (hasUV) uvBuffer = new Float32Array(vertices.length * 2);
let i2 = 0;
let i3 = 0;
for (let i = 0; i < vertices.length; i++) {
i3 = i * 3;
positionBuffer[i3] = vertices[i].x;
positionBuffer[i3 + 1] = vertices[i].y;
positionBuffer[i3 + 2] = vertices[i].z;
if (hasNormal) {
normalBuffer[i3] = normals[i].x;
normalBuffer[i3 + 1] = normals[i].y;
normalBuffer[i3 + 2] = normals[i].z;
}
if (hasUV) {
i2 = i * 2;
uvBuffer[i2] = uvs[i].x;
uvBuffer[i2 + 1] = uvs[i].y;
}
}
bufferGeometry.addAttribute('position', new BufferAttribute(positionBuffer, 3));
if (hasNormal) bufferGeometry.addAttribute('normal', new BufferAttribute(normalBuffer, 3));
if (hasUV) bufferGeometry.addAttribute('uv', new BufferAttribute(uvBuffer, 2));
bufferGeometry.setIndex(new BufferAttribute(new Uint32Array(indices), 1));
return bufferGeometry;
function exists(v, vertices) {
for (let i = 0; i < vertices.length; i++) {
if (v.equals(vertices[i])) return i;
}
return -1;
}
}
export { getSize, getCenter, toIndexed };

@ -1,21 +1,17 @@
<!--
* @Author: 张涛
* @Date: 2023-10-31 17:28:25
* @LastEditors: 张涛
* @LastEditTime: 2023-11-01 10:11:59
* @FilePath: \volunteer-pc\src\views\3dmodel.vue
-->
<template>
<div class="page">
<!-- <model-collada
:backgroundAlpha="0"
:rotation="{
x: -Math.PI / 2,
y: 0,
z: 0,
}"
src="http://localhost/3dmodel/elf.dae"
/> -->
<!-- src="http://localhost/3dmodel/tree.obj" -->
<!-- <model-obj src="https://www.jichuanglanhai.com/demo/3dmodel/2.obj" /> -->
<!-- src="https://www.jichuanglanhai.com/demo/3dmodel/2.obj" -->
<model-obj
:width="375"
:height="667"
ref="model"
src="https://www.jichuanglanhai.com/demo/3dmodel/2.obj"
src="http://localhost/3dmodel/star.obj"
:rotation="rotation"
:position="position"
:scale="scale"
@ -23,12 +19,10 @@
@on-load="onLoad"
:controls-options="{}"
/>
<!-- src="http://localhost/3dmodel/dancing.fbx" -->
<!-- <model-fbx src="http://localhost/3dmodel/1.fbx" /> -->
</div>
</template>
<script>
import { ModelObj } from "../utils/vue3dmodel";
import { ModelObj } from "vue-3d-model";
export default {
components: {
@ -66,25 +60,16 @@ export default {
intensity: 0.8,
},
],
val: 0,
};
},
created() {
// let _this = this.rotate();
},
created() {},
methods: {
onLoad(e) {
this.rotate(e);
// console.log(this.$refs.model.$el.childNodes[0]);
// let el = this.$refs.model.$el.childNodes[0];
// el.style["transform"] = "rotateY(45deg)";
onLoad() {
this.rotate();
},
rotate(e) {
// this.rotation.z += 0.01;
rotate() {
this.rotation.y += 0.01;
this.val += 1;
let el = this.$refs.model.$el.childNodes[0];
el.style["transform"] = `rotateY(${this.val}deg)`;
requestAnimationFrame(this.rotate);
},
},

Loading…
Cancel
Save