forked from kscience/visionforge
Integrated ROOT geometry builder
This commit is contained in:
parent
a7432a2b33
commit
5c8665ac3e
@ -77,6 +77,9 @@ fun DisplayObject.int(default: Int? = null, key: String? = null, inherited: Bool
|
|||||||
fun DisplayObject.node(key: String? = null, inherited: Boolean = true) =
|
fun DisplayObject.node(key: String? = null, inherited: Boolean = true) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), null, inherited) { it.node }
|
DisplayObjectDelegateWrapper(key?.toName(), null, inherited) { it.node }
|
||||||
|
|
||||||
|
fun DisplayObject.item(key: String? = null, inherited: Boolean = true) =
|
||||||
|
DisplayObjectDelegateWrapper(key?.toName(), null, inherited) { it }
|
||||||
|
|
||||||
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
|
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
|
||||||
|
|
||||||
@JvmName("safeString")
|
@JvmName("safeString")
|
||||||
@ -95,6 +98,10 @@ fun DisplayObject.number(default: Number, key: String? = null, inherited: Boolea
|
|||||||
fun DisplayObject.double(default: Double, key: String? = null, inherited: Boolean = true) =
|
fun DisplayObject.double(default: Double, key: String? = null, inherited: Boolean = true) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
|
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
|
||||||
|
|
||||||
|
@JvmName("safeInt")
|
||||||
|
fun DisplayObject.int(default: Int, key: String? = null, inherited: Boolean = true) =
|
||||||
|
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.int }
|
||||||
|
|
||||||
inline fun <reified E : Enum<E>> DisplayObject.enum(default: E, key: String? = null, inherited: Boolean = true) =
|
inline fun <reified E : Enum<E>> DisplayObject.enum(default: E, key: String? = null, inherited: Boolean = true) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { item -> item.string?.let { enumValueOf<E>(it) } }
|
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { item -> item.string?.let { enumValueOf<E>(it) } }
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ plugins {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":dataforge-vis-spatial"))
|
api(project(":dataforge-vis-spatial"))
|
||||||
implementation("info.laht.threekt:threejs-wrapper:0.88-npm-1")
|
implementation("info.laht.threekt:threejs-wrapper:0.88-npm-2")
|
||||||
}
|
}
|
||||||
|
|
||||||
configure<KotlinFrontendExtension> {
|
configure<KotlinFrontendExtension> {
|
||||||
@ -19,7 +19,6 @@ configure<KotlinFrontendExtension> {
|
|||||||
|
|
||||||
configure<NpmExtension> {
|
configure<NpmExtension> {
|
||||||
dependency("three-full")
|
dependency("three-full")
|
||||||
//dependency("three-orbitcontrols")
|
|
||||||
dependency("style-loader")
|
dependency("style-loader")
|
||||||
devDependency("karma")
|
devDependency("karma")
|
||||||
}
|
}
|
||||||
@ -45,6 +44,7 @@ tasks{
|
|||||||
sourceMap = true
|
sourceMap = true
|
||||||
moduleKind = "umd"
|
moduleKind = "umd"
|
||||||
main = "call"
|
main = "call"
|
||||||
|
kotlinOptions.sourceMapEmbedSources = "always"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +54,7 @@ tasks{
|
|||||||
outputFile = "${project.buildDir.path}/js/${project.name}-test.js"
|
outputFile = "${project.buildDir.path}/js/${project.name}-test.js"
|
||||||
sourceMap = true
|
sourceMap = true
|
||||||
moduleKind = "umd"
|
moduleKind = "umd"
|
||||||
|
kotlinOptions.sourceMapEmbedSources = "always"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package hep.dataforge.vis.hmr
|
package hep.dataforge.vis
|
||||||
|
|
||||||
external val module: Module
|
external val module: Module
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package hep.dataforge.vis
|
package hep.dataforge.vis
|
||||||
|
|
||||||
import hep.dataforge.vis.hmr.module
|
|
||||||
import hep.dataforge.vis.spatial.ThreeDemoApp
|
import hep.dataforge.vis.spatial.ThreeDemoApp
|
||||||
import kotlin.browser.document
|
import kotlin.browser.document
|
||||||
import kotlin.dom.hasClass
|
import kotlin.dom.hasClass
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.meta.buildMeta
|
||||||
import hep.dataforge.meta.number
|
import hep.dataforge.meta.number
|
||||||
import hep.dataforge.meta.set
|
import hep.dataforge.meta.set
|
||||||
import hep.dataforge.vis.ApplicationBase
|
import hep.dataforge.vis.ApplicationBase
|
||||||
import hep.dataforge.vis.DisplayGroup
|
import hep.dataforge.vis.DisplayGroup
|
||||||
|
import hep.dataforge.vis.require
|
||||||
|
import hep.dataforge.vis.spatial.gdml.gdml
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
@ -18,8 +21,7 @@ class ThreeDemoApp : ApplicationBase() {
|
|||||||
override val stateKeys: List<String> = emptyList()
|
override val stateKeys: List<String> = emptyList()
|
||||||
|
|
||||||
override fun start(state: Map<String, Any>) {
|
override fun start(state: Map<String, Any>) {
|
||||||
//require("three-full")
|
require("JSRootGeoBase.js")
|
||||||
//require("three/examples/js/geometries/ConvexGeometry")
|
|
||||||
|
|
||||||
val renderer = ThreeOutput(Global)
|
val renderer = ThreeOutput(Global)
|
||||||
renderer.start(document.getElementById("canvas")!!)
|
renderer.start(document.getElementById("canvas")!!)
|
||||||
@ -42,16 +44,24 @@ class ThreeDemoApp : ApplicationBase() {
|
|||||||
properties.style["color"] = 1530
|
properties.style["color"] = 1530
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
convex {
|
// convex {
|
||||||
point(50,50,-50)
|
// point(50, 50, -50)
|
||||||
point(50,-50,-50)
|
// point(50, -50, -50)
|
||||||
point(-50,-50,-50)
|
// point(-50, -50, -50)
|
||||||
point(-50,50,-50)
|
// point(-50, 50, -50)
|
||||||
point(50,50,50)
|
// point(50, 50, 50)
|
||||||
point(50,-50,50)
|
// point(50, -50, 50)
|
||||||
point(-50,-50,50)
|
// point(-50, -50, 50)
|
||||||
point(-50,50,50)
|
// point(-50, 50, 50)
|
||||||
|
// }
|
||||||
|
gdml {
|
||||||
|
y = 110.0
|
||||||
|
shape = buildMeta {
|
||||||
|
"_typename" to "TGeoBBox"
|
||||||
|
"fDX" to 50.0
|
||||||
|
"fDY" to 50.0
|
||||||
|
"fDZ" to 50.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,5 +86,5 @@ class ThreeDemoApp : ApplicationBase() {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() = emptyMap<String,Any>()//mapOf("lines" to presenter.dispose())
|
override fun dispose() = emptyMap<String, Any>()//mapOf("lines" to presenter.dispose())
|
||||||
}
|
}
|
@ -5,6 +5,8 @@ import hep.dataforge.io.Output
|
|||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.vis.DisplayGroup
|
import hep.dataforge.vis.DisplayGroup
|
||||||
import hep.dataforge.vis.DisplayObject
|
import hep.dataforge.vis.DisplayObject
|
||||||
|
import hep.dataforge.vis.spatial.gdml.GDMLObject
|
||||||
|
import hep.dataforge.vis.spatial.gdml.ThreeGDMLBuilder
|
||||||
import hep.dataforge.vis.spatial.three.Group
|
import hep.dataforge.vis.spatial.three.Group
|
||||||
import info.laht.threekt.WebGLRenderer
|
import info.laht.threekt.WebGLRenderer
|
||||||
import info.laht.threekt.cameras.PerspectiveCamera
|
import info.laht.threekt.cameras.PerspectiveCamera
|
||||||
@ -66,6 +68,7 @@ class ThreeOutput(override val context: Context) : Output<DisplayObject> {
|
|||||||
ThreeObjectBuilder.updatePosition(obj, this)
|
ThreeObjectBuilder.updatePosition(obj, this)
|
||||||
}
|
}
|
||||||
is Box -> ThreeBoxBuilder(obj)
|
is Box -> ThreeBoxBuilder(obj)
|
||||||
|
is GDMLObject -> ThreeGDMLBuilder(obj)
|
||||||
//is Convex -> ThreeConvexBuilder(obj)
|
//is Convex -> ThreeConvexBuilder(obj)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
package hep.dataforge.vis.spatial.gdml
|
||||||
|
|
||||||
|
import hep.dataforge.meta.EmptyMeta
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.MetaItem
|
||||||
|
import hep.dataforge.vis.*
|
||||||
|
import hep.dataforge.vis.spatial.GenericThreeBuilder
|
||||||
|
import hep.dataforge.vis.spatial.Materials
|
||||||
|
import hep.dataforge.vis.spatial.material
|
||||||
|
import hep.dataforge.vis.spatial.three.EdgesGeometry
|
||||||
|
import info.laht.threekt.objects.LineSegments
|
||||||
|
import info.laht.threekt.objects.Mesh
|
||||||
|
|
||||||
|
class GDMLObject(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) {
|
||||||
|
|
||||||
|
var shape by node()
|
||||||
|
|
||||||
|
var color by item()
|
||||||
|
|
||||||
|
var facesLimit by int(0)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TYPE = "geometry.spatial.gdml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO add Zelenyy GDML builder here
|
||||||
|
fun DisplayGroup.gdml(meta: Meta = EmptyMeta, action: GDMLObject.() -> Unit = {}) =
|
||||||
|
GDMLObject(this, meta).apply(action).also { addChild(it) }
|
||||||
|
|
||||||
|
fun Meta.toDynamic(): dynamic {
|
||||||
|
fun MetaItem<*>.toDynamic(): dynamic = when (this) {
|
||||||
|
is MetaItem.ValueItem -> this.value.value.asDynamic()
|
||||||
|
is MetaItem.NodeItem -> this.node.toDynamic()
|
||||||
|
}
|
||||||
|
|
||||||
|
val res = js("{}")
|
||||||
|
this.items.entries.groupBy { it.key.body }.forEach { (key, value) ->
|
||||||
|
val list = value.map { it.value }
|
||||||
|
res[key] = when (list.size) {
|
||||||
|
1 -> list.first().toDynamic()
|
||||||
|
else -> list.map { it.toDynamic() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
object ThreeGDMLBuilder : GenericThreeBuilder<GDMLObject, Mesh>() {
|
||||||
|
override fun build(obj: GDMLObject): Mesh {
|
||||||
|
val shapeMeta = obj.shape?.toDynamic() ?: error("The shape not defined")
|
||||||
|
println(shapeMeta)
|
||||||
|
val geometry = createGeometry(shapeMeta, obj.facesLimit)
|
||||||
|
return Mesh(geometry, obj.color.material()).also { mesh ->
|
||||||
|
mesh.add(LineSegments(EdgesGeometry(geometry), Materials.DEFAULT))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(obj: GDMLObject, target: Mesh) {
|
||||||
|
val shapeMeta: dynamic = obj.shape?.toDynamic()
|
||||||
|
target.geometry = createGeometry(shapeMeta, obj.facesLimit)
|
||||||
|
target.material = obj.color.material()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
@file:JsModule("JSRootGeoBase.js")
|
||||||
|
@file:JsNonModule
|
||||||
|
package hep.dataforge.vis.spatial.gdml
|
||||||
|
|
||||||
|
import info.laht.threekt.core.Geometry
|
||||||
|
|
||||||
|
external fun createGeometry(shape: dynamic, limit: Int): Geometry
|
@ -1,4 +1,5 @@
|
|||||||
@file:JsQualifier("THREE")
|
@file:JsModule("three-full")
|
||||||
|
@file:JsNonModule
|
||||||
package hep.dataforge.vis.spatial.three
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
import info.laht.threekt.core.BufferGeometry
|
import info.laht.threekt.core.BufferGeometry
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@file:JsModule("three")
|
@file:JsModule("three-full")
|
||||||
@file:JsNonModule
|
@file:JsNonModule
|
||||||
|
|
||||||
package hep.dataforge.vis.spatial.three
|
package hep.dataforge.vis.spatial.three
|
||||||
|
3426
dataforge-vis-spatial-js/src/main/resources/JSRootGeoBase.js
Normal file
3426
dataforge-vis-spatial-js/src/main/resources/JSRootGeoBase.js
Normal file
File diff suppressed because it is too large
Load Diff
905
dataforge-vis-spatial-js/src/main/resources/ThreeCSG.js
Normal file
905
dataforge-vis-spatial-js/src/main/resources/ThreeCSG.js
Normal file
@ -0,0 +1,905 @@
|
|||||||
|
(function( factory ) {
|
||||||
|
if ( typeof define === "function" && define.amd ) {
|
||||||
|
define( [ 'three-full' ], factory );
|
||||||
|
} else
|
||||||
|
if (typeof exports === 'object' && typeof module !== 'undefined') {
|
||||||
|
factory(require("three-full"), exports);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (typeof THREE == 'undefined')
|
||||||
|
throw new Error('THREE is not defined', 'ThreeCSG.js');
|
||||||
|
|
||||||
|
ThreeBSP = factory(THREE);
|
||||||
|
}
|
||||||
|
} (function(THREE, ThreeBSP) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
if (!ThreeBSP) ThreeBSP = {};
|
||||||
|
|
||||||
|
var EPSILON = 1e-5,
|
||||||
|
COPLANAR = 0,
|
||||||
|
FRONT = 1,
|
||||||
|
BACK = 2,
|
||||||
|
SPANNING = 3;
|
||||||
|
|
||||||
|
ThreeBSP.Geometry = function( geometry, transfer_matrix, nodeid, flippedMesh ) {
|
||||||
|
// Convert THREE.Geometry to ThreeBSP
|
||||||
|
|
||||||
|
if ( geometry instanceof THREE.Geometry ) {
|
||||||
|
this.matrix = null; // new THREE.Matrix4; not create matrix when do not needed
|
||||||
|
} else if ( geometry instanceof THREE.Mesh ) {
|
||||||
|
// #todo: add hierarchy support
|
||||||
|
geometry.updateMatrix();
|
||||||
|
transfer_matrix = this.matrix = geometry.matrix.clone();
|
||||||
|
geometry = geometry.geometry;
|
||||||
|
} else if ( geometry instanceof ThreeBSP.Node ) {
|
||||||
|
this.tree = geometry;
|
||||||
|
this.matrix = null; // new THREE.Matrix4;
|
||||||
|
return this;
|
||||||
|
} else if ( geometry instanceof THREE.BufferGeometry ) {
|
||||||
|
var pos_buf = geometry.getAttribute('position').array,
|
||||||
|
norm_buf = geometry.getAttribute('normal').array,
|
||||||
|
polygons = [], polygon, vert1, vert2, vert3;
|
||||||
|
|
||||||
|
for (var i=0; i < pos_buf.length; i+=9) {
|
||||||
|
polygon = new ThreeBSP.Polygon;
|
||||||
|
|
||||||
|
vert1 = new ThreeBSP.Vertex( pos_buf[i], pos_buf[i+1], pos_buf[i+2], norm_buf[i], norm_buf[i+1], norm_buf[i+2]);
|
||||||
|
if (transfer_matrix) vert1.applyMatrix4(transfer_matrix);
|
||||||
|
|
||||||
|
vert2 = new ThreeBSP.Vertex( pos_buf[i+3], pos_buf[i+4], pos_buf[i+5], norm_buf[i+3], norm_buf[i+4], norm_buf[i+5]);
|
||||||
|
if (transfer_matrix) vert2.applyMatrix4(transfer_matrix);
|
||||||
|
|
||||||
|
vert3 = new ThreeBSP.Vertex( pos_buf[i+6], pos_buf[i+7], pos_buf[i+8], norm_buf[i+6], norm_buf[i+7], norm_buf[i+8]);
|
||||||
|
if (transfer_matrix) vert3.applyMatrix4(transfer_matrix);
|
||||||
|
|
||||||
|
if (flippedMesh) polygon.vertices.push( vert1, vert3, vert2 );
|
||||||
|
else polygon.vertices.push( vert1, vert2, vert3 );
|
||||||
|
|
||||||
|
polygon.calculateProperties();
|
||||||
|
polygons.push( polygon );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tree = new ThreeBSP.Node( polygons, nodeid );
|
||||||
|
if (nodeid!==undefined) this.maxid = this.tree.maxnodeid;
|
||||||
|
return this;
|
||||||
|
|
||||||
|
} else if (geometry.polygons && (geometry.polygons[0] instanceof ThreeBSP.Polygon)) {
|
||||||
|
var polygons = geometry.polygons;
|
||||||
|
|
||||||
|
for (var i=0;i<polygons.length;++i) {
|
||||||
|
var polygon = polygons[i];
|
||||||
|
if (transfer_matrix) {
|
||||||
|
for (var n=0;n<polygon.vertices.length;++n)
|
||||||
|
polygon.vertices[n].applyMatrix4(transfer_matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon.calculateProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tree = new ThreeBSP.Node( polygons, nodeid );
|
||||||
|
if (nodeid!==undefined) this.maxid = this.tree.maxnodeid;
|
||||||
|
return this;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw 'ThreeBSP: Given geometry is unsupported';
|
||||||
|
}
|
||||||
|
|
||||||
|
var polygons = [],
|
||||||
|
nfaces = geometry.faces.length,
|
||||||
|
face, polygon, vertex;
|
||||||
|
|
||||||
|
for (var i = 0; i < nfaces; ++i ) {
|
||||||
|
face = geometry.faces[i];
|
||||||
|
// faceVertexUvs = geometry.faceVertexUvs[0][i];
|
||||||
|
polygon = new ThreeBSP.Polygon;
|
||||||
|
|
||||||
|
if ( face instanceof THREE.Face3 ) {
|
||||||
|
vertex = geometry.vertices[ face.a ];
|
||||||
|
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[0].x, faceVertexUvs[0].y ) : null;
|
||||||
|
vertex = new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, face.vertexNormals[0].x, face.vertexNormals[0].y, face.vertexNormals[0].z /*face.normal , uvs */ );
|
||||||
|
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
|
||||||
|
polygon.vertices.push( vertex );
|
||||||
|
|
||||||
|
vertex = geometry.vertices[ face.b ];
|
||||||
|
//uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[1].x, faceVertexUvs[1].y ) : null;
|
||||||
|
vertex = new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, face.vertexNormals[1].x, face.vertexNormals[1].y, face.vertexNormals[1].z/*face.normal , uvs */ );
|
||||||
|
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
|
||||||
|
polygon.vertices.push( vertex );
|
||||||
|
|
||||||
|
vertex = geometry.vertices[ face.c ];
|
||||||
|
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[2].x, faceVertexUvs[2].y ) : null;
|
||||||
|
vertex = new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, face.vertexNormals[2].x, face.vertexNormals[2].y, face.vertexNormals[2].z /*face.normal, uvs */ );
|
||||||
|
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
|
||||||
|
polygon.vertices.push( vertex );
|
||||||
|
} else if ( typeof THREE.Face4 ) {
|
||||||
|
vertex = geometry.vertices[ face.a ];
|
||||||
|
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[0].x, faceVertexUvs[0].y ) : null;
|
||||||
|
vertex = new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, face.vertexNormals[0].x, face.vertexNormals[0].y, face.vertexNormals[0].z /*, uvs */ );
|
||||||
|
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
|
||||||
|
polygon.vertices.push( vertex );
|
||||||
|
|
||||||
|
vertex = geometry.vertices[ face.b ];
|
||||||
|
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[1].x, faceVertexUvs[1].y ) : null;
|
||||||
|
vertex = new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, face.vertexNormals[1].x, face.vertexNormals[1].y, face.vertexNormals[1].z /*, uvs */ );
|
||||||
|
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
|
||||||
|
polygon.vertices.push( vertex );
|
||||||
|
|
||||||
|
vertex = geometry.vertices[ face.c ];
|
||||||
|
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[2].x, faceVertexUvs[2].y ) : null;
|
||||||
|
vertex = new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, face.vertexNormals[2].x, face.vertexNormals[2].y, face.vertexNormals[2].z /*, uvs */ );
|
||||||
|
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
|
||||||
|
polygon.vertices.push( vertex );
|
||||||
|
|
||||||
|
vertex = geometry.vertices[ face.d ];
|
||||||
|
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[3].x, faceVertexUvs[3].y ) : null;
|
||||||
|
vertex = new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, face.vertexNormals[3].x, face.vertexNormals[3].y, face.vertexNormals[3].z /*, uvs */ );
|
||||||
|
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
|
||||||
|
polygon.vertices.push( vertex );
|
||||||
|
} else {
|
||||||
|
throw 'Invalid face type at index ' + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon.calculateProperties();
|
||||||
|
polygons.push( polygon );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tree = new ThreeBSP.Node( polygons, nodeid );
|
||||||
|
if (nodeid!==undefined) this.maxid = this.tree.maxnodeid;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.subtract = function( other_tree ) {
|
||||||
|
var a = this.tree.clone(),
|
||||||
|
b = other_tree.tree.clone();
|
||||||
|
|
||||||
|
a.invert();
|
||||||
|
a.clipTo( b );
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
a.build( b.allPolygons() );
|
||||||
|
a.invert();
|
||||||
|
a = new ThreeBSP.Geometry( a );
|
||||||
|
a.matrix = this.matrix;
|
||||||
|
return a;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.union = function( other_tree ) {
|
||||||
|
var a = this.tree.clone(),
|
||||||
|
b = other_tree.tree.clone();
|
||||||
|
|
||||||
|
a.clipTo( b );
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
a.build( b.allPolygons() );
|
||||||
|
a = new ThreeBSP.Geometry( a );
|
||||||
|
a.matrix = this.matrix;
|
||||||
|
return a;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.intersect = function( other_tree ) {
|
||||||
|
var a = this.tree.clone(),
|
||||||
|
b = other_tree.tree.clone();
|
||||||
|
|
||||||
|
a.invert();
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
a.clipTo( b );
|
||||||
|
b.clipTo( a );
|
||||||
|
a.build( b.allPolygons() );
|
||||||
|
a.invert();
|
||||||
|
a = new ThreeBSP.Geometry( a );
|
||||||
|
a.matrix = this.matrix;
|
||||||
|
return a;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.tryToCompress = function(polygons) {
|
||||||
|
|
||||||
|
if (this.maxid === undefined) return;
|
||||||
|
|
||||||
|
var arr = [], parts, foundpair,
|
||||||
|
nreduce = 0, n, len = polygons.length,
|
||||||
|
p, p1, p2, i1, i2;
|
||||||
|
|
||||||
|
// sort out polygons
|
||||||
|
for (n=0;n<len;++n) {
|
||||||
|
p = polygons[n];
|
||||||
|
if (p.id === undefined) continue;
|
||||||
|
if (arr[p.id] === undefined) arr[p.id] = [];
|
||||||
|
|
||||||
|
arr[p.id].push(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(n=0; n<arr.length; ++n) {
|
||||||
|
parts = arr[n];
|
||||||
|
if (parts===undefined) continue;
|
||||||
|
|
||||||
|
len = parts.length;
|
||||||
|
|
||||||
|
foundpair = (len > 1);
|
||||||
|
|
||||||
|
while (foundpair) {
|
||||||
|
foundpair = false;
|
||||||
|
|
||||||
|
for (i1 = 0; i1<len-1; ++i1) {
|
||||||
|
p1 = parts[i1];
|
||||||
|
if (!p1 || !p1.parent) continue;
|
||||||
|
for (i2 = i1+1; i2 < len; ++i2) {
|
||||||
|
p2 = parts[i2];
|
||||||
|
if (p2 && (p1.parent === p2.parent) && (p1.nsign === p2.nsign)) {
|
||||||
|
|
||||||
|
if (p1.nsign !== p1.parent.nsign) p1.parent.flip();
|
||||||
|
|
||||||
|
nreduce++;
|
||||||
|
parts[i1] = p1.parent;
|
||||||
|
parts[i2] = null;
|
||||||
|
if (p1.parent.vertices.length < 3) console.log('something wrong with parent');
|
||||||
|
foundpair = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nreduce>0) {
|
||||||
|
polygons.splice(0, polygons.length);
|
||||||
|
|
||||||
|
for(n=0;n<arr.length;++n) {
|
||||||
|
parts = arr[n];
|
||||||
|
if (parts !== undefined)
|
||||||
|
for (i1=0,len=parts.length; i1<len;++i1)
|
||||||
|
if (parts[i1]) polygons.push(parts[i1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.direct_subtract = function( other_tree ) {
|
||||||
|
var a = this.tree,
|
||||||
|
b = other_tree.tree;
|
||||||
|
a.invert();
|
||||||
|
a.clipTo( b );
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
a.build( b.collectPolygons([]) );
|
||||||
|
a.invert();
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.direct_union = function( other_tree ) {
|
||||||
|
var a = this.tree,
|
||||||
|
b = other_tree.tree;
|
||||||
|
|
||||||
|
a.clipTo( b );
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
a.build( b.collectPolygons([]) );
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.direct_intersect = function( other_tree ) {
|
||||||
|
var a = this.tree,
|
||||||
|
b = other_tree.tree;
|
||||||
|
|
||||||
|
a.invert();
|
||||||
|
b.clipTo( a );
|
||||||
|
b.invert();
|
||||||
|
a.clipTo( b );
|
||||||
|
b.clipTo( a );
|
||||||
|
a.build( b.collectPolygons([]) );
|
||||||
|
a.invert();
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.CreateNormal = function(axis_name, pos, size) {
|
||||||
|
// create geometry to make cut on specified axis
|
||||||
|
|
||||||
|
var vert1, vert2, vert3;
|
||||||
|
|
||||||
|
if (!size || (size<10000)) size = 10000;
|
||||||
|
|
||||||
|
switch(axis_name) {
|
||||||
|
case "x":
|
||||||
|
vert1 = new ThreeBSP.Vertex(pos, -3*size, size, 1, 0, 0),
|
||||||
|
vert3 = new ThreeBSP.Vertex(pos, size, size, 1, 0, 0),
|
||||||
|
vert2 = new ThreeBSP.Vertex(pos, size, -3*size, 1, 0, 0);
|
||||||
|
break;
|
||||||
|
case "y":
|
||||||
|
vert1 = new ThreeBSP.Vertex(-3*size, pos, size, 0, 1, 0),
|
||||||
|
vert2 = new ThreeBSP.Vertex( size, pos, size, 0, 1, 0),
|
||||||
|
vert3 = new ThreeBSP.Vertex( size, pos, -3*size, 0, 1, 0);
|
||||||
|
break;
|
||||||
|
case "z":
|
||||||
|
vert1 = new ThreeBSP.Vertex(-3*size, size, pos, 0, 0, 1),
|
||||||
|
vert3 = new ThreeBSP.Vertex( size, size, pos, 0, 0, 1),
|
||||||
|
vert2 = new ThreeBSP.Vertex( size, -3*size, pos, 0, 0, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var polygon = new ThreeBSP.Polygon([vert1, vert2, vert3]);
|
||||||
|
polygon.calculateProperties();
|
||||||
|
|
||||||
|
var node = new ThreeBSP.Node([polygon]);
|
||||||
|
|
||||||
|
return new ThreeBSP.Geometry(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.cut_from_plane = function( other_tree) {
|
||||||
|
// just cut peaces from second geometry, which just simple plane
|
||||||
|
|
||||||
|
var a = this.tree,
|
||||||
|
b = other_tree.tree;
|
||||||
|
|
||||||
|
a.invert();
|
||||||
|
b.clipTo( a );
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.toGeometry = function() {
|
||||||
|
var i, j,
|
||||||
|
matrix = this.matrix ? new THREE.Matrix4().getInverse( this.matrix ) : null,
|
||||||
|
geometry = new THREE.Geometry(),
|
||||||
|
polygons = this.tree.collectPolygons([]),
|
||||||
|
polygon_count = polygons.length,
|
||||||
|
polygon, polygon_vertice_count,
|
||||||
|
vertice_dict = {},
|
||||||
|
vertex_idx_a, vertex_idx_b, vertex_idx_c,
|
||||||
|
vertex, face;
|
||||||
|
|
||||||
|
for ( i = 0; i < polygon_count; ++i ) {
|
||||||
|
polygon = polygons[i];
|
||||||
|
polygon_vertice_count = polygon.vertices.length;
|
||||||
|
|
||||||
|
for ( j = 2; j < polygon_vertice_count; ++j ) {
|
||||||
|
// verticeUvs = [];
|
||||||
|
|
||||||
|
vertex = polygon.vertices[0];
|
||||||
|
// verticeUvs.push( new THREE.Vector2( vertex.uv.x, vertex.uv.y ) );
|
||||||
|
vertex = new THREE.Vector3( vertex.x, vertex.y, vertex.z );
|
||||||
|
if (matrix) vertex.applyMatrix4(matrix);
|
||||||
|
|
||||||
|
if ( typeof vertice_dict[ vertex.x + ',' + vertex.y + ',' + vertex.z ] !== 'undefined' ) {
|
||||||
|
vertex_idx_a = vertice_dict[ vertex.x + ',' + vertex.y + ',' + vertex.z ];
|
||||||
|
} else {
|
||||||
|
geometry.vertices.push( vertex );
|
||||||
|
vertex_idx_a = vertice_dict[ vertex.x + ',' + vertex.y + ',' + vertex.z ] = geometry.vertices.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex = polygon.vertices[j-1];
|
||||||
|
// verticeUvs.push( new THREE.Vector2( vertex.uv.x, vertex.uv.y ) );
|
||||||
|
vertex = new THREE.Vector3( vertex.x, vertex.y, vertex.z );
|
||||||
|
if (matrix) vertex.applyMatrix4(matrix);
|
||||||
|
if ( typeof vertice_dict[ vertex.x + ',' + vertex.y + ',' + vertex.z ] !== 'undefined' ) {
|
||||||
|
vertex_idx_b = vertice_dict[ vertex.x + ',' + vertex.y + ',' + vertex.z ];
|
||||||
|
} else {
|
||||||
|
geometry.vertices.push( vertex );
|
||||||
|
vertex_idx_b = vertice_dict[ vertex.x + ',' + vertex.y + ',' + vertex.z ] = geometry.vertices.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex = polygon.vertices[j];
|
||||||
|
// verticeUvs.push( new THREE.Vector2( vertex.uv.x, vertex.uv.y ) );
|
||||||
|
vertex = new THREE.Vector3( vertex.x, vertex.y, vertex.z );
|
||||||
|
if (matrix) vertex.applyMatrix4(matrix);
|
||||||
|
if ( typeof vertice_dict[ vertex.x + ',' + vertex.y + ',' + vertex.z ] !== 'undefined' ) {
|
||||||
|
vertex_idx_c = vertice_dict[ vertex.x + ',' + vertex.y + ',' + vertex.z ];
|
||||||
|
} else {
|
||||||
|
geometry.vertices.push( vertex );
|
||||||
|
vertex_idx_c = vertice_dict[ vertex.x + ',' + vertex.y + ',' + vertex.z ] = geometry.vertices.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
face = new THREE.Face3(
|
||||||
|
vertex_idx_a,
|
||||||
|
vertex_idx_b,
|
||||||
|
vertex_idx_c,
|
||||||
|
new THREE.Vector3( polygon.normal.x, polygon.normal.y, polygon.normal.z )
|
||||||
|
);
|
||||||
|
|
||||||
|
geometry.faces.push( face );
|
||||||
|
// geometry.faceVertexUvs[0].push( verticeUvs );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return geometry;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.scale = function(x,y,z) {
|
||||||
|
// try to scale as THREE.BufferGeometry
|
||||||
|
var polygons = this.tree.collectPolygons([]);
|
||||||
|
|
||||||
|
for (var i = 0; i < polygons.length; ++i) {
|
||||||
|
var polygon = polygons[i];
|
||||||
|
for (var k=0; k < polygon.vertices.length; ++k) {
|
||||||
|
var v = polygon.vertices[k];
|
||||||
|
v.x *= x;
|
||||||
|
v.y *= y;
|
||||||
|
v.z *= z;
|
||||||
|
}
|
||||||
|
delete polygon.normal;
|
||||||
|
polygon.calculateProperties();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.toPolygons = function() {
|
||||||
|
var polygons = this.tree.collectPolygons([]);
|
||||||
|
|
||||||
|
this.tryToCompress(polygons);
|
||||||
|
|
||||||
|
for (var i = 0; i < polygons.length; ++i ) {
|
||||||
|
delete polygons[i].id;
|
||||||
|
delete polygons[i].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return polygons;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.toBufferGeometry = function() {
|
||||||
|
return ThreeBSP.CreateBufferGeometry(this.toPolygons());
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.CreateBufferGeometry = function(polygons) {
|
||||||
|
var i, j, polygon_count = polygons.length, buf_size = 0;
|
||||||
|
|
||||||
|
for ( i = 0; i < polygon_count; ++i )
|
||||||
|
buf_size += (polygons[i].vertices.length - 2) * 9;
|
||||||
|
|
||||||
|
var positions_buf = new Float32Array(buf_size),
|
||||||
|
normals_buf = new Float32Array(buf_size),
|
||||||
|
iii = 0, polygon;
|
||||||
|
|
||||||
|
function CopyVertex(vertex) {
|
||||||
|
|
||||||
|
positions_buf[iii] = vertex.x;
|
||||||
|
positions_buf[iii+1] = vertex.y;
|
||||||
|
positions_buf[iii+2] = vertex.z;
|
||||||
|
|
||||||
|
normals_buf[iii] = polygon.nsign * vertex.nx;
|
||||||
|
normals_buf[iii+1] = polygon.nsign * vertex.ny;
|
||||||
|
normals_buf[iii+2] = polygon.nsign * vertex.nz;
|
||||||
|
iii+=3;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; i < polygon_count; ++i ) {
|
||||||
|
polygon = polygons[i];
|
||||||
|
for ( j = 2; j < polygon.vertices.length; ++j ) {
|
||||||
|
CopyVertex(polygon.vertices[0]);
|
||||||
|
CopyVertex(polygon.vertices[j-1]);
|
||||||
|
CopyVertex(polygon.vertices[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var geometry = new THREE.BufferGeometry();
|
||||||
|
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions_buf, 3 ) );
|
||||||
|
geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals_buf, 3 ) );
|
||||||
|
|
||||||
|
// geometry.computeVertexNormals();
|
||||||
|
return geometry;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Geometry.prototype.toMesh = function( material ) {
|
||||||
|
var geometry = this.toGeometry(),
|
||||||
|
mesh = new THREE.Mesh( geometry, material );
|
||||||
|
|
||||||
|
if (this.matrix) {
|
||||||
|
mesh.position.setFromMatrixPosition( this.matrix );
|
||||||
|
mesh.rotation.setFromRotationMatrix( this.matrix );
|
||||||
|
}
|
||||||
|
|
||||||
|
return mesh;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Polygon = function( vertices, normal, w ) {
|
||||||
|
if ( !( vertices instanceof Array ) ) {
|
||||||
|
vertices = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.vertices = vertices;
|
||||||
|
this.nsign = 1;
|
||||||
|
if ( vertices.length > 0 ) {
|
||||||
|
this.calculateProperties();
|
||||||
|
} else {
|
||||||
|
this.normal = this.w = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Polygon.prototype.copyProperties = function(parent, more) {
|
||||||
|
this.normal = parent.normal; // .clone();
|
||||||
|
this.w = parent.w;
|
||||||
|
this.nsign = parent.nsign;
|
||||||
|
if (more && (parent.id !== undefined)) {
|
||||||
|
this.id = parent.id;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Polygon.prototype.calculateProperties = function() {
|
||||||
|
if (this.normal) return;
|
||||||
|
|
||||||
|
var a = this.vertices[0],
|
||||||
|
b = this.vertices[1],
|
||||||
|
c = this.vertices[2];
|
||||||
|
|
||||||
|
this.nsign = 1;
|
||||||
|
|
||||||
|
this.normal = b.clone().subtract( a ).cross(
|
||||||
|
c.clone().subtract( a )
|
||||||
|
).normalize();
|
||||||
|
|
||||||
|
this.w = this.normal.clone().dot( a );
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Polygon.prototype.clone = function() {
|
||||||
|
var vertice_count = this.vertices.length,
|
||||||
|
polygon = new ThreeBSP.Polygon;
|
||||||
|
|
||||||
|
for (var i = 0; i < vertice_count; ++i )
|
||||||
|
polygon.vertices.push( this.vertices[i].clone() );
|
||||||
|
|
||||||
|
return polygon.copyProperties(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Polygon.prototype.flip = function() {
|
||||||
|
|
||||||
|
/// normal is not changed, only sign variable
|
||||||
|
//this.normal.multiplyScalar( -1 );
|
||||||
|
//this.w *= -1;
|
||||||
|
|
||||||
|
this.nsign *= -1;
|
||||||
|
|
||||||
|
this.vertices.reverse();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Polygon.prototype.classifyVertex = function( vertex ) {
|
||||||
|
var side_value = this.nsign * (this.normal.dot( vertex ) - this.w);
|
||||||
|
|
||||||
|
if ( side_value < -EPSILON ) return BACK;
|
||||||
|
if ( side_value > EPSILON ) return FRONT;
|
||||||
|
return COPLANAR;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Polygon.prototype.classifySide = function( polygon ) {
|
||||||
|
var i, classification,
|
||||||
|
num_positive = 0, num_negative = 0,
|
||||||
|
vertice_count = polygon.vertices.length;
|
||||||
|
|
||||||
|
for ( i = 0; i < vertice_count; ++i ) {
|
||||||
|
classification = this.classifyVertex( polygon.vertices[i] );
|
||||||
|
if ( classification === FRONT ) {
|
||||||
|
++num_positive;
|
||||||
|
} else if ( classification === BACK ) {
|
||||||
|
++num_negative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( num_positive > 0 && num_negative === 0 ) return FRONT;
|
||||||
|
if ( num_positive === 0 && num_negative > 0 ) return BACK;
|
||||||
|
if ( num_positive === 0 && num_negative === 0 ) return COPLANAR;
|
||||||
|
return SPANNING;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Polygon.prototype.splitPolygon = function( polygon, coplanar_front, coplanar_back, front, back ) {
|
||||||
|
var classification = this.classifySide( polygon );
|
||||||
|
|
||||||
|
if ( classification === COPLANAR ) {
|
||||||
|
|
||||||
|
( (this.nsign * polygon.nsign * this.normal.dot( polygon.normal ) > 0) ? coplanar_front : coplanar_back ).push( polygon );
|
||||||
|
|
||||||
|
} else if ( classification === FRONT ) {
|
||||||
|
|
||||||
|
front.push( polygon );
|
||||||
|
|
||||||
|
} else if ( classification === BACK ) {
|
||||||
|
|
||||||
|
back.push( polygon );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
var vertice_count = polygon.vertices.length,
|
||||||
|
nnx = this.normal.x,
|
||||||
|
nny = this.normal.y,
|
||||||
|
nnz = this.normal.z,
|
||||||
|
i, j, ti, tj, vi, vj,
|
||||||
|
t, v,
|
||||||
|
f = [], b = [];
|
||||||
|
|
||||||
|
for ( i = 0; i < vertice_count; ++i ) {
|
||||||
|
|
||||||
|
j = (i + 1) % vertice_count;
|
||||||
|
vi = polygon.vertices[i];
|
||||||
|
vj = polygon.vertices[j];
|
||||||
|
ti = this.classifyVertex( vi );
|
||||||
|
tj = this.classifyVertex( vj );
|
||||||
|
|
||||||
|
if ( ti != BACK ) f.push( vi );
|
||||||
|
if ( ti != FRONT ) b.push( vi );
|
||||||
|
if ( (ti | tj) === SPANNING ) {
|
||||||
|
// t = ( this.w - this.normal.dot( vi ) ) / this.normal.dot( vj.clone().subtract( vi ) );
|
||||||
|
//v = vi.clone().lerp( vj, t );
|
||||||
|
|
||||||
|
t = (this.w - (nnx*vi.x + nny*vi.y + nnz*vi.z)) / (nnx*(vj.x-vi.x) + nny*(vj.y-vi.y) + nnz*(vj.z-vi.z));
|
||||||
|
|
||||||
|
v = vi.interpolate( vj, t );
|
||||||
|
f.push( v );
|
||||||
|
b.push( v );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if ( f.length >= 3 ) front.push( new ThreeBSP.Polygon( f ).calculateProperties() );
|
||||||
|
//if ( b.length >= 3 ) back.push( new ThreeBSP.Polygon( b ).calculateProperties() );
|
||||||
|
if ( f.length >= 3 ) front.push( new ThreeBSP.Polygon( f ).copyProperties(polygon, true) );
|
||||||
|
if ( b.length >= 3 ) back.push( new ThreeBSP.Polygon( b ).copyProperties(polygon, true) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex = function(x, y, z, nx, ny, nz) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.nx = nx;
|
||||||
|
this.ny = ny;
|
||||||
|
this.nz = nz;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.setnormal = function ( nx, ny, nz ) {
|
||||||
|
this.nx = nx;
|
||||||
|
this.ny = ny;
|
||||||
|
this.nz = nz;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.clone = function() {
|
||||||
|
return new ThreeBSP.Vertex( this.x, this.y, this.z, this.nx, this.ny, this.nz);
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.add = function( vertex ) {
|
||||||
|
this.x += vertex.x;
|
||||||
|
this.y += vertex.y;
|
||||||
|
this.z += vertex.z;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.subtract = function( vertex ) {
|
||||||
|
this.x -= vertex.x;
|
||||||
|
this.y -= vertex.y;
|
||||||
|
this.z -= vertex.z;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.multiplyScalar = function( scalar ) {
|
||||||
|
this.x *= scalar;
|
||||||
|
this.y *= scalar;
|
||||||
|
this.z *= scalar;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.cross = function( vertex ) {
|
||||||
|
var x = this.x,
|
||||||
|
y = this.y,
|
||||||
|
z = this.z;
|
||||||
|
|
||||||
|
this.x = y * vertex.z - z * vertex.y;
|
||||||
|
this.y = z * vertex.x - x * vertex.z;
|
||||||
|
this.z = x * vertex.y - y * vertex.x;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.normalize = function() {
|
||||||
|
var length = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
|
||||||
|
|
||||||
|
this.x /= length;
|
||||||
|
this.y /= length;
|
||||||
|
this.z /= length;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.dot = function( vertex ) {
|
||||||
|
return this.x*vertex.x + this.y*vertex.y + this.z*vertex.z;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.diff = function( vertex ) {
|
||||||
|
var dx = (this.x - vertex.x),
|
||||||
|
dy = (this.y - vertex.y),
|
||||||
|
dz = (this.z - vertex.z),
|
||||||
|
len2 = this.x*this.x + this.y*this.y + this.z*this.z;
|
||||||
|
|
||||||
|
return (dx*dx + dy*dy + dz*dz) / (len2>0 ? len2 : 1e-10);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
ThreeBSP.Vertex.prototype.lerp = function( a, t ) {
|
||||||
|
this.add(
|
||||||
|
a.clone().subtract( this ).multiplyScalar( t )
|
||||||
|
);
|
||||||
|
|
||||||
|
this.normal.add(
|
||||||
|
a.normal.clone().sub( this.normal ).multiplyScalar( t )
|
||||||
|
);
|
||||||
|
|
||||||
|
//this.uv.add(
|
||||||
|
// a.uv.clone().sub( this.uv ).multiplyScalar( t )
|
||||||
|
//);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
ThreeBSP.Vertex.prototype.interpolate = function( other, t ) {
|
||||||
|
return this.clone().lerp( other, t );
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.interpolate = function( a, t ) {
|
||||||
|
var t1 = 1-t;
|
||||||
|
return new ThreeBSP.Vertex(this.x*t1 + a.x*t, this.y*t1 + a.y*t, this.z*t1 + a.z*t,
|
||||||
|
this.nx*t1 + a.nx*t, this.ny*t1 + a.ny*t, this.nz*t1 + a.nz*t);
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Vertex.prototype.applyMatrix4 = function ( m ) {
|
||||||
|
|
||||||
|
// input: THREE.Matrix4 affine matrix
|
||||||
|
|
||||||
|
var x = this.x, y = this.y, z = this.z, e = m.elements;
|
||||||
|
|
||||||
|
this.x = e[0] * x + e[4] * y + e[8] * z + e[12];
|
||||||
|
this.y = e[1] * x + e[5] * y + e[9] * z + e[13];
|
||||||
|
this.z = e[2] * x + e[6] * y + e[10] * z + e[14];
|
||||||
|
|
||||||
|
x = this.nx; y = this.ny; z = this.nz;
|
||||||
|
|
||||||
|
this.nx = e[0] * x + e[4] * y + e[8] * z;
|
||||||
|
this.ny = e[1] * x + e[5] * y + e[9] * z;
|
||||||
|
this.nz = e[2] * x + e[6] * y + e[10] * z;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
|
||||||
|
ThreeBSP.Node = function( polygons, nodeid ) {
|
||||||
|
this.polygons = [];
|
||||||
|
this.front = this.back = undefined;
|
||||||
|
|
||||||
|
if ( !(polygons instanceof Array) || polygons.length === 0 ) return;
|
||||||
|
|
||||||
|
this.divider = polygons[0].clone();
|
||||||
|
|
||||||
|
var polygon_count = polygons.length,
|
||||||
|
front = [], back = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < polygon_count; ++i ) {
|
||||||
|
if (nodeid!==undefined) {
|
||||||
|
polygons[i].id = nodeid++;
|
||||||
|
delete polygons[i].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.divider.splitPolygon( polygons[i], this.polygons, this.polygons, front, back );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodeid !== undefined) this.maxnodeid = nodeid;
|
||||||
|
|
||||||
|
if ( front.length > 0 )
|
||||||
|
this.front = new ThreeBSP.Node( front );
|
||||||
|
|
||||||
|
if ( back.length > 0 )
|
||||||
|
this.back = new ThreeBSP.Node( back );
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Node.isConvex = function( polygons ) {
|
||||||
|
var i, j, len = polygons.length;
|
||||||
|
for ( i = 0; i < len; ++i )
|
||||||
|
for ( j = 0; j < len; ++j )
|
||||||
|
if ( i !== j && polygons[i].classifySide( polygons[j] ) !== BACK ) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Node.prototype.build = function( polygons ) {
|
||||||
|
var polygon_count = polygons.length,
|
||||||
|
front = [], back = [];
|
||||||
|
|
||||||
|
if ( !this.divider )
|
||||||
|
this.divider = polygons[0].clone();
|
||||||
|
|
||||||
|
for (var i = 0; i < polygon_count; ++i )
|
||||||
|
this.divider.splitPolygon( polygons[i], this.polygons, this.polygons, front, back );
|
||||||
|
|
||||||
|
if ( front.length > 0 ) {
|
||||||
|
if ( !this.front ) this.front = new ThreeBSP.Node();
|
||||||
|
this.front.build( front );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( back.length > 0 ) {
|
||||||
|
if ( !this.back ) this.back = new ThreeBSP.Node();
|
||||||
|
this.back.build( back );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Node.prototype.collectPolygons = function(arr) {
|
||||||
|
var len = this.polygons.length;
|
||||||
|
for (var i=0;i<len;++i) arr.push(this.polygons[i]);
|
||||||
|
if ( this.front ) this.front.collectPolygons(arr);
|
||||||
|
if ( this.back ) this.back.collectPolygons(arr);
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Node.prototype.allPolygons = function() {
|
||||||
|
var polygons = this.polygons.slice();
|
||||||
|
if ( this.front ) polygons = polygons.concat( this.front.allPolygons() );
|
||||||
|
if ( this.back ) polygons = polygons.concat( this.back.allPolygons() );
|
||||||
|
return polygons;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Node.prototype.numPolygons = function() {
|
||||||
|
var res = this.polygons.length;
|
||||||
|
if ( this.front ) res += this.front.numPolygons();
|
||||||
|
if ( this.back ) res += this.back.numPolygons();
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Node.prototype.clone = function() {
|
||||||
|
var node = new ThreeBSP.Node();
|
||||||
|
|
||||||
|
node.divider = this.divider.clone();
|
||||||
|
node.polygons = this.polygons.map( function( polygon ) { return polygon.clone(); } );
|
||||||
|
node.front = this.front && this.front.clone();
|
||||||
|
node.back = this.back && this.back.clone();
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Node.prototype.invert = function() {
|
||||||
|
var polygon_count = this.polygons.length;
|
||||||
|
|
||||||
|
for (var i = 0; i < polygon_count; ++i )
|
||||||
|
this.polygons[i].flip();
|
||||||
|
|
||||||
|
this.divider.flip();
|
||||||
|
if ( this.front ) this.front.invert();
|
||||||
|
if ( this.back ) this.back.invert();
|
||||||
|
|
||||||
|
var temp = this.front;
|
||||||
|
this.front = this.back;
|
||||||
|
this.back = temp;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Node.prototype.clipPolygons = function( polygons ) {
|
||||||
|
|
||||||
|
if ( !this.divider ) return polygons.slice();
|
||||||
|
|
||||||
|
var polygon_count = polygons.length, front = [], back = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < polygon_count; ++i )
|
||||||
|
this.divider.splitPolygon( polygons[i], front, back, front, back );
|
||||||
|
|
||||||
|
if ( this.front ) front = this.front.clipPolygons( front );
|
||||||
|
if ( this.back ) back = this.back.clipPolygons( back );
|
||||||
|
else back = [];
|
||||||
|
|
||||||
|
return front.concat( back );
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreeBSP.Node.prototype.clipTo = function( node ) {
|
||||||
|
this.polygons = node.clipPolygons( this.polygons );
|
||||||
|
if ( this.front ) this.front.clipTo( node );
|
||||||
|
if ( this.back ) this.back.clipTo( node );
|
||||||
|
};
|
||||||
|
|
||||||
|
return ThreeBSP;
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
@ -10,6 +10,10 @@
|
|||||||
</style>
|
</style>
|
||||||
<!--<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script>-->
|
<!--<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script>-->
|
||||||
<!--<script type="text/javascript" src="js/OrbitControls.js"></script>-->
|
<!--<script type="text/javascript" src="js/OrbitControls.js"></script>-->
|
||||||
|
<!--<script type="text/javascript" src="js/three.min.js"></script>-->
|
||||||
|
<!--<script type="text/javascript" src="js/ThreeCSG.js"></script>-->
|
||||||
|
<!--<script type="text/javascript" src="js/JSRootCore.js"></script>-->
|
||||||
|
<!--<script type="text/javascript" src="js/JSRootGeoBase.js"></script>-->
|
||||||
<script type="text/javascript" language="JavaScript" src="main.bundle.js"></script>
|
<script type="text/javascript" language="JavaScript" src="main.bundle.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="testApp">
|
<body class="testApp">
|
||||||
|
Loading…
Reference in New Issue
Block a user