Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
three.js-projector
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Дмитрий Никулин
three.js-projector
Commits
45d1a027
You need to sign in or sign up before continuing.
Commit
45d1a027
authored
Jul 29, 2016
by
Evgeny
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update three dep. Update to E6^
parent
a8c7af38
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
926 additions
and
932 deletions
+926
-932
index.js
index.js
+926
-932
No files found.
index.js
View file @
45d1a027
...
...
@@ -4,465 +4,454 @@
* @author julianwa / https://github.com/julianwa
*/
define
([
'three'
],
function
(
THREE
,
BSPTree
){
var
Projector
=
{};
import
THREE
from
'three.js'
;
var
i
,
l
,
o
;
// counters
var
i
,
l
,
o
;
// counters
Projector
.
RenderableObject
=
function
()
{
export
class
RenderableObject
{
this
.
id
=
0
;
this
.
id
=
0
;
this
.
object
=
null
;
this
.
z
=
0
;
this
.
object
=
null
;
this
.
z
=
0
;
};
};
Projector
.
RenderableFace
=
function
()
{
export
function
RenderableFace
()
{
this
.
id
=
0
;
this
.
id
=
0
;
this
.
v1
=
new
THREE
.
RenderableVertex
();
this
.
v2
=
new
THREE
.
RenderableVertex
();
this
.
v3
=
new
THREE
.
RenderableVertex
();
this
.
v1
=
new
THREE
.
RenderableVertex
();
this
.
v2
=
new
THREE
.
RenderableVertex
();
this
.
v3
=
new
THREE
.
RenderableVertex
();
this
.
normalModel
=
new
THREE
.
Vector3
();
this
.
normalModel
=
new
THREE
.
Vector3
();
this
.
vertexNormalsModel
=
[
new
THREE
.
Vector3
(),
new
THREE
.
Vector3
(),
new
THREE
.
Vector3
()
];
this
.
vertexNormalsLength
=
0
;
this
.
vertexNormalsModel
=
[
new
THREE
.
Vector3
(),
new
THREE
.
Vector3
(),
new
THREE
.
Vector3
()
];
this
.
vertexNormalsLength
=
0
;
this
.
color
=
new
THREE
.
Color
();
this
.
material
=
null
;
this
.
uvs
=
[
new
THREE
.
Vector2
(),
new
THREE
.
Vector2
(),
new
THREE
.
Vector2
()
];
this
.
priority
=
null
;
this
.
color
=
new
THREE
.
Color
();
this
.
material
=
null
;
this
.
uvs
=
[
new
THREE
.
Vector2
(),
new
THREE
.
Vector2
(),
new
THREE
.
Vector2
()
];
this
.
priority
=
null
;
this
.
z
=
0
;
this
.
z
=
0
;
};
};
RenderableFace
.
prototype
.
copy
=
function
(
face
){
this
.
v1
.
copy
(
face
.
v1
);
this
.
v2
.
copy
(
face
.
v2
);
this
.
v3
.
copy
(
face
.
v3
);
this
.
normalModel
.
copy
(
face
.
normalModel
);
Projector
.
RenderableFace
.
prototype
.
copy
=
function
(
face
){
this
.
v1
.
copy
(
face
.
v1
);
this
.
v2
.
copy
(
face
.
v2
);
this
.
v3
.
copy
(
face
.
v3
);
this
.
normalModel
.
copy
(
face
.
normalModel
);
this
.
vertexNormalsModel
=
face
.
vertexNormalsModel
;
this
.
vertexNormalsLength
=
face
.
vertexNormalsLength
;
this
.
color
=
face
.
color
;
this
.
material
=
face
.
material
;
this
.
uvs
=
face
.
uvs
;
this
.
priority
=
face
.
priority
;
};
Projector
.
RenderableVertex
=
function
()
{
this
.
position
=
new
THREE
.
Vector3
();
this
.
positionWorld
=
new
THREE
.
Vector3
();
this
.
positionScreen
=
new
THREE
.
Vector4
();
this
.
visible
=
true
;
this
.
vertexNormalsModel
=
face
.
vertexNormalsModel
;
this
.
vertexNormalsLength
=
face
.
vertexNormalsLength
;
this
.
color
=
face
.
color
;
this
.
material
=
face
.
material
;
this
.
uvs
=
face
.
uvs
;
this
.
priority
=
face
.
priority
;
};
};
export
function
RenderableVertex
()
{
Projector
.
RenderableVertex
.
prototype
.
copy
=
function
(
vertex
)
{
this
.
position
=
new
THREE
.
Vector3
();
this
.
positionWorld
=
new
THREE
.
Vector3
();
this
.
positionScreen
=
new
THREE
.
Vector4
();
this
.
positionWorld
.
copy
(
vertex
.
positionWorld
);
this
.
positionScreen
.
copy
(
vertex
.
positionScreen
);
this
.
visible
=
true
;
};
};
Projector
.
RenderableLine
=
function
(
)
{
RenderableVertex
.
prototype
.
copy
=
function
(
vertex
)
{
this
.
id
=
0
;
this
.
positionWorld
.
copy
(
vertex
.
positionWorld
);
this
.
positionScreen
.
copy
(
vertex
.
positionScreen
);
this
.
v1
=
new
Projector
.
RenderableVertex
();
this
.
v2
=
new
Projector
.
RenderableVertex
();
};
this
.
vertexColors
=
[
new
THREE
.
Color
(),
new
THREE
.
Color
()
];
this
.
material
=
null
;
export
function
RenderableLine
()
{
this
.
z
=
0
;
this
.
id
=
0
;
};
Projector
.
RenderableLine
.
prototype
.
copy
=
function
(
line
){
this
.
v1
.
copy
(
line
.
v1
);
this
.
v2
.
copy
(
line
.
v2
);
this
.
vertexColors
=
line
.
vertexColors
;
this
.
material
=
line
.
material
;
};
this
.
v1
=
new
RenderableVertex
();
this
.
v2
=
new
RenderableVertex
();
Projector
.
RenderableSprite
=
function
()
{
this
.
vertexColors
=
[
new
THREE
.
Color
(),
new
THREE
.
Color
()
];
this
.
material
=
null
;
this
.
id
=
0
;
this
.
z
=
0
;
this
.
object
=
null
;
}
;
this
.
x
=
0
;
this
.
y
=
0
;
this
.
z
=
0
;
RenderableLine
.
prototype
.
copy
=
function
(
line
){
this
.
v1
.
copy
(
line
.
v1
);
this
.
v2
.
copy
(
line
.
v2
);
this
.
vertexColors
=
line
.
vertexColors
;
this
.
material
=
line
.
material
;
};
this
.
rotation
=
0
;
this
.
scale
=
new
THREE
.
Vector2
();
export
function
RenderableSprite
()
{
this
.
material
=
null
;
this
.
id
=
0
;
}
;
this
.
object
=
null
;
Projector
.
Projector
=
function
()
{
this
.
x
=
0
;
this
.
y
=
0
;
this
.
z
=
0
;
var
_object
,
_objectCount
,
_objectPool
=
[],
_objectPoolLength
=
0
,
_vertex
,
_camera
,
_vertexCount
,
_vertexPool
=
[],
_vertexPoolLength
=
0
,
_face
,
_faceCount
,
_facePool
=
[],
_facePoolLength
=
0
,
_line
,
_lineCount
,
_linePool
=
[],
_linePoolLength
=
0
,
_sprite
,
_spriteCount
,
_spritePool
=
[],
_spritePoolLength
=
0
,
this
.
rotation
=
0
;
this
.
scale
=
new
THREE
.
Vector2
();
_renderData
=
{
objects
:
[],
lights
:
[],
elements
:
[]
},
this
.
material
=
null
;
_vA
=
new
THREE
.
Vector3
(),
_vB
=
new
THREE
.
Vector3
(),
_vC
=
new
THREE
.
Vector3
(),
};
_vector3
=
new
THREE
.
Vector3
(),
_vector4
=
new
THREE
.
Vector4
(),
export
function
Projector
()
{
_clipBox
=
new
THREE
.
Box3
(
new
THREE
.
Vector3
(
-
1
,
-
1
,
-
1
),
new
THREE
.
Vector3
(
1
,
1
,
1
)
),
_boundingBox
=
new
THREE
.
Box3
(),
_points3
=
new
Array
(
3
),
_points4
=
new
Array
(
4
),
var
_object
,
_objectCount
,
_objectPool
=
[],
_objectPoolLength
=
0
,
_vertex
,
_camera
,
_vertexCount
,
_vertexPool
=
[],
_vertexPoolLength
=
0
,
_face
,
_faceCount
,
_facePool
=
[],
_facePoolLength
=
0
,
_line
,
_lineCount
,
_linePool
=
[],
_linePoolLength
=
0
,
_sprite
,
_spriteCount
,
_spritePool
=
[],
_spritePoolLength
=
0
,
_viewMatrix
=
new
THREE
.
Matrix4
(),
_viewProjectionMatrix
=
new
THREE
.
Matrix4
(),
_renderData
=
{
objects
:
[],
lights
:
[],
elements
:
[]
},
_modelMatrix
,
_modelViewProjectionMatrix
=
new
THREE
.
Matrix4
(),
_vA
=
new
THREE
.
Vector3
(),
_vB
=
new
THREE
.
Vector3
(),
_vC
=
new
THREE
.
Vector3
(),
_normalMatrix
=
new
THREE
.
Matrix3
(),
_vector3
=
new
THREE
.
Vector3
(),
_vector4
=
new
THREE
.
Vector4
(),
_frustum
=
new
THREE
.
Frustum
(),
_clipBox
=
new
THREE
.
Box3
(
new
THREE
.
Vector3
(
-
1
,
-
1
,
-
1
),
new
THREE
.
Vector3
(
1
,
1
,
1
)
),
_boundingBox
=
new
THREE
.
Box3
(),
_points3
=
new
Array
(
3
),
_points4
=
new
Array
(
4
),
_clippedVertex1PositionScreen
=
new
THREE
.
Vector
4
(),
_clippedVertex2PositionScreen
=
new
THREE
.
Vector4
();
_viewMatrix
=
new
THREE
.
Matrix
4
(),
_viewProjectionMatrix
=
new
THREE
.
Matrix4
(),
this
.
projectVector
=
function
(
vector
,
camera
)
{
_modelMatrix
,
_modelViewProjectionMatrix
=
new
THREE
.
Matrix4
(),
logger
.
warn
(
'THREE.Projector: .projectVector() is now vector.project().'
);
vector
.
project
(
camera
);
_normalMatrix
=
new
THREE
.
Matrix3
(),
};
_frustum
=
new
THREE
.
Frustum
(),
this
.
unprojectVector
=
function
(
vector
,
camera
)
{
_clippedVertex1PositionScreen
=
new
THREE
.
Vector4
(),
_clippedVertex2PositionScreen
=
new
THREE
.
Vector4
();
logger
.
warn
(
'THREE.Projector: .unprojectVector() is now vector.unproject().'
);
vector
.
unproject
(
camera
);
this
.
projectVector
=
function
(
vector
,
camera
)
{
};
logger
.
warn
(
'THREE.Projector: .projectVector() is now vector.project().'
);
vector
.
project
(
camera
);
this
.
pickingRay
=
function
(
vector
,
camera
)
{
};
logger
.
error
(
'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().'
);
this
.
unprojectVector
=
function
(
vector
,
camera
)
{
};
logger
.
warn
(
'THREE.Projector: .unprojectVector() is now vector.unproject().'
);
vector
.
unproject
(
camera
);
var
RenderList
=
function
()
{
};
var
normals
=
[];
var
uvs
=
[];
this
.
pickingRay
=
function
(
vector
,
camera
)
{
var
object
=
null
;
var
material
=
null
;
logger
.
error
(
'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().'
);
var
normalMatrix
=
new
THREE
.
Matrix3
()
;
}
;
var
setObject
=
function
(
value
)
{
var
RenderList
=
function
(
)
{
object
=
value
;
material
=
object
.
material
;
var
normals
=
[]
;
var
uvs
=
[]
;
normalMatrix
.
getNormalMatrix
(
object
.
matrixWorld
);
var
object
=
null
;
var
material
=
null
;
normals
.
length
=
0
;
uvs
.
length
=
0
;
var
normalMatrix
=
new
THREE
.
Matrix3
();
};
var
setObject
=
function
(
value
)
{
var
projectVertex
=
function
(
vertex
)
{
object
=
value
;
material
=
object
.
material
;
var
position
=
vertex
.
position
;
var
positionWorld
=
vertex
.
positionWorld
;
var
positionScreen
=
vertex
.
positionScreen
;
normalMatrix
.
getNormalMatrix
(
object
.
matrixWorld
);
positionWorld
.
copy
(
position
).
applyMatrix4
(
_modelMatrix
)
;
positionScreen
.
copy
(
positionWorld
).
applyMatrix4
(
_viewProjectionMatrix
)
;
normals
.
length
=
0
;
uvs
.
length
=
0
;
var
invW
=
1
/
positionScreen
.
w
;
}
;
positionScreen
.
x
*=
invW
;
positionScreen
.
y
*=
invW
;
positionScreen
.
z
*=
invW
;
var
projectVertex
=
function
(
vertex
)
{
vertex
.
visible
=
positionScreen
.
x
>=
-
1
&&
positionScreen
.
x
<=
1
&&
positionScreen
.
y
>=
-
1
&&
positionScreen
.
y
<=
1
&&
positionScreen
.
z
>=
-
1
&&
positionScreen
.
z
<=
1
;
var
position
=
vertex
.
position
;
var
positionWorld
=
vertex
.
positionWorld
;
var
positionScreen
=
vertex
.
positionScreen
;
};
positionWorld
.
copy
(
position
).
applyMatrix4
(
_modelMatrix
);
positionScreen
.
copy
(
positionWorld
).
applyMatrix4
(
_viewProjectionMatrix
);
var
pushVertex
=
function
(
x
,
y
,
z
)
{
var
invW
=
1
/
positionScreen
.
w
;
_vertex
=
getNextVertexInPool
();
_vertex
.
position
.
set
(
x
,
y
,
z
);
positionScreen
.
x
*=
invW
;
positionScreen
.
y
*=
invW
;
positionScreen
.
z
*=
invW
;
projectVertex
(
_vertex
);
vertex
.
visible
=
positionScreen
.
x
>=
-
1
&&
positionScreen
.
x
<=
1
&&
positionScreen
.
y
>=
-
1
&&
positionScreen
.
y
<=
1
&&
positionScreen
.
z
>=
-
1
&&
positionScreen
.
z
<=
1
;
};
};
var
pushNormal
=
function
(
x
,
y
,
z
)
{
var
pushVertex
=
function
(
x
,
y
,
z
)
{
normals
.
push
(
x
,
y
,
z
);
_vertex
=
getNextVertexInPool
();
_vertex
.
position
.
set
(
x
,
y
,
z
);
}
;
projectVertex
(
_vertex
)
;
var
pushUv
=
function
(
x
,
y
)
{
};
uvs
.
push
(
x
,
y
);
var
pushNormal
=
function
(
x
,
y
,
z
)
{
}
;
normals
.
push
(
x
,
y
,
z
)
;
var
checkTriangleVisibility
=
function
(
v1
,
v2
,
v3
)
{
};
if
(
v1
.
visible
===
true
||
v2
.
visible
===
true
||
v3
.
visible
===
true
)
return
true
;
var
pushUv
=
function
(
x
,
y
)
{
_points3
[
0
]
=
v1
.
positionScreen
;
_points3
[
1
]
=
v2
.
positionScreen
;
_points3
[
2
]
=
v3
.
positionScreen
;
uvs
.
push
(
x
,
y
);
return
_clipBox
.
isIntersectionBox
(
_boundingBox
.
setFromPoints
(
_points3
)
)
;
}
;
};
var
checkTriangleVisibility
=
function
(
v1
,
v2
,
v3
)
{
var
checkBackfaceCulling
=
function
(
v1
,
v2
,
v3
)
{
if
(
v1
.
visible
===
true
||
v2
.
visible
===
true
||
v3
.
visible
===
true
)
return
true
;
return
(
(
v3
.
positionScreen
.
x
-
v1
.
positionScreen
.
x
)
*
(
v2
.
positionScreen
.
y
-
v1
.
positionScreen
.
y
)
-
(
v3
.
positionScreen
.
y
-
v1
.
positionScreen
.
y
)
*
(
v2
.
positionScreen
.
x
-
v1
.
positionScreen
.
x
)
)
<
0
;
_points3
[
0
]
=
v1
.
positionScreen
;
_points3
[
1
]
=
v2
.
positionScreen
;
_points3
[
2
]
=
v3
.
positionScreen
;
}
;
return
_clipBox
.
isIntersectionBox
(
_boundingBox
.
setFromPoints
(
_points3
)
)
;
var
pushLine
=
function
(
a
,
b
)
{
};
var
v1
=
_vertexPool
[
a
];
var
v2
=
_vertexPool
[
b
];
var
checkBackfaceCulling
=
function
(
v1
,
v2
,
v3
)
{
_line
=
getNextLineInPool
();
return
(
(
v3
.
positionScreen
.
x
-
v1
.
positionScreen
.
x
)
*
(
v2
.
positionScreen
.
y
-
v1
.
positionScreen
.
y
)
-
(
v3
.
positionScreen
.
y
-
v1
.
positionScreen
.
y
)
*
(
v2
.
positionScreen
.
x
-
v1
.
positionScreen
.
x
)
)
<
0
;
_line
.
id
=
object
.
id
;
_line
.
v1
.
copy
(
v1
);
_line
.
v2
.
copy
(
v2
);
_line
.
z
=
(
v1
.
positionScreen
.
z
+
v2
.
positionScreen
.
z
)
/
2
;
};
_line
.
material
=
object
.
material
;
var
pushLine
=
function
(
a
,
b
)
{
_renderData
.
elements
.
push
(
_line
);
var
v1
=
_vertexPool
[
a
];
var
v2
=
_vertexPool
[
b
];
}
;
_line
=
getNextLineInPool
()
;
var
pushTriangle
=
function
(
a
,
b
,
c
)
{
_line
.
id
=
object
.
id
;
_line
.
v1
.
copy
(
v1
);
_line
.
v2
.
copy
(
v2
);
_line
.
z
=
(
v1
.
positionScreen
.
z
+
v2
.
positionScreen
.
z
)
/
2
;
var
v1
=
_vertexPool
[
a
];
var
v2
=
_vertexPool
[
b
];
var
v3
=
_vertexPool
[
c
];
_line
.
material
=
object
.
material
;
if
(
checkTriangleVisibility
(
v1
,
v2
,
v3
)
===
false
)
return
;
_renderData
.
elements
.
push
(
_line
)
;
if
(
material
.
side
===
THREE
.
DoubleSide
||
checkBackfaceCulling
(
v1
,
v2
,
v3
)
===
true
)
{
};
_face
=
getNextFaceInPool
();
var
pushTriangle
=
function
(
a
,
b
,
c
)
{
_face
.
id
=
object
.
id
;
_face
.
priority
=
face
.
priority
;
_face
.
v1
.
copy
(
v1
);
_face
.
v2
.
copy
(
v2
);
_face
.
v3
.
copy
(
v3
);
_face
.
z
=
(
v1
.
positionScreen
.
z
+
v2
.
positionScreen
.
z
+
v3
.
positionScreen
.
z
)
/
3
;
var
v1
=
_vertexPool
[
a
];
var
v2
=
_vertexPool
[
b
];
var
v3
=
_vertexPool
[
c
];
for
(
var
i
=
0
;
i
<
3
;
i
++
)
{
if
(
checkTriangleVisibility
(
v1
,
v2
,
v3
)
===
false
)
return
;
var
offset
=
arguments
[
i
]
*
3
;
var
normal
=
_face
.
vertexNormalsModel
[
i
];
if
(
material
.
side
===
THREE
.
DoubleSide
||
checkBackfaceCulling
(
v1
,
v2
,
v3
)
===
true
)
{
normal
.
set
(
normals
[
offset
],
normals
[
offset
+
1
],
normals
[
offset
+
2
]
);
normal
.
applyMatrix3
(
normalMatrix
).
normalize
();
_face
=
getNextFaceInPool
();
var
offset2
=
arguments
[
i
]
*
2
;
_face
.
id
=
object
.
id
;
_face
.
priority
=
face
.
priority
;
_face
.
v1
.
copy
(
v1
);
_face
.
v2
.
copy
(
v2
);
_face
.
v3
.
copy
(
v3
);
_face
.
z
=
(
v1
.
positionScreen
.
z
+
v2
.
positionScreen
.
z
+
v3
.
positionScreen
.
z
)
/
3
;
var
uv
=
_face
.
uvs
[
i
];
uv
.
set
(
uvs
[
offset2
],
uvs
[
offset2
+
1
]
);
for
(
var
i
=
0
;
i
<
3
;
i
++
)
{
}
var
offset
=
arguments
[
i
]
*
3
;
var
normal
=
_face
.
vertexNormalsModel
[
i
];
_face
.
vertexNormalsLength
=
3
;
normal
.
set
(
normals
[
offset
],
normals
[
offset
+
1
],
normals
[
offset
+
2
]
);
normal
.
applyMatrix3
(
normalMatrix
).
normalize
();
_face
.
material
=
object
.
material
;
var
offset2
=
arguments
[
i
]
*
2
;
_renderData
.
elements
.
push
(
_face
);
var
uv
=
_face
.
uvs
[
i
];
uv
.
set
(
uvs
[
offset2
],
uvs
[
offset2
+
1
]
);
}
}
;
_face
.
vertexNormalsLength
=
3
;
return
{
setObject
:
setObject
,
projectVertex
:
projectVertex
,
checkTriangleVisibility
:
checkTriangleVisibility
,
checkBackfaceCulling
:
checkBackfaceCulling
,
pushVertex
:
pushVertex
,
pushNormal
:
pushNormal
,
pushUv
:
pushUv
,
pushLine
:
pushLine
,
pushTriangle
:
pushTriangle
};
_face
.
material
=
object
.
material
;
}
;
_renderData
.
elements
.
push
(
_face
)
;
var
renderList
=
new
RenderList
();
}
this
.
projectScene
=
function
(
scene
,
camera
,
sortObjects
,
sortElements
)
{
};
_faceCount
=
0
;
_lineCount
=
0
;
_spriteCount
=
0
;
return
{
setObject
:
setObject
,
projectVertex
:
projectVertex
,
checkTriangleVisibility
:
checkTriangleVisibility
,
checkBackfaceCulling
:
checkBackfaceCulling
,
pushVertex
:
pushVertex
,
pushNormal
:
pushNormal
,
pushUv
:
pushUv
,
pushLine
:
pushLine
,
pushTriangle
:
pushTriangle
};
_renderData
.
elements
.
length
=
0
;
_camera
=
camera
;
};
if
(
scene
.
autoUpdate
===
true
)
scene
.
updateMatrixWorld
();
if
(
camera
.
parent
===
undefined
)
camera
.
updateMatrixWorld
();
var
renderList
=
new
RenderList
();
_viewMatrix
.
copy
(
camera
.
matrixWorldInverse
.
getInverse
(
camera
.
matrixWorld
)
);
_viewProjectionMatrix
.
multiplyMatrices
(
camera
.
projectionMatrix
,
_viewMatrix
);
this
.
projectScene
=
function
(
scene
,
camera
,
sortObjects
,
sortElements
)
{
_frustum
.
setFromMatrix
(
_viewProjectionMatrix
);
_faceCount
=
0
;
_lineCount
=
0
;
_spriteCount
=
0
;
_objectCount
=
0
;
_renderData
.
elements
.
length
=
0
;
_camera
=
camera
;
_renderData
.
objects
.
length
=
0
;
_renderData
.
lights
.
length
=
0
;
if
(
scene
.
autoUpdate
===
true
)
scene
.
updateMatrixWorld
()
;
if
(
camera
.
parent
===
undefined
)
camera
.
updateMatrixWorld
()
;
scene
.
traverseVisible
(
function
(
object
)
{
_viewMatrix
.
copy
(
camera
.
matrixWorldInverse
.
getInverse
(
camera
.
matrixWorld
)
);
_viewProjectionMatrix
.
multiplyMatrices
(
camera
.
projectionMatrix
,
_viewMatrix
);
if
(
object
instanceof
THREE
.
Light
)
{
_frustum
.
setFromMatrix
(
_viewProjectionMatrix
);
_renderData
.
lights
.
push
(
object
)
;
_objectCount
=
0
;
}
else
if
(
object
instanceof
THREE
.
Mesh
||
object
instanceof
THREE
.
Line
||
object
instanceof
THREE
.
Sprite
)
{
_renderData
.
objects
.
length
=
0
;
_renderData
.
lights
.
length
=
0
;
if
(
object
.
material
.
visible
===
false
)
return
;
scene
.
traverseVisible
(
function
(
object
)
{
if
(
object
.
frustumCulled
===
false
||
_frustum
.
intersectsObject
(
object
)
===
true
)
{
if
(
object
instanceof
THREE
.
Light
)
{
_object
=
getNextObjectInPool
();
_object
.
id
=
object
.
id
;
_object
.
object
=
object
;
_renderData
.
lights
.
push
(
object
);
_vector3
.
setFromMatrixPosition
(
object
.
matrixWorld
);
_vector3
.
applyProjection
(
_viewProjectionMatrix
);
_object
.
z
=
_vector3
.
z
;
}
else
if
(
object
instanceof
THREE
.
Mesh
||
object
instanceof
THREE
.
Line
||
object
instanceof
THREE
.
Sprite
)
{
_renderData
.
objects
.
push
(
_object
)
;
if
(
object
.
material
.
visible
===
false
)
return
;
}
if
(
object
.
frustumCulled
===
false
||
_frustum
.
intersectsObject
(
object
)
===
true
)
{
}
_object
=
getNextObjectInPool
();
_object
.
id
=
object
.
id
;
_object
.
object
=
object
;
}
);
_vector3
.
setFromMatrixPosition
(
object
.
matrixWorld
);
_vector3
.
applyProjection
(
_viewProjectionMatrix
);
_object
.
z
=
_vector3
.
z
;
if
(
sortObjects
===
true
)
{
_renderData
.
objects
.
push
(
_object
);
_renderData
.
objects
.
sort
(
customSort
);
}
}
for
(
var
o
=
0
,
ol
=
_renderData
.
objects
.
length
;
o
<
ol
;
o
++
)
{
var
object
=
_renderData
.
objects
[
o
].
object
;
var
geometry
=
object
.
geometry
;
}
);
renderList
.
setObject
(
object
);
if
(
sortObjects
===
true
)
{
_modelMatrix
=
object
.
matrixWorld
;
_renderData
.
objects
.
sort
(
customSort
)
;
_vertexCount
=
0
;
}
if
(
object
instanceof
THREE
.
Mesh
)
{
for
(
var
o
=
0
,
ol
=
_renderData
.
objects
.
length
;
o
<
ol
;
o
++
)
{
if
(
geometry
instanceof
THREE
.
BufferGeometry
)
{
var
object
=
_renderData
.
objects
[
o
].
object
;
var
geometry
=
object
.
geometry
;
var
attributes
=
geometry
.
attributes
;
var
offsets
=
geometry
.
offsets
;
renderList
.
setObject
(
object
);
if
(
attributes
.
position
===
undefined
)
continue
;
_modelMatrix
=
object
.
matrixWorld
;
var
positions
=
attributes
.
position
.
array
;
_vertexCount
=
0
;
for
(
i
=
0
,
l
=
positions
.
length
;
i
<
l
;
i
+=
3
)
{
if
(
object
instanceof
THREE
.
Mesh
)
{
renderList
.
pushVertex
(
positions
[
i
],
positions
[
i
+
1
],
positions
[
i
+
2
]
);
if
(
geometry
instanceof
THREE
.
BufferGeometry
)
{
}
var
attributes
=
geometry
.
attributes
;
var
offsets
=
geometry
.
offsets
;
if
(
attributes
.
normal
!==
undefined
)
{
if
(
attributes
.
position
===
undefined
)
continue
;
var
normals
=
attributes
.
normal
.
array
;
var
positions
=
attributes
.
position
.
array
;
for
(
i
=
0
,
l
=
normal
s
.
length
;
i
<
l
;
i
+=
3
)
{
for
(
i
=
0
,
l
=
position
s
.
length
;
i
<
l
;
i
+=
3
)
{
renderList
.
pushNormal
(
normals
[
i
],
normals
[
i
+
1
],
normal
s
[
i
+
2
]
);
renderList
.
pushVertex
(
positions
[
i
],
positions
[
i
+
1
],
position
s
[
i
+
2
]
);
}
}
}
if
(
attributes
.
normal
!==
undefined
)
{
if
(
attributes
.
uv
!==
undefined
)
{
var
normals
=
attributes
.
normal
.
array
;
var
uvs
=
attributes
.
uv
.
array
;
for
(
i
=
0
,
l
=
normals
.
length
;
i
<
l
;
i
+=
3
)
{
for
(
i
=
0
,
l
=
uvs
.
length
;
i
<
l
;
i
+=
2
)
{
renderList
.
pushNormal
(
normals
[
i
],
normals
[
i
+
1
],
normals
[
i
+
2
]
);
renderList
.
pushUv
(
uvs
[
i
],
uvs
[
i
+
1
]
);
}
}
}
}
if
(
attributes
.
uv
!==
undefined
)
{
if
(
attributes
.
index
!==
undefined
)
{
var
uvs
=
attributes
.
uv
.
array
;
var
indices
=
attributes
.
index
.
array
;
for
(
i
=
0
,
l
=
uvs
.
length
;
i
<
l
;
i
+=
2
)
{
if
(
offsets
.
length
>
0
)
{
renderList
.
pushUv
(
uvs
[
i
],
uvs
[
i
+
1
]
);
for
(
o
=
0
;
o
<
offsets
.
length
;
o
++
)
{
}
var
offset
=
offsets
[
o
];
var
index
=
offset
.
index
;
}
for
(
i
=
offset
.
start
,
l
=
offset
.
start
+
offset
.
count
;
i
<
l
;
i
+=
3
)
{
if
(
attributes
.
index
!==
undefined
)
{
renderList
.
pushTriangle
(
indices
[
i
]
+
index
,
indices
[
i
+
1
]
+
index
,
indices
[
i
+
2
]
+
index
)
;
var
indices
=
attributes
.
index
.
array
;
}
if
(
offsets
.
length
>
0
)
{
}
for
(
o
=
0
;
o
<
offsets
.
length
;
o
++
)
{
}
else
{
var
offset
=
offsets
[
o
];
var
index
=
offset
.
index
;
for
(
i
=
0
,
l
=
indices
.
length
;
i
<
l
;
i
+=
3
)
{
for
(
i
=
offset
.
start
,
l
=
offset
.
start
+
offset
.
count
;
i
<
l
;
i
+=
3
)
{
renderList
.
pushTriangle
(
indices
[
i
]
,
indices
[
i
+
1
],
indices
[
i
+
2
]
);
renderList
.
pushTriangle
(
indices
[
i
]
+
index
,
indices
[
i
+
1
]
+
index
,
indices
[
i
+
2
]
+
index
);
}
...
...
@@ -470,870 +459,875 @@ define(['three'], function(THREE, BSPTree){
}
else
{
for
(
i
=
0
,
l
=
positions
.
length
/
3
;
i
<
l
;
i
+=
3
)
{
for
(
i
=
0
,
l
=
indices
.
length
;
i
<
l
;
i
+=
3
)
{
renderList
.
pushTriangle
(
i
,
i
+
1
,
i
+
2
);
renderList
.
pushTriangle
(
i
ndices
[
i
],
indices
[
i
+
1
],
indices
[
i
+
2
]
);
}
}
}
else
if
(
geometry
instanceof
THREE
.
Geometry
)
{
}
else
{
var
vertices
=
geometry
.
vertices
;
var
faces
=
geometry
.
faces
;
var
faceVertexUvs
=
geometry
.
faceVertexUvs
[
0
];
for
(
i
=
0
,
l
=
positions
.
length
/
3
;
i
<
l
;
i
+=
3
)
{
_normalMatrix
.
getNormalMatrix
(
_modelMatrix
);
renderList
.
pushTriangle
(
i
,
i
+
1
,
i
+
2
);
var
isFaceMaterial
=
object
.
material
instanceof
THREE
.
MeshFaceMaterial
;
var
objectMaterials
=
isFaceMaterial
===
true
?
object
.
material
:
null
;
}
for
(
var
v
=
0
,
vl
=
vertices
.
length
;
v
<
vl
;
v
++
)
{
}
var
vertex
=
vertices
[
v
];
renderList
.
pushVertex
(
vertex
.
x
,
vertex
.
y
,
vertex
.
z
);
}
else
if
(
geometry
instanceof
THREE
.
Geometry
)
{
}
var
vertices
=
geometry
.
vertices
;
var
faces
=
geometry
.
faces
;
var
faceVertexUvs
=
geometry
.
faceVertexUvs
[
0
];
for
(
var
f
=
0
,
fl
=
faces
.
length
;
f
<
fl
;
f
++
)
{
_normalMatrix
.
getNormalMatrix
(
_modelMatrix
);
var
face
=
faces
[
f
];
var
isFaceMaterial
=
object
.
material
instanceof
THREE
.
MeshFaceMaterial
;
var
objectMaterials
=
isFaceMaterial
===
true
?
object
.
material
:
null
;
var
material
;
if
(
isFaceMaterial
===
true
){
material
=
objectMaterials
.
materials
[
face
.
materialIndex
];
}
else
{
material
=
object
.
material
;
}
for
(
var
v
=
0
,
vl
=
vertices
.
length
;
v
<
vl
;
v
++
)
{
if
(
material
===
undefined
)
continue
;
var
vertex
=
vertices
[
v
];
renderList
.
pushVertex
(
vertex
.
x
,
vertex
.
y
,
vertex
.
z
);
var
side
=
material
.
side
;
}
var
v1
=
_vertexPool
[
face
.
a
];
var
v2
=
_vertexPool
[
face
.
b
];
var
v3
=
_vertexPool
[
face
.
c
];
for
(
var
f
=
0
,
fl
=
faces
.
length
;
f
<
fl
;
f
++
)
{
if
(
material
.
morphTargets
===
true
)
{
var
face
=
faces
[
f
];
var
morphTargets
=
geometry
.
morphTargets
;
var
morphInfluences
=
object
.
morphTargetInfluences
;
var
material
;
if
(
isFaceMaterial
===
true
){
material
=
objectMaterials
.
materials
[
face
.
materialIndex
];
}
else
{
material
=
object
.
material
;
}
var
v1p
=
v1
.
position
;
var
v2p
=
v2
.
position
;
var
v3p
=
v3
.
position
;
if
(
material
===
undefined
)
continue
;
_vA
.
set
(
0
,
0
,
0
);
_vB
.
set
(
0
,
0
,
0
);
_vC
.
set
(
0
,
0
,
0
);
var
side
=
material
.
side
;
for
(
var
t
=
0
,
tl
=
morphTargets
.
length
;
t
<
tl
;
t
++
)
{
var
v1
=
_vertexPool
[
face
.
a
];
var
v2
=
_vertexPool
[
face
.
b
];
var
v3
=
_vertexPool
[
face
.
c
];
var
influence
=
morphInfluences
[
t
];
if
(
material
.
morphTargets
===
true
)
{
if
(
influence
===
0
)
continue
;
var
morphTargets
=
geometry
.
morphTargets
;
var
morphInfluences
=
object
.
morphTargetInfluences
;
var
targets
=
morphTargets
[
t
].
vertices
;
var
v1p
=
v1
.
position
;
var
v2p
=
v2
.
position
;
var
v3p
=
v3
.
position
;
_vA
.
x
+=
(
targets
[
face
.
a
].
x
-
v1p
.
x
)
*
influence
;
_vA
.
y
+=
(
targets
[
face
.
a
].
y
-
v1p
.
y
)
*
influence
;
_vA
.
z
+=
(
targets
[
face
.
a
].
z
-
v1p
.
z
)
*
influence
;
_vA
.
set
(
0
,
0
,
0
)
;
_vB
.
set
(
0
,
0
,
0
)
;
_vC
.
set
(
0
,
0
,
0
)
;
_vB
.
x
+=
(
targets
[
face
.
b
].
x
-
v2p
.
x
)
*
influence
;
_vB
.
y
+=
(
targets
[
face
.
b
].
y
-
v2p
.
y
)
*
influence
;
_vB
.
z
+=
(
targets
[
face
.
b
].
z
-
v2p
.
z
)
*
influence
;
for
(
var
t
=
0
,
tl
=
morphTargets
.
length
;
t
<
tl
;
t
++
)
{
_vC
.
x
+=
(
targets
[
face
.
c
].
x
-
v3p
.
x
)
*
influence
;
_vC
.
y
+=
(
targets
[
face
.
c
].
y
-
v3p
.
y
)
*
influence
;
_vC
.
z
+=
(
targets
[
face
.
c
].
z
-
v3p
.
z
)
*
influence
;
var
influence
=
morphInfluences
[
t
];
}
if
(
influence
===
0
)
continue
;
var
targets
=
morphTargets
[
t
].
vertices
;
_vA
.
x
+=
(
targets
[
face
.
a
].
x
-
v1p
.
x
)
*
influence
;
_vA
.
y
+=
(
targets
[
face
.
a
].
y
-
v1p
.
y
)
*
influence
;
_vA
.
z
+=
(
targets
[
face
.
a
].
z
-
v1p
.
z
)
*
influence
;
v1
.
position
.
add
(
_vA
)
;
v2
.
position
.
add
(
_vB
)
;
v3
.
position
.
add
(
_vC
)
;
_vB
.
x
+=
(
targets
[
face
.
b
].
x
-
v2p
.
x
)
*
influence
;
_vB
.
y
+=
(
targets
[
face
.
b
].
y
-
v2p
.
y
)
*
influence
;
_vB
.
z
+=
(
targets
[
face
.
b
].
z
-
v2p
.
z
)
*
influence
;
renderList
.
projectVertex
(
v1
)
;
renderList
.
projectVertex
(
v2
)
;
renderList
.
projectVertex
(
v3
)
;
_vC
.
x
+=
(
targets
[
face
.
c
].
x
-
v3p
.
x
)
*
influence
;
_vC
.
y
+=
(
targets
[
face
.
c
].
y
-
v3p
.
y
)
*
influence
;
_vC
.
z
+=
(
targets
[
face
.
c
].
z
-
v3p
.
z
)
*
influence
;
}
if
(
renderList
.
checkTriangleVisibility
(
v1
,
v2
,
v3
)
===
false
)
continue
;
v1
.
position
.
add
(
_vA
);
v2
.
position
.
add
(
_vB
);
v3
.
position
.
add
(
_vC
);
var
visible
=
renderList
.
checkBackfaceCulling
(
v1
,
v2
,
v3
);
renderList
.
projectVertex
(
v1
);
renderList
.
projectVertex
(
v2
);
renderList
.
projectVertex
(
v3
);
if
(
side
!==
THREE
.
DoubleSide
)
{
if
(
side
===
THREE
.
FrontSide
&&
visible
===
false
)
continue
;
if
(
side
===
THREE
.
BackSide
&&
visible
===
true
)
continue
;
}
}
if
(
renderList
.
checkTriangleVisibility
(
v1
,
v2
,
v3
)
===
false
)
continue
;
_face
=
getNextFaceInPool
(
);
var
visible
=
renderList
.
checkBackfaceCulling
(
v1
,
v2
,
v3
);
_face
.
id
=
object
.
id
;
_face
.
priority
=
face
.
priority
;
_face
.
v1
.
copy
(
v1
);
_face
.
v2
.
copy
(
v2
);
_face
.
v3
.
copy
(
v3
);
if
(
side
!==
THREE
.
DoubleSide
)
{
if
(
side
===
THREE
.
FrontSide
&&
visible
===
false
)
continue
;
if
(
side
===
THREE
.
BackSide
&&
visible
===
true
)
continue
;
}
_face
.
normalModel
.
copy
(
face
.
normal
);
_face
=
getNextFaceInPool
(
);
if
(
visible
===
false
&&
(
side
===
THREE
.
BackSide
||
side
===
THREE
.
DoubleSide
)
)
{
_face
.
id
=
object
.
id
;
_face
.
priority
=
face
.
priority
;
_face
.
v1
.
copy
(
v1
);
_face
.
v2
.
copy
(
v2
);
_face
.
v3
.
copy
(
v3
);
_face
.
normalModel
.
negate
(
);
_face
.
normalModel
.
copy
(
face
.
normal
);
}
if
(
visible
===
false
&&
(
side
===
THREE
.
BackSide
||
side
===
THREE
.
DoubleSide
)
)
{
_face
.
normalModel
.
applyMatrix3
(
_normalMatrix
).
normaliz
e
();
_face
.
normalModel
.
negat
e
();
var
faceVertexNormals
=
face
.
vertexNormals
;
}
for
(
var
n
=
0
,
nl
=
Math
.
min
(
faceVertexNormals
.
length
,
3
);
n
<
nl
;
n
++
)
{
_face
.
normalModel
.
applyMatrix3
(
_normalMatrix
).
normalize
();
var
normalModel
=
_face
.
vertexNormalsModel
[
n
];
normalModel
.
copy
(
faceVertexNormals
[
n
]
);
var
faceVertexNormals
=
face
.
vertexNormals
;
if
(
visible
===
false
&&
(
side
===
THREE
.
BackSide
||
side
===
THREE
.
DoubleSide
)
)
{
for
(
var
n
=
0
,
nl
=
Math
.
min
(
faceVertexNormals
.
length
,
3
);
n
<
nl
;
n
++
)
{
normalModel
.
negate
();
var
normalModel
=
_face
.
vertexNormalsModel
[
n
];
normalModel
.
copy
(
faceVertexNormals
[
n
]
);
}
if
(
visible
===
false
&&
(
side
===
THREE
.
BackSide
||
side
===
THREE
.
DoubleSide
)
)
{
normalModel
.
applyMatrix3
(
_normalMatrix
).
normaliz
e
();
normalModel
.
negat
e
();
}
_face
.
vertexNormalsLength
=
faceVertexNormals
.
length
;
normalModel
.
applyMatrix3
(
_normalMatrix
).
normalize
()
;
var
vertexUvs
=
faceVertexUvs
[
f
];
}
if
(
vertexUvs
!==
undefined
)
{
_face
.
vertexNormalsLength
=
faceVertexNormals
.
length
;
for
(
var
u
=
0
;
u
<
3
;
u
++
)
{
var
vertexUvs
=
faceVertexUvs
[
f
];
_face
.
uvs
[
u
].
copy
(
vertexUvs
[
u
]
);
if
(
vertexUvs
!==
undefined
)
{
}
for
(
var
u
=
0
;
u
<
3
;
u
++
)
{
_face
.
uvs
[
u
].
copy
(
vertexUvs
[
u
]
);
}
_face
.
color
=
face
.
color
;
_face
.
material
=
material
;
}
_face
.
z
=
(
v1
.
positionScreen
.
z
+
v2
.
positionScreen
.
z
+
v3
.
positionScreen
.
z
)
/
3
;
_face
.
color
=
face
.
color
;
_face
.
material
=
material
;
_renderData
.
elements
.
push
(
_face
)
;
_face
.
z
=
(
v1
.
positionScreen
.
z
+
v2
.
positionScreen
.
z
+
v3
.
positionScreen
.
z
)
/
3
;
}
_renderData
.
elements
.
push
(
_face
);
}
}
else
if
(
object
instanceof
THREE
.
Line
)
{
}
if
(
geometry
instanceof
THREE
.
BufferGeometry
)
{
}
else
if
(
object
instanceof
THREE
.
Line
)
{
var
attributes
=
geometry
.
attributes
;
if
(
geometry
instanceof
THREE
.
BufferGeometry
)
{
if
(
attributes
.
position
!==
undefined
)
{
var
attributes
=
geometry
.
attributes
;
var
positions
=
attributes
.
position
.
array
;
if
(
attributes
.
position
!==
undefined
)
{
for
(
i
=
0
,
l
=
positions
.
length
;
i
<
l
;
i
+=
3
)
{
var
positions
=
attributes
.
position
.
array
;
renderList
.
pushVertex
(
positions
[
i
],
positions
[
i
+
1
],
positions
[
i
+
2
]
);
for
(
i
=
0
,
l
=
positions
.
length
;
i
<
l
;
i
+=
3
)
{
}
renderList
.
pushVertex
(
positions
[
i
],
positions
[
i
+
1
],
positions
[
i
+
2
]
);
if
(
attributes
.
index
!==
undefined
)
{
}
var
indices
=
attributes
.
index
.
array
;
if
(
attributes
.
index
!==
undefined
)
{
for
(
i
=
0
,
l
=
indices
.
length
;
i
<
l
;
i
+=
2
)
{
var
indices
=
attributes
.
index
.
array
;
renderList
.
pushLine
(
indices
[
i
],
indices
[
i
+
1
]
);
for
(
i
=
0
,
l
=
indices
.
length
;
i
<
l
;
i
+=
2
)
{
}
renderList
.
pushLine
(
indices
[
i
],
indices
[
i
+
1
]
);
}
else
{
}
var
step
=
object
.
mode
===
THREE
.
LinePieces
?
2
:
1
;
}
else
{
for
(
i
=
0
,
l
=
(
positions
.
length
/
3
)
-
1
;
i
<
l
;
i
+=
step
)
{
var
step
=
object
.
mode
===
THREE
.
LinePieces
?
2
:
1
;
renderList
.
pushLine
(
i
,
i
+
1
);
for
(
i
=
0
,
l
=
(
positions
.
length
/
3
)
-
1
;
i
<
l
;
i
+=
step
)
{
}
renderList
.
pushLine
(
i
,
i
+
1
);
}
}
}
else
if
(
geometry
instanceof
THREE
.
Geometry
)
{
_modelViewProjectionMatrix
.
multiplyMatrices
(
_viewProjectionMatrix
,
_modelMatrix
);
}
var
vertices
=
object
.
geometry
.
vertices
;
}
else
if
(
geometry
instanceof
THREE
.
Geometry
)
{
if
(
vertices
.
length
===
0
)
continue
;
_modelViewProjectionMatrix
.
multiplyMatrices
(
_viewProjectionMatrix
,
_modelMatrix
)
;
var
v1
=
getNextVertexInPool
();
v1
.
positionWorld
.
copy
(
vertices
[
0
]
);
v1
.
positionScreen
.
copy
(
vertices
[
0
]
).
applyMatrix4
(
_modelViewProjectionMatrix
);
var
vertices
=
object
.
geometry
.
vertices
;
// Handle LineStrip and LinePieces
var
step
=
object
.
mode
===
THREE
.
LinePieces
?
2
:
1
;
if
(
vertices
.
length
===
0
)
continue
;
for
(
var
v
=
1
,
vl
=
vertices
.
length
;
v
<
vl
;
v
++
)
{
var
v1
=
getNextVertexInPool
();
v1
.
positionWorld
.
copy
(
vertices
[
0
]
);
v1
.
positionScreen
.
copy
(
vertices
[
0
]
).
applyMatrix4
(
_modelViewProjectionMatrix
);
v1
=
getNextVertexInPool
();
v1
.
positionWorld
.
copy
(
vertices
[
v
]
);
v1
.
positionScreen
.
copy
(
vertices
[
v
]
).
applyMatrix4
(
_modelViewProjectionMatrix
);
// Handle LineStrip and LinePieces
var
step
=
object
.
mode
===
THREE
.
LinePieces
?
2
:
1
;
if
(
(
v
+
1
)
%
step
>
0
)
continue
;
for
(
var
v
=
1
,
vl
=
vertices
.
length
;
v
<
vl
;
v
++
)
{
v2
=
_vertexPool
[
_vertexCount
-
2
];
v1
=
getNextVertexInPool
();
v1
.
positionWorld
.
copy
(
vertices
[
v
]
);
v1
.
positionScreen
.
copy
(
vertices
[
v
]
).
applyMatrix4
(
_modelViewProjectionMatrix
);
_clippedVertex1PositionScreen
.
copy
(
v1
.
positionScreen
);
_clippedVertex2PositionScreen
.
copy
(
v2
.
positionScreen
);
if
(
(
v
+
1
)
%
step
>
0
)
continue
;
if
(
clipLine
(
_clippedVertex1PositionScreen
,
_clippedVertex2PositionScreen
)
===
true
)
{
v2
=
_vertexPool
[
_vertexCount
-
2
];
// Perform the perspective divide
_clippedVertex1PositionScreen
.
multiplyScalar
(
1
/
_clippedVertex1PositionScreen
.
w
);
_clippedVertex2PositionScreen
.
multiplyScalar
(
1
/
_clippedVertex2PositionScreen
.
w
);
_clippedVertex1PositionScreen
.
copy
(
v1
.
positionScreen
);
_clippedVertex2PositionScreen
.
copy
(
v2
.
positionScreen
);
_line
=
getNextLineInPool
();
if
(
clipLine
(
_clippedVertex1PositionScreen
,
_clippedVertex2PositionScreen
)
===
true
)
{
_line
.
id
=
object
.
id
;
_line
.
v1
.
positionScreen
.
copy
(
_clippedVertex1PositionScreen
);
_line
.
v1
.
positionWorld
.
copy
(
v1
.
positionWorld
);
_line
.
v2
.
positionScreen
.
copy
(
_clippedVertex2PositionScreen
);
_line
.
v2
.
positionWorld
.
copy
(
v2
.
positionWorld
);
// Perform the perspective divide
_clippedVertex1PositionScreen
.
multiplyScalar
(
1
/
_clippedVertex1PositionScreen
.
w
);
_clippedVertex2PositionScreen
.
multiplyScalar
(
1
/
_clippedVertex2PositionScreen
.
w
);
_line
.
z
=
Math
.
max
(
_clippedVertex1PositionScreen
.
z
,
_clippedVertex2PositionScreen
.
z
);
_line
=
getNextLineInPool
(
);
_line
.
material
=
object
.
material
;
_line
.
id
=
object
.
id
;
_line
.
v1
.
positionScreen
.
copy
(
_clippedVertex1PositionScreen
);
_line
.
v1
.
positionWorld
.
copy
(
v1
.
positionWorld
);
_line
.
v2
.
positionScreen
.
copy
(
_clippedVertex2PositionScreen
);
_line
.
v2
.
positionWorld
.
copy
(
v2
.
positionWorld
);
if
(
object
.
material
.
vertexColors
===
THREE
.
VertexColors
)
{
_line
.
z
=
Math
.
max
(
_clippedVertex1PositionScreen
.
z
,
_clippedVertex2PositionScreen
.
z
);
_line
.
vertexColors
[
0
].
copy
(
object
.
geometry
.
colors
[
v
]
);
_line
.
vertexColors
[
1
].
copy
(
object
.
geometry
.
colors
[
v
-
1
]
);
_line
.
material
=
object
.
material
;
}
if
(
object
.
material
.
vertexColors
===
THREE
.
VertexColors
)
{
_renderData
.
elements
.
push
(
_line
);
_line
.
vertexColors
[
0
].
copy
(
object
.
geometry
.
colors
[
v
]
);
_line
.
vertexColors
[
1
].
copy
(
object
.
geometry
.
colors
[
v
-
1
]
);
}
_renderData
.
elements
.
push
(
_line
);
}
}
}
else
if
(
object
instanceof
THREE
.
Sprite
)
{
}
_vector4
.
set
(
_modelMatrix
.
elements
[
12
],
_modelMatrix
.
elements
[
13
],
_modelMatrix
.
elements
[
14
],
1
);
_vector4
.
applyMatrix4
(
_viewProjectionMatrix
);
}
else
if
(
object
instanceof
THREE
.
Sprite
)
{
var
invW
=
1
/
_vector4
.
w
;
_vector4
.
set
(
_modelMatrix
.
elements
[
12
],
_modelMatrix
.
elements
[
13
],
_modelMatrix
.
elements
[
14
],
1
);
_vector4
.
applyMatrix4
(
_viewProjectionMatrix
);
_vector4
.
z
*=
invW
;
var
invW
=
1
/
_vector4
.
w
;
if
(
_vector4
.
z
>=
-
1
&&
_vector4
.
z
<=
1
)
{
_vector4
.
z
*=
invW
;
_sprite
=
getNextSpriteInPool
();
_sprite
.
id
=
object
.
id
;
_sprite
.
x
=
_vector4
.
x
*
invW
;
_sprite
.
y
=
_vector4
.
y
*
invW
;
_sprite
.
z
=
_vector4
.
z
;
_sprite
.
object
=
object
;
if
(
_vector4
.
z
>=
-
1
&&
_vector4
.
z
<=
1
)
{
_sprite
.
rotation
=
object
.
rotation
;
_sprite
=
getNextSpriteInPool
();
_sprite
.
id
=
object
.
id
;
_sprite
.
x
=
_vector4
.
x
*
invW
;
_sprite
.
y
=
_vector4
.
y
*
invW
;
_sprite
.
z
=
_vector4
.
z
;
_sprite
.
object
=
object
;
_sprite
.
scale
.
x
=
object
.
scale
.
x
*
Math
.
abs
(
_sprite
.
x
-
(
_vector4
.
x
+
camera
.
projectionMatrix
.
elements
[
0
]
)
/
(
_vector4
.
w
+
camera
.
projectionMatrix
.
elements
[
12
]
)
);
_sprite
.
scale
.
y
=
object
.
scale
.
y
*
Math
.
abs
(
_sprite
.
y
-
(
_vector4
.
y
+
camera
.
projectionMatrix
.
elements
[
5
]
)
/
(
_vector4
.
w
+
camera
.
projectionMatrix
.
elements
[
13
]
)
);
_sprite
.
rotation
=
object
.
rotation
;
_sprite
.
material
=
object
.
material
;
_sprite
.
scale
.
x
=
object
.
scale
.
x
*
Math
.
abs
(
_sprite
.
x
-
(
_vector4
.
x
+
camera
.
projectionMatrix
.
elements
[
0
]
)
/
(
_vector4
.
w
+
camera
.
projectionMatrix
.
elements
[
12
]
)
);
_sprite
.
scale
.
y
=
object
.
scale
.
y
*
Math
.
abs
(
_sprite
.
y
-
(
_vector4
.
y
+
camera
.
projectionMatrix
.
elements
[
5
]
)
/
(
_vector4
.
w
+
camera
.
projectionMatrix
.
elements
[
13
]
)
);
_renderData
.
elements
.
push
(
_sprite
)
;
_sprite
.
material
=
object
.
material
;
}
_renderData
.
elements
.
push
(
_sprite
);
}
}
if
(
sortElements
===
true
)
{
}
//_renderData.elements.sort( customSort );
if
(
sortElements
===
true
)
{
}
// Build the BSP tree
var
btree
=
new
BSPTree
(
_renderData
.
elements
);
_renderData
.
elements
=
btree
.
toArray
();
//_renderData.elements.length = 15;
return
_renderData
;
//_renderData.elements.sort( customSort );
}
;
}
// Build the BSP tree
var
btree
=
new
BSPTree
(
_renderData
.
elements
);
_renderData
.
elements
=
btree
.
toArray
();
//_renderData.elements.length = 15;
// Pools
return
_renderData
;
function
getNextObjectInPool
()
{
};
if
(
_objectCount
===
_objectPoolLength
)
{
// Pools
var
object
=
new
Projector
.
RenderableObject
();
_objectPool
.
push
(
object
);
_objectPoolLength
++
;
_objectCount
++
;
return
object
;
function
getNextObjectInPool
()
{
}
if
(
_objectCount
===
_objectPoolLength
)
{
return
_objectPool
[
_objectCount
++
];
var
object
=
new
RenderableObject
();
_objectPool
.
push
(
object
);
_objectPoolLength
++
;
_objectCount
++
;
return
object
;
}
function
getNextVertexInPool
()
{
return
_objectPool
[
_objectCount
++
];
if
(
_vertexCount
===
_vertexPoolLength
)
{
}
var
vertex
=
new
Projector
.
RenderableVertex
();
_vertexPool
.
push
(
vertex
);
_vertexPoolLength
++
;
_vertexCount
++
;
return
vertex
;
function
getNextVertexInPool
()
{
}
if
(
_vertexCount
===
_vertexPoolLength
)
{
return
_vertexPool
[
_vertexCount
++
];
var
vertex
=
new
RenderableVertex
();
_vertexPool
.
push
(
vertex
);
_vertexPoolLength
++
;
_vertexCount
++
;
return
vertex
;
}
function
getNextFaceInPool
()
{
return
_vertexPool
[
_vertexCount
++
];
if
(
_faceCount
===
_facePoolLength
)
{
}
var
face
=
new
Projector
.
RenderableFace
();
_facePool
.
push
(
face
);
_facePoolLength
++
;
_faceCount
++
;
return
face
;
function
getNextFaceInPool
()
{
}
return
_facePool
[
_faceCount
++
];
if
(
_faceCount
===
_facePoolLength
)
{
var
face
=
new
RenderableFace
();
_facePool
.
push
(
face
);
_facePoolLength
++
;
_faceCount
++
;
return
face
;
}
function
getNextLineInPool
()
{
return
_facePool
[
_faceCount
++
];
if
(
_lineCount
===
_linePoolLength
)
{
var
line
=
new
Projector
.
RenderableLine
();
_linePool
.
push
(
line
);
_linePoolLength
++
;
_lineCount
++
;
return
line
;
}
}
function
getNextLineInPool
()
{
return
_linePool
[
_lineCount
++
];
if
(
_lineCount
===
_linePoolLength
)
{
var
line
=
new
RenderableLine
();
_linePool
.
push
(
line
);
_linePoolLength
++
;
_lineCount
++
;
return
line
;
}
function
getNextSpriteInPool
()
{
return
_linePool
[
_lineCount
++
];
if
(
_spriteCount
===
_spritePoolLength
)
{
}
var
sprite
=
new
Projector
.
RenderableSprite
();
_spritePool
.
push
(
sprite
);
_spritePoolLength
++
;
_spriteCount
++
;
return
sprite
;
function
getNextSpriteInPool
()
{
}
if
(
_spriteCount
===
_spritePoolLength
)
{
var
sprite
=
new
RenderableSprite
();
_spritePool
.
push
(
sprite
);
_spritePoolLength
++
;
_spriteCount
++
;
return
sprite
;
}
return
_spritePool
[
_spriteCount
++
];
return
_spritePool
[
_spriteCount
++
];
}
function
BSPTree
(
data
){
if
(
data
.
length
){
this
.
root
=
BSPTree
.
utils
.
createNode
(
data
[
0
]);
for
(
var
i
=
1
;
i
<
data
.
length
;
i
++
){
this
.
insert
(
data
[
i
]);
}
}
}
BSPTree
.
prototype
.
insert
=
function
(
element
,
compareWith
){
compareWith
=
compareWith
||
this
.
root
;
var
node
=
(
element
instanceof
BSPTree
.
Node
)
?
element
:
BSPTree
.
utils
.
createNode
(
element
);
var
comparison
=
node
.
isBehind
(
compareWith
);
if
(
comparison
===
undefined
){
var
fragments
=
node
.
separate
(
compareWith
.
getNormal
(),
compareWith
.
getPointOnPlane
()
);
var
self
=
this
;
fragments
.
forEach
(
function
(
f
){
self
.
insert
(
f
,
compareWith
);
});
return
;
}
function
BSPTree
(
data
){
if
(
data
.
length
){
this
.
root
=
BSPTree
.
utils
.
createNode
(
data
[
0
]);
for
(
var
i
=
1
;
i
<
data
.
length
;
i
++
){
this
.
insert
(
data
[
i
]);
}
}
}
BSPTree
.
prototype
.
insert
=
function
(
element
,
compareWith
){
compareWith
=
compareWith
||
this
.
root
;
var
node
=
(
element
instanceof
BSPTree
.
Node
)
?
element
:
BSPTree
.
utils
.
createNode
(
element
);
var
comparison
=
node
.
isBehind
(
compareWith
);
if
(
comparison
===
undefined
){
var
fragments
=
node
.
separate
(
compareWith
.
getNormal
(),
compareWith
.
getPointOnPlane
()
);
var
self
=
this
;
fragments
.
forEach
(
function
(
f
){
self
.
insert
(
f
,
compareWith
);
});
return
;
}
if
(
comparison
===
0
){
var
nodePriority
=
BSPTree
.
utils
.
getPriority
(
node
);
var
compareWithPriority
=
BSPTree
.
utils
.
getPriority
(
compareWith
);
if
(
nodePriority
>
compareWithPriority
){
comparison
=
-
1
;
}
else
{
comparison
=
1
;
}
}
if
(
comparison
===
1
){
if
(
!
compareWith
.
back
){
compareWith
.
back
=
node
;
}
else
{
this
.
insert
(
node
,
compareWith
.
back
);
}
if
(
comparison
===
0
){
var
nodePriority
=
BSPTree
.
utils
.
getPriority
(
node
);
var
compareWithPriority
=
BSPTree
.
utils
.
getPriority
(
compareWith
);
if
(
nodePriority
>
compareWithPriority
){
comparison
=
-
1
;
}
else
{
if
(
!
compareWith
.
front
){
compareWith
.
front
=
node
;
}
else
{
this
.
insert
(
node
,
compareWith
.
front
);
}
}
};
BSPTree
.
prototype
.
toArray
=
function
(){
var
output
=
[];
if
(
this
.
root
){
this
.
root
.
traverse
(
function
(
elem
){
output
.
push
(
elem
);
});
comparison
=
1
;
}
return
output
;
}
BSPTree
.
utils
=
{
createNode
:
function
(
element
){
return
new
(
element
.
v3
?
BSPTree
.
TriangleNode
:
BSPTree
.
LineNode
)(
element
);
},
getPointSign
:
function
(
normal
,
point
,
pointOnPlane
){
return
this
.
sign
(
normal
.
dot
(
point
.
clone
().
sub
(
pointOnPlane
)));
},
getPriority
:
function
(
node
){
if
(
typeof
node
.
element
.
priority
===
'number'
){
return
node
.
element
.
priority
;
}
else
{
return
0
;
}
},
isPointInSegment
:
function
(
point
,
p1
,
p2
){
// This function assumes that point lies on the line
// and determines whether it is in line _segment_
var
minX
=
Math
.
min
(
p1
.
x
,
p2
.
x
);
var
minY
=
Math
.
min
(
p1
.
y
,
p2
.
y
);
var
minZ
=
Math
.
min
(
p1
.
z
,
p2
.
z
);
var
maxX
=
Math
.
max
(
p1
.
x
,
p2
.
x
);
var
maxY
=
Math
.
max
(
p1
.
y
,
p2
.
y
);
var
maxZ
=
Math
.
max
(
p1
.
z
,
p2
.
z
);
return
(
point
.
x
>=
minX
&&
point
.
x
<=
maxX
)
&&
(
point
.
y
>=
minY
&&
point
.
y
<=
maxY
)
&&
(
point
.
z
>=
minZ
&&
point
.
z
<=
maxZ
);
},
isZero
:
function
(
x
){
return
Math
.
abs
(
x
)
<
this
.
EPSILON
;
},
linePlaneIntersection
:
function
(
normal
,
pointOnPlane
,
p1
,
p2
){
var
upper
=
pointOnPlane
.
clone
().
sub
(
p1
);
upper
=
upper
.
dot
(
normal
);
var
l
=
p2
.
clone
().
sub
(
p1
);
var
lower
=
l
.
dot
(
normal
);
if
(
lower
===
0
)
return
undefined
;
var
d
=
upper
/
lower
;
var
intersectionPoint
=
l
.
multiplyScalar
(
d
).
add
(
p1
);
return
BSPTree
.
utils
.
isPointInSegment
(
intersectionPoint
,
p1
,
p2
)
?
intersectionPoint
:
undefined
;
},
pointsEqual
:
function
(
p1
,
p2
){
return
this
.
isZero
(
p2
.
distanceTo
(
p1
));
},
projectVertex
:
function
(
vertex
){
var
oldModelMatrix
=
_modelMatrix
;
_modelMatrix
=
this
.
IDENTITY_MATRIX
;
renderList
.
projectVertex
(
vertex
);
vertex
.
positionScreen
.
w
=
1
;
_modelMatrix
=
oldModelMatrix
;
},
sign
:
function
(
x
){
if
(
this
.
isZero
(
x
)){
return
0
;
}
else
if
(
x
>
0
)
{
return
1
;
}
else
{
return
-
1
;
}
},
EPSILON
:
1
e
-
6
,
IDENTITY_MATRIX
:
new
THREE
.
Matrix4
()
}
BSPTree
.
Node
=
function
(){
this
.
back
=
null
;
this
.
front
=
null
;
}
BSPTree
.
Node
.
prototype
.
isBehind
=
function
(
node
){
var
normal
=
node
.
getNormal
();
var
point
=
node
.
getPointOnPlane
();
var
viewer
=
_camera
.
position
;
var
viewerSign
=
BSPTree
.
utils
.
getPointSign
(
normal
,
viewer
,
point
);
var
thisSign
=
this
.
getSign
(
normal
,
point
);
if
(
thisSign
===
undefined
)
return
undefined
;
if
(
thisSign
===
0
)
return
0
;
if
(
viewerSign
!==
thisSign
){
return
1
;
}
else
{
return
-
1
;
}
}
BSPTree
.
Node
.
prototype
.
traverse
=
function
(
callback
){
if
(
!
callback
){
return
;
}
if
(
comparison
===
1
){
if
(
!
compareWith
.
back
){
compareWith
.
back
=
node
;
}
else
{
this
.
insert
(
node
,
compareWith
.
back
);
}
if
(
this
.
back
){
this
.
back
.
traverse
(
callback
);
}
else
{
if
(
!
compareWith
.
front
){
compareWith
.
front
=
node
;
}
else
{
this
.
insert
(
node
,
compareWith
.
front
);
}
}
};
BSPTree
.
prototype
.
toArray
=
function
(){
var
output
=
[];
callback
(
this
.
element
);
if
(
this
.
front
){
this
.
front
.
traverse
(
callback
);
}
if
(
this
.
root
){
this
.
root
.
traverse
(
function
(
elem
){
output
.
push
(
elem
);
});
}
BSPTree
.
LineNode
=
function
(
element
){
this
.
element
=
element
;
this
.
isTriangle
=
false
;
};
BSPTree
.
LineNode
.
prototype
=
Object
.
create
(
BSPTree
.
Node
.
prototype
);
BSPTree
.
LineNode
.
prototype
.
getNormal
=
function
(){
var
l
=
new
THREE
.
Line3
(
this
.
element
.
v1
.
positionWorld
,
this
.
element
.
v2
.
positionWorld
);
var
pt
=
l
.
closestPointToPoint
(
_camera
.
position
,
false
);
return
pt
.
sub
(
_camera
.
position
);
}
BSPTree
.
LineNode
.
prototype
.
getPointOnPlane
=
function
(){
return
this
.
element
.
v1
.
positionWorld
;
}
BSPTree
.
LineNode
.
prototype
.
getSign
=
function
(
normal
,
pointOnPlane
){
var
s1
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v1
.
positionWorld
,
pointOnPlane
);
var
s2
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v2
.
positionWorld
,
pointOnPlane
);
var
sMax
=
Math
.
max
(
s1
,
s2
);
var
sMin
=
Math
.
min
(
s1
,
s2
);
switch
(
Math
.
abs
(
sMax
-
sMin
)){
case
0
:
return
sMax
;
case
1
:
return
sMax
||
sMin
;
case
2
:
return
undefined
;
default
:
throw
new
Error
(
'It looks like some unexpected FP error!'
);
return
output
;
}
BSPTree
.
utils
=
{
createNode
:
function
(
element
){
return
new
(
element
.
v3
?
BSPTree
.
TriangleNode
:
BSPTree
.
LineNode
)(
element
);
},
getPointSign
:
function
(
normal
,
point
,
pointOnPlane
){
return
this
.
sign
(
normal
.
dot
(
point
.
clone
().
sub
(
pointOnPlane
)));
},
getPriority
:
function
(
node
){
if
(
typeof
node
.
element
.
priority
===
'number'
){
return
node
.
element
.
priority
;
}
else
{
return
0
;
}
}
BSPTree
.
LineNode
.
prototype
.
separate
=
function
(
normal
,
point
){
var
intersectionPoint
=
BSPTree
.
utils
.
linePlaneIntersection
(
normal
,
point
,
this
.
element
.
v1
.
positionWorld
,
this
.
element
.
v2
.
positionWorld
);
if
(
intersectionPoint
){
var
newLine
=
getNextLineInPool
();
newLine
.
copy
(
this
.
element
);
var
vertex
=
getNextVertexInPool
();
vertex
.
position
.
copy
(
intersectionPoint
);
BSPTree
.
utils
.
projectVertex
(
vertex
);
newLine
.
v1
.
copy
(
vertex
);
newLine
.
v2
=
this
.
element
.
v2
;
this
.
element
.
v2
=
vertex
;
return
[
this
,
BSPTree
.
utils
.
createNode
(
newLine
)];
}
else
{
return
[
this
];
}
}
BSPTree
.
TriangleNode
=
function
(
element
){
this
.
element
=
element
;
this
.
isTriangle
=
true
;
};
BSPTree
.
TriangleNode
.
prototype
=
Object
.
create
(
BSPTree
.
Node
.
prototype
);
BSPTree
.
TriangleNode
.
prototype
.
getNormal
=
function
(){
return
this
.
element
.
normalModel
;
}
BSPTree
.
TriangleNode
.
prototype
.
getPointOnPlane
=
function
(){
return
this
.
element
.
v1
.
positionWorld
;
}
BSPTree
.
TriangleNode
.
prototype
.
getSign
=
function
(
normal
,
pointOnPlane
){
var
s1
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v1
.
positionWorld
,
pointOnPlane
);
var
s2
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v2
.
positionWorld
,
pointOnPlane
);
var
s3
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v3
.
positionWorld
,
pointOnPlane
);
var
sMax
=
Math
.
max
(
s1
,
s2
,
s3
);
var
sMin
=
Math
.
min
(
s1
,
s2
,
s3
);
switch
(
Math
.
abs
(
sMax
-
sMin
)){
case
0
:
return
sMax
;
case
1
:
return
sMax
||
sMin
;
case
2
:
return
undefined
;
default
:
throw
new
Error
(
'It looks like some unexpected FP error!'
);
},
isPointInSegment
:
function
(
point
,
p1
,
p2
){
// This function assumes that point lies on the line
// and determines whether it is in line _segment_
var
minX
=
Math
.
min
(
p1
.
x
,
p2
.
x
);
var
minY
=
Math
.
min
(
p1
.
y
,
p2
.
y
);
var
minZ
=
Math
.
min
(
p1
.
z
,
p2
.
z
);
var
maxX
=
Math
.
max
(
p1
.
x
,
p2
.
x
);
var
maxY
=
Math
.
max
(
p1
.
y
,
p2
.
y
);
var
maxZ
=
Math
.
max
(
p1
.
z
,
p2
.
z
);
return
(
point
.
x
>=
minX
&&
point
.
x
<=
maxX
)
&&
(
point
.
y
>=
minY
&&
point
.
y
<=
maxY
)
&&
(
point
.
z
>=
minZ
&&
point
.
z
<=
maxZ
);
},
isZero
:
function
(
x
){
return
Math
.
abs
(
x
)
<
this
.
EPSILON
;
},
linePlaneIntersection
:
function
(
normal
,
pointOnPlane
,
p1
,
p2
){
var
upper
=
pointOnPlane
.
clone
().
sub
(
p1
);
upper
=
upper
.
dot
(
normal
);
var
l
=
p2
.
clone
().
sub
(
p1
);
var
lower
=
l
.
dot
(
normal
);
if
(
lower
===
0
)
return
undefined
;
var
d
=
upper
/
lower
;
var
intersectionPoint
=
l
.
multiplyScalar
(
d
).
add
(
p1
);
return
BSPTree
.
utils
.
isPointInSegment
(
intersectionPoint
,
p1
,
p2
)
?
intersectionPoint
:
undefined
;
},
pointsEqual
:
function
(
p1
,
p2
){
return
this
.
isZero
(
p2
.
distanceTo
(
p1
));
},
projectVertex
:
function
(
vertex
){
var
oldModelMatrix
=
_modelMatrix
;
_modelMatrix
=
this
.
IDENTITY_MATRIX
;
renderList
.
projectVertex
(
vertex
);
vertex
.
positionScreen
.
w
=
1
;
_modelMatrix
=
oldModelMatrix
;
},
sign
:
function
(
x
){
if
(
this
.
isZero
(
x
)){
return
0
;
}
else
if
(
x
>
0
)
{
return
1
;
}
else
{
return
-
1
;
}
}
BSPTree
.
TriangleNode
.
prototype
.
separate
=
function
(
normal
,
pointOnPlane
){
var
p1
=
this
.
element
.
v1
.
positionWorld
;
var
p2
=
this
.
element
.
v2
.
positionWorld
;
var
p3
=
this
.
element
.
v3
.
positionWorld
;
// Intersection points
var
i12
=
BSPTree
.
utils
.
linePlaneIntersection
(
normal
,
pointOnPlane
,
p1
,
p2
);
var
i23
=
BSPTree
.
utils
.
linePlaneIntersection
(
normal
,
pointOnPlane
,
p2
,
p3
);
var
i31
=
BSPTree
.
utils
.
linePlaneIntersection
(
normal
,
pointOnPlane
,
p3
,
p1
);
if
(
i12
&&
i23
&&
i31
){
// Special case, one split point is a vertex
// In this case we split triangle into two
var
iVertex
,
iSide
;
var
vertex
=
getNextVertexInPool
();
var
newTriangle
=
getNextFaceInPool
();
newTriangle
.
copy
(
this
.
element
);
if
(
BSPTree
.
utils
.
pointsEqual
(
i12
,
i23
)){
vertex
.
position
=
i31
;
BSPTree
.
utils
.
projectVertex
(
vertex
);
this
.
element
.
v3
.
copy
(
vertex
);
newTriangle
.
v1
=
vertex
;
}
else
if
(
BSPTree
.
utils
.
pointsEqual
(
i23
,
i31
)){
vertex
.
position
=
i12
;
BSPTree
.
utils
.
projectVertex
(
vertex
);
this
.
element
.
v1
.
copy
(
vertex
);
newTriangle
.
v2
=
vertex
;
}
else
{
vertex
.
position
=
i23
;
BSPTree
.
utils
.
projectVertex
(
vertex
);
this
.
element
.
v2
.
copy
(
vertex
);
newTriangle
.
v3
=
vertex
;
}
return
[
this
,
BSPTree
.
utils
.
createNode
(
newTriangle
)];
}
else
{
var
t1
=
getNextFaceInPool
();
var
t2
=
getNextFaceInPool
();
t1
.
copy
(
this
.
element
);
t2
.
copy
(
this
.
element
);
var
v1
=
getNextVertexInPool
();
var
v2
=
getNextVertexInPool
();
// Split triangle into three triangles
if
(
!
i12
){
this
.
element
.
v1
.
position
=
i31
;
this
.
element
.
v2
.
position
=
i23
;
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v1
);
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v2
);
t1
.
v2
.
copy
(
this
.
element
.
v2
);
t1
.
v3
.
copy
(
this
.
element
.
v1
);
t2
.
v3
.
copy
(
this
.
element
.
v2
);
}
else
if
(
!
i23
){
this
.
element
.
v2
.
position
=
i12
;
this
.
element
.
v3
.
position
=
i31
;
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v2
);
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v3
);
t1
.
v1
.
copy
(
this
.
element
.
v2
);
t1
.
v3
.
copy
(
this
.
element
.
v3
);
t2
.
v1
.
copy
(
this
.
element
.
v3
);
}
else
{
this
.
element
.
v1
.
position
=
i12
;
this
.
element
.
v3
.
position
=
i23
;
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v1
);
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v3
);
t1
.
v1
.
copy
(
this
.
element
.
v1
);
t1
.
v2
.
copy
(
this
.
element
.
v3
);
t2
.
v2
.
copy
(
this
.
element
.
v1
);
}
return
[
this
,
BSPTree
.
utils
.
createNode
(
t1
),
BSPTree
.
utils
.
createNode
(
t2
)
]
}
}
},
EPSILON
:
1
e
-
6
,
IDENTITY_MATRIX
:
new
THREE
.
Matrix4
()
}
BSPTree
.
Node
=
function
(){
this
.
back
=
null
;
this
.
front
=
null
;
}
BSPTree
.
Node
.
prototype
.
isBehind
=
function
(
node
){
var
normal
=
node
.
getNormal
();
var
point
=
node
.
getPointOnPlane
();
var
viewer
=
_camera
.
position
;
var
viewerSign
=
BSPTree
.
utils
.
getPointSign
(
normal
,
viewer
,
point
);
var
thisSign
=
this
.
getSign
(
normal
,
point
);
function
painterSort
(
a
,
b
){
if
(
a
.
z
!==
b
.
z
)
{
if
(
thisSign
===
undefined
)
return
undefined
;
return
b
.
z
-
a
.
z
;
if
(
thisSign
===
0
)
return
0
;
// Fallback: compare ids
}
else
if
(
a
.
id
!==
b
.
id
)
{
if
(
viewerSign
!==
thisSign
){
return
1
;
}
else
{
return
-
1
;
}
}
return
a
.
id
-
b
.
id
;
BSPTree
.
Node
.
prototype
.
traverse
=
function
(
callback
){
if
(
!
callback
){
return
;
}
if
(
this
.
back
){
this
.
back
.
traverse
(
callback
);
}
callback
(
this
.
element
);
if
(
this
.
front
){
this
.
front
.
traverse
(
callback
);
}
}
BSPTree
.
LineNode
=
function
(
element
){
this
.
element
=
element
;
this
.
isTriangle
=
false
;
};
BSPTree
.
LineNode
.
prototype
=
Object
.
create
(
BSPTree
.
Node
.
prototype
);
BSPTree
.
LineNode
.
prototype
.
getNormal
=
function
(){
var
l
=
new
THREE
.
Line3
(
this
.
element
.
v1
.
positionWorld
,
this
.
element
.
v2
.
positionWorld
);
var
pt
=
l
.
closestPointToPoint
(
_camera
.
position
,
false
);
return
pt
.
sub
(
_camera
.
position
);
}
BSPTree
.
LineNode
.
prototype
.
getPointOnPlane
=
function
(){
return
this
.
element
.
v1
.
positionWorld
;
}
BSPTree
.
LineNode
.
prototype
.
getSign
=
function
(
normal
,
pointOnPlane
){
var
s1
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v1
.
positionWorld
,
pointOnPlane
);
var
s2
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v2
.
positionWorld
,
pointOnPlane
);
var
sMax
=
Math
.
max
(
s1
,
s2
);
var
sMin
=
Math
.
min
(
s1
,
s2
);
switch
(
Math
.
abs
(
sMax
-
sMin
)){
case
0
:
return
sMax
;
case
1
:
return
sMax
||
sMin
;
case
2
:
return
undefined
;
default
:
throw
new
Error
(
'It looks like some unexpected FP error!'
);
}
}
BSPTree
.
LineNode
.
prototype
.
separate
=
function
(
normal
,
point
){
var
intersectionPoint
=
BSPTree
.
utils
.
linePlaneIntersection
(
normal
,
point
,
this
.
element
.
v1
.
positionWorld
,
this
.
element
.
v2
.
positionWorld
);
if
(
intersectionPoint
){
var
newLine
=
getNextLineInPool
();
newLine
.
copy
(
this
.
element
);
var
vertex
=
getNextVertexInPool
();
vertex
.
position
.
copy
(
intersectionPoint
);
BSPTree
.
utils
.
projectVertex
(
vertex
);
newLine
.
v1
.
copy
(
vertex
);
newLine
.
v2
=
this
.
element
.
v2
;
this
.
element
.
v2
=
vertex
;
return
[
this
,
BSPTree
.
utils
.
createNode
(
newLine
)];
}
else
{
return
[
this
];
}
}
BSPTree
.
TriangleNode
=
function
(
element
){
this
.
element
=
element
;
this
.
isTriangle
=
true
;
};
BSPTree
.
TriangleNode
.
prototype
=
Object
.
create
(
BSPTree
.
Node
.
prototype
);
BSPTree
.
TriangleNode
.
prototype
.
getNormal
=
function
(){
return
this
.
element
.
normalModel
;
}
BSPTree
.
TriangleNode
.
prototype
.
getPointOnPlane
=
function
(){
return
this
.
element
.
v1
.
positionWorld
;
}
BSPTree
.
TriangleNode
.
prototype
.
getSign
=
function
(
normal
,
pointOnPlane
){
var
s1
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v1
.
positionWorld
,
pointOnPlane
);
var
s2
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v2
.
positionWorld
,
pointOnPlane
);
var
s3
=
BSPTree
.
utils
.
getPointSign
(
normal
,
this
.
element
.
v3
.
positionWorld
,
pointOnPlane
);
var
sMax
=
Math
.
max
(
s1
,
s2
,
s3
);
var
sMin
=
Math
.
min
(
s1
,
s2
,
s3
);
switch
(
Math
.
abs
(
sMax
-
sMin
)){
case
0
:
return
sMax
;
case
1
:
return
sMax
||
sMin
;
case
2
:
return
undefined
;
default
:
throw
new
Error
(
'It looks like some unexpected FP error!'
);
}
}
BSPTree
.
TriangleNode
.
prototype
.
separate
=
function
(
normal
,
pointOnPlane
){
var
p1
=
this
.
element
.
v1
.
positionWorld
;
var
p2
=
this
.
element
.
v2
.
positionWorld
;
var
p3
=
this
.
element
.
v3
.
positionWorld
;
// Intersection points
var
i12
=
BSPTree
.
utils
.
linePlaneIntersection
(
normal
,
pointOnPlane
,
p1
,
p2
);
var
i23
=
BSPTree
.
utils
.
linePlaneIntersection
(
normal
,
pointOnPlane
,
p2
,
p3
);
var
i31
=
BSPTree
.
utils
.
linePlaneIntersection
(
normal
,
pointOnPlane
,
p3
,
p1
);
if
(
i12
&&
i23
&&
i31
){
// Special case, one split point is a vertex
// In this case we split triangle into two
var
iVertex
,
iSide
;
var
vertex
=
getNextVertexInPool
();
var
newTriangle
=
getNextFaceInPool
();
newTriangle
.
copy
(
this
.
element
);
if
(
BSPTree
.
utils
.
pointsEqual
(
i12
,
i23
)){
vertex
.
position
=
i31
;
BSPTree
.
utils
.
projectVertex
(
vertex
);
this
.
element
.
v3
.
copy
(
vertex
);
newTriangle
.
v1
=
vertex
;
}
else
if
(
BSPTree
.
utils
.
pointsEqual
(
i23
,
i31
)){
vertex
.
position
=
i12
;
BSPTree
.
utils
.
projectVertex
(
vertex
);
this
.
element
.
v1
.
copy
(
vertex
);
newTriangle
.
v2
=
vertex
;
}
else
{
// Faces seem to be equal!
return
0
;
vertex
.
position
=
i23
;
BSPTree
.
utils
.
projectVertex
(
vertex
)
;
this
.
element
.
v2
.
copy
(
vertex
);
newTriangle
.
v3
=
vertex
;
}
return
[
this
,
BSPTree
.
utils
.
createNode
(
newTriangle
)];
}
else
{
var
t1
=
getNextFaceInPool
();
var
t2
=
getNextFaceInPool
();
t1
.
copy
(
this
.
element
);
t2
.
copy
(
this
.
element
);
var
v1
=
getNextVertexInPool
();
var
v2
=
getNextVertexInPool
();
// Split triangle into three triangles
if
(
!
i12
){
this
.
element
.
v1
.
position
=
i31
;
this
.
element
.
v2
.
position
=
i23
;
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v1
);
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v2
);
t1
.
v2
.
copy
(
this
.
element
.
v2
);
t1
.
v3
.
copy
(
this
.
element
.
v1
);
t2
.
v3
.
copy
(
this
.
element
.
v2
);
}
else
if
(
!
i23
){
this
.
element
.
v2
.
position
=
i12
;
this
.
element
.
v3
.
position
=
i31
;
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v2
);
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v3
);
t1
.
v1
.
copy
(
this
.
element
.
v2
);
t1
.
v3
.
copy
(
this
.
element
.
v3
);
t2
.
v1
.
copy
(
this
.
element
.
v3
);
}
else
{
this
.
element
.
v1
.
position
=
i12
;
this
.
element
.
v3
.
position
=
i23
;
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v1
);
BSPTree
.
utils
.
projectVertex
(
this
.
element
.
v3
);
t1
.
v1
.
copy
(
this
.
element
.
v1
);
t1
.
v2
.
copy
(
this
.
element
.
v3
);
t2
.
v2
.
copy
(
this
.
element
.
v1
);
}
return
[
this
,
BSPTree
.
utils
.
createNode
(
t1
),
BSPTree
.
utils
.
createNode
(
t2
)
]
}
}
function
clipLine
(
s1
,
s2
)
{
function
painterSort
(
a
,
b
){
if
(
a
.
z
!==
b
.
z
)
{
var
alpha1
=
0
,
alpha2
=
1
,
return
b
.
z
-
a
.
z
;
// Calculate the boundary coordinate of each vertex for the near and far clip planes,
// Z = -1 and Z = +1, respectively.
bc1near
=
s1
.
z
+
s1
.
w
,
bc2near
=
s2
.
z
+
s2
.
w
,
bc1far
=
-
s1
.
z
+
s1
.
w
,
bc2far
=
-
s2
.
z
+
s2
.
w
;
// Fallback: compare ids
}
else
if
(
a
.
id
!==
b
.
id
)
{
if
(
bc1near
>=
0
&&
bc2near
>=
0
&&
bc1far
>=
0
&&
bc2far
>=
0
)
{
return
a
.
id
-
b
.
id
;
// Both vertices lie entirely within all clip planes.
return
true
;
}
else
{
// Faces seem to be equal!
return
0
;
}
else
if
(
(
bc1near
<
0
&&
bc2near
<
0
)
||
(
bc1far
<
0
&&
bc2far
<
0
)
)
{
// Both vertices lie entirely outside one of the clip planes.
return
false
;
}
}
}
else
{
function
clipLine
(
s1
,
s2
)
{
// The line segment spans at least one clip plane.
var
alpha1
=
0
,
alpha2
=
1
,
if
(
bc1near
<
0
)
{
// Calculate the boundary coordinate of each vertex for the near and far clip planes,
// Z = -1 and Z = +1, respectively.
bc1near
=
s1
.
z
+
s1
.
w
,
bc2near
=
s2
.
z
+
s2
.
w
,
bc1far
=
-
s1
.
z
+
s1
.
w
,
bc2far
=
-
s2
.
z
+
s2
.
w
;
// v1 lies outside the near plane, v2 inside
alpha1
=
Math
.
max
(
alpha1
,
bc1near
/
(
bc1near
-
bc2near
)
);
if
(
bc1near
>=
0
&&
bc2near
>=
0
&&
bc1far
>=
0
&&
bc2far
>=
0
)
{
}
else
if
(
bc2near
<
0
)
{
// Both vertices lie entirely within all clip planes.
return
true
;
// v2 lies outside the near plane, v1 inside
alpha2
=
Math
.
min
(
alpha2
,
bc1near
/
(
bc1near
-
bc2near
)
);
}
else
if
(
(
bc1near
<
0
&&
bc2near
<
0
)
||
(
bc1far
<
0
&&
bc2far
<
0
)
)
{
}
// Both vertices lie entirely outside one of the clip planes.
return
false
;
if
(
bc1far
<
0
)
{
}
else
{
// v1 lies outside the far plane, v2 inside
alpha1
=
Math
.
max
(
alpha1
,
bc1far
/
(
bc1far
-
bc2far
)
);
// The line segment spans at least one clip plane.
}
else
if
(
bc2f
ar
<
0
)
{
if
(
bc1ne
ar
<
0
)
{
// v2 lies outside the f
ar plane, v2 inside
alpha2
=
Math
.
min
(
alpha2
,
bc1far
/
(
bc1far
-
bc2f
ar
)
);
// v1 lies outside the ne
ar plane, v2 inside
alpha1
=
Math
.
max
(
alpha1
,
bc1near
/
(
bc1near
-
bc2ne
ar
)
);
}
}
else
if
(
bc2near
<
0
)
{
if
(
alpha2
<
alpha1
)
{
// v2 lies outside the near plane, v1 inside
alpha2
=
Math
.
min
(
alpha2
,
bc1near
/
(
bc1near
-
bc2near
)
);
// The line segment spans two boundaries, but is outside both of them.
// (This can't happen when we're only clipping against just near/far but good
// to leave the check here for future usage if other clip planes are added.)
return
false
;
}
}
else
{
if
(
bc1far
<
0
)
{
// Update the s1 and s2 vertices to match the clipped line segment.
s1
.
lerp
(
s2
,
alpha1
);
s2
.
lerp
(
s1
,
1
-
alpha2
);
// v1 lies outside the far plane, v2 inside
alpha1
=
Math
.
max
(
alpha1
,
bc1far
/
(
bc1far
-
bc2far
)
);
return
true
;
}
else
if
(
bc2far
<
0
)
{
}
// v2 lies outside the far plane, v2 inside
alpha2
=
Math
.
min
(
alpha2
,
bc1far
/
(
bc1far
-
bc2far
)
);
}
}
if
(
alpha2
<
alpha1
)
{
};
// The line segment spans two boundaries, but is outside both of them.
// (This can't happen when we're only clipping against just near/far but good
// to leave the check here for future usage if other clip planes are added.)
return
false
;
}
else
{
// Update the s1 and s2 vertices to match the clipped line segment.
s1
.
lerp
(
s2
,
alpha1
);
s2
.
lerp
(
s1
,
1
-
alpha2
);
return
true
;
}
}
return
Projector
;
}
}
)
;
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment