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
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