1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "mozilla/gfx/Polygon.h"
13 void BSPTree::BuildDrawOrder(BSPTreeNode
* aNode
,
14 nsTArray
<LayerPolygon
>& aLayers
) const {
15 const gfx::Point4D
& normal
= aNode
->First().GetNormal();
17 BSPTreeNode
* front
= aNode
->front
;
18 BSPTreeNode
* back
= aNode
->back
;
20 // Since the goal is to return the draw order from back to front, we reverse
21 // the traversal order if the current polygon is facing towards the camera.
22 const bool reverseOrder
= normal
.z
> 0.0f
;
25 std::swap(front
, back
);
29 BuildDrawOrder(front
, aLayers
);
32 for (LayerPolygon
& layer
: aNode
->layers
) {
33 MOZ_ASSERT(layer
.geometry
);
35 if (layer
.geometry
->GetPoints().Length() >= 3) {
36 aLayers
.AppendElement(std::move(layer
));
41 BuildDrawOrder(back
, aLayers
);
45 void BSPTree::BuildTree(BSPTreeNode
* aRoot
, std::list
<LayerPolygon
>& aLayers
) {
46 MOZ_ASSERT(!aLayers
.empty());
48 aRoot
->layers
.push_back(std::move(aLayers
.front()));
51 if (aLayers
.empty()) {
55 const gfx::Polygon
& plane
= aRoot
->First();
56 MOZ_ASSERT(!plane
.IsEmpty());
58 const gfx::Point4D
& planeNormal
= plane
.GetNormal();
59 const gfx::Point4D
& planePoint
= plane
.GetPoints()[0];
61 std::list
<LayerPolygon
> backLayers
, frontLayers
;
62 for (LayerPolygon
& layerPolygon
: aLayers
) {
63 const nsTArray
<gfx::Point4D
>& geometry
= layerPolygon
.geometry
->GetPoints();
65 // Calculate the plane-point distances for the polygon classification.
66 size_t pos
= 0, neg
= 0;
67 nsTArray
<float> distances
= CalculatePointPlaneDistances(
68 geometry
, planeNormal
, planePoint
, pos
, neg
);
71 if (pos
== 0 && neg
> 0) {
72 backLayers
.push_back(std::move(layerPolygon
));
75 else if (pos
> 0 && neg
== 0) {
76 frontLayers
.push_back(std::move(layerPolygon
));
79 else if (pos
== 0 && neg
== 0) {
80 aRoot
->layers
.push_back(std::move(layerPolygon
));
82 // Polygon intersects with the splitting plane.
83 else if (pos
> 0 && neg
> 0) {
84 nsTArray
<gfx::Point4D
> backPoints
, frontPoints
;
85 // Clip the polygon against the plane. We reuse the previously calculated
86 // distances to find the plane-edge intersections.
87 ClipPointsWithPlane(geometry
, planeNormal
, distances
, backPoints
,
90 const gfx::Point4D
& normal
= layerPolygon
.geometry
->GetNormal();
91 Layer
* layer
= layerPolygon
.layer
;
93 if (backPoints
.Length() >= 3) {
94 backLayers
.emplace_back(layer
, std::move(backPoints
), normal
);
97 if (frontPoints
.Length() >= 3) {
98 frontLayers
.emplace_back(layer
, std::move(frontPoints
), normal
);
103 if (!backLayers
.empty()) {
104 aRoot
->back
= new (mPool
) BSPTreeNode(mListPointers
);
105 BuildTree(aRoot
->back
, backLayers
);
108 if (!frontLayers
.empty()) {
109 aRoot
->front
= new (mPool
) BSPTreeNode(mListPointers
);
110 BuildTree(aRoot
->front
, frontLayers
);
114 } // namespace layers
115 } // namespace mozilla