Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(752)

Side by Side Diff: Source/platform/transforms/TransformOperations.cpp

Issue 328333003: Adding Blink-side 3d Box and Bounds calculations to TransformOperations (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) 2 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details. 13 * Library General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU Library General Public License 15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to 16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA. 18 * Boston, MA 02110-1301, USA.
19 * 19 *
20 */ 20 */
21 21
22 #include "config.h" 22 #include "config.h"
23 #include "platform/transforms/TransformOperations.h" 23 #include "platform/transforms/TransformOperations.h"
24 24
25 #include "platform/animation/AnimationUtilities.h"
26 #include "platform/geometry/FloatBox.h"
25 #include "platform/transforms/IdentityTransformOperation.h" 27 #include "platform/transforms/IdentityTransformOperation.h"
26 #include "platform/transforms/InterpolatedTransformOperation.h" 28 #include "platform/transforms/InterpolatedTransformOperation.h"
29 #include "platform/transforms/RotateTransformOperation.h"
27 #include <algorithm> 30 #include <algorithm>
28 31
29 using namespace std; 32 using namespace std;
30 33
31 namespace WebCore { 34 namespace WebCore {
32 35
33 TransformOperations::TransformOperations(bool makeIdentity) 36 TransformOperations::TransformOperations(bool makeIdentity)
34 { 37 {
35 if (makeIdentity) 38 if (makeIdentity)
36 m_operations.append(IdentityTransformOperation::create()); 39 m_operations.append(IdentityTransformOperation::create());
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 if (from == *this || (!from.size() && !size())) 105 if (from == *this || (!from.size() && !size()))
103 return *this; 106 return *this;
104 107
105 // If either list is empty, use blendByMatchingOperations which has special logic for this case. 108 // If either list is empty, use blendByMatchingOperations which has special logic for this case.
106 if (!from.size() || !size() || from.operationsMatch(*this)) 109 if (!from.size() || !size() || from.operationsMatch(*this))
107 return blendByMatchingOperations(from, progress); 110 return blendByMatchingOperations(from, progress);
108 111
109 return blendByUsingMatrixInterpolation(from, progress); 112 return blendByUsingMatrixInterpolation(from, progress);
110 } 113 }
111 114
115 static void findCandidatesInPlane(double px, double py, double nz, double* candi dates, int* numCandidates)
116 {
117 // The angle that this point is rotated with respect to the plane nz
118 double phi = atan2(px, py);
119
120 *numCandidates = 4;
121 candidates[0] = phi; // The element at 0deg (maximum x)
122
123 for (int i = 1; i < *numCandidates; ++i)
124 candidates[i] = candidates[i - 1] + M_PI_2; // every 90 deg
125 if (nz < 0.f) {
126 for (int i = 0; i < *numCandidates; ++i)
127 candidates[i] *= -1;
128 }
129 }
130
131 // This method returns the bounding box that contains the starting point,
132 // the ending point, and any of the extrema (in each dimension) found across
Ian Vollick 2014/06/17 15:54:56 nit: extra space.
awoloszyn 2014/06/17 20:06:02 Done.
133 // the circle described by the arc. These are then filtered to points that
134 // actually reside on the arc.
135 static void boundingBoxForArc(const FloatPoint3D& point, const RotateTransformOp eration& fromTransform, const RotateTransformOperation& toTransform, double minP rogress, double maxProgress, FloatBox& box)
136 {
137 double candidates[6];
138 int numCandidates = 0;
139
140 FloatPoint3D axis(fromTransform.x(), fromTransform.y(), fromTransform.z());
Ian Vollick 2014/06/17 15:54:56 fromTransform.axis()
awoloszyn 2014/06/17 20:06:02 Done.
141 double fromDegrees = fromTransform.angle();
142 double toDegrees = toTransform.angle();
143
144 if (axis.dot(toTransform.axis()) < 0)
145 toDegrees *= -1;
146
147 fromDegrees = blend(fromDegrees, toTransform.angle(), minProgress);
148 toDegrees = blend(toDegrees, fromTransform.angle(), 1.0 - maxProgress);
149 if (fromDegrees > toDegrees)
150 std::swap(fromDegrees, toDegrees);
151
152 TransformationMatrix fromMatrix;
153 TransformationMatrix toMatrix;
154 fromMatrix.rotate3d(fromTransform.x(), fromTransform.y(), fromTransform.z(), fromDegrees);
155 toMatrix.rotate3d(fromTransform.x(), fromTransform.y(), fromTransform.z(), t oDegrees);
156
157 FloatPoint3D fromPoint = fromMatrix.mapPoint(point);
158 FloatPoint3D toPoint = toMatrix.mapPoint(point);
159
160 if (box.isEmpty())
161 box.setOrigin(fromPoint);
162 else
163 box.expandTo(fromPoint);
164
165 box.expandTo(toPoint);
166
167 switch (fromTransform.type()) {
168 case TransformOperation::RotateX:
169 findCandidatesInPlane(point.y(), point.z(), fromTransform.x(), candidate s, &numCandidates);
170 break;
171 case TransformOperation::RotateY:
172 findCandidatesInPlane(point.z(), point.x(), fromTransform.y(), candidate s, &numCandidates);
173 break;
174 case TransformOperation::RotateZ:
175 findCandidatesInPlane(point.x(), point.y(), fromTransform.z(), candidate s, &numCandidates);
176 break;
177 default:
178 {
179 FloatPoint3D normal = axis;
180 if (normal.isZero())
181 return;
182 normal.normalize();
183 FloatPoint3D origin;
184 FloatPoint3D toPoint = point - origin;
185 FloatPoint3D center = origin + normal*toPoint.dot(normal);
Ian Vollick 2014/06/17 15:54:56 http://dev.chromium.org/blink/coding-style says sp
awoloszyn 2014/06/17 20:06:02 Done.
186 FloatPoint3D v1 = point - center;
187 if (v1.isZero())
188 return;
189
190 v1.normalize();
191 FloatPoint3D v2 = normal.cross(v1);
192 // v1 is the basis vector in the direction of the point.
193 // i.e. with a rotation of 0, v1 is our +x vector.
194 // v2 is a perpenticular basis vector of our plane (+y).
195
196 // Take the parametric equation of a circle.
197 // (x = r*cos(t); y = r*sin(t);
198 // We can treat that as a circle on the plane v1xv2
199 // From that we get the parametric equations for a circle on the
200 // plane in 3d space of
201 // x(t) = r*cos(t)*v1.x + r*sin(t)*v2.x + cx
202 // y(t) = r*cos(t)*v1.y + r*sin(t)*v2.y + cy
203 // z(t) = r*cos(t)*v1.z + r*sin(t)*v2.z + cz
204 // taking the derivative of (x, y, z) and solving for 0 gives us our
205 // maximum/minimum x, y, z values
206 // x'(t) = r*cos(t)*v2.x - r*sin(t)*v1.x = 0
207 // tan(t) = v2.x/v1.x
208 // t = atan2(v2.x, v1.x) + n*M_PI;
209
210 candidates[0] = atan2(v2.x(), v1.x());
211 candidates[1] = candidates[0] + M_PI;
212 candidates[2] = atan2(v2.y(), v1.y());
213 candidates[3] = candidates[2] + M_PI;
214 candidates[4] = atan2(v2.z(), v1.z());
215 candidates[5] = candidates[4] + M_PI;
216 numCandidates = 6;
217 }
218 break;
219 }
220
221 double minRadians = deg2rad(fromDegrees);
222 double maxRadians = deg2rad(toDegrees);
223 // Once we have the candidates, we now filter them down to ones that
224 // actually live on the arc, rather than the entire circle.
225 for (int i = 0; i < numCandidates; ++i) {
226 double radians = candidates[i];
227
228 while (radians < minRadians)
229 radians += 2.0 * M_PI;
230 while (radians > maxRadians)
231 radians -= 2.0 * M_PI;
232 if (radians < minRadians)
233 continue;
234
235 TransformationMatrix rotation;
236 rotation.rotate3d(axis.x(), axis.y(), axis.z(), rad2deg(radians));
237 box.expandTo(rotation.mapPoint(point));
238 }
239 }
240
241 bool TransformOperations::blendedBoundsForBox(const FloatBox& box, const Transfo rmOperations& from, const double& minProgress, const double& maxProgress, FloatB ox* bounds) const
242 {
243
244 int fromSize = from.operations().size();
245 int toSize = operations().size();
246 int size = max(fromSize, toSize);
247
248 *bounds = box;
249 for (int i = size - 1; i >= 0; i--) {
250 RefPtr<TransformOperation> fromOperation = (i < fromSize) ? from.operati ons()[i] : static_cast<TransformOperation*>(0);
Ian Vollick 2014/06/17 15:54:56 Can you use nullptr rather than static_cast<Transf
awoloszyn 2014/06/17 20:06:02 Done.
251 RefPtr<TransformOperation> toOperation = (i < toSize) ? operations()[i]: static_cast<TransformOperation*>(0);
Ian Vollick 2014/06/17 15:54:56 nit: space before colon
awoloszyn 2014/06/17 20:06:02 Done.
252 if (fromOperation && fromOperation->type() == TransformOperation::None)
253 fromOperation = static_cast<TransformOperation*>(0);
254
255 if (toOperation && toOperation->type() == TransformOperation::None)
256 toOperation = static_cast<TransformOperation*>(0);
257
258 TransformOperation::OperationType interpolationType = toOperation ? toOp eration->type() :
259 fromOperation ? fromOperation->type() :
260 TransformOperation::None;
261 if (fromOperation && toOperation && !fromOperation->canInterpolateWith(* toOperation.get()))
Ian Vollick 2014/06/17 15:54:56 This seems fishy. Why do we not return false here?
awoloszyn 2014/06/17 20:06:02 Thanks for the catch. This should almost certainly
262 continue;
263
264 switch (interpolationType) {
265 case TransformOperation::Identity:
266 bounds->expandTo(box);
267 continue;
268 case TransformOperation::Translate:
269 case TransformOperation::TranslateX:
270 case TransformOperation::TranslateY:
271 case TransformOperation::TranslateZ:
272 case TransformOperation::Translate3D:
273 case TransformOperation::Scale:
274 case TransformOperation::ScaleX:
275 case TransformOperation::ScaleY:
276 case TransformOperation::ScaleZ:
277 case TransformOperation::Scale3D:
278 case TransformOperation::Skew:
279 case TransformOperation::SkewX:
280 case TransformOperation::SkewY:
281 case TransformOperation::Perspective:
282 {
283 RefPtr<TransformOperation> fromTransform;
284 RefPtr<TransformOperation> toTransform;
285 if (!toOperation) {
286 fromTransform = fromOperation->blend(toOperation.get(), 1-mi nProgress, false);
287 toTransform = fromOperation->blend(toOperation.get(), 1-maxP rogress, false);
288 } else {
289 fromTransform = toOperation->blend(fromOperation.get(), minP rogress, false);
290 toTransform = toOperation->blend(fromOperation.get(), maxPro gress, false);
291 }
292 if (!fromTransform || !toTransform)
293 continue;
294 TransformationMatrix fromMatrix;
295 TransformationMatrix toMatrix;
296 fromTransform->apply(fromMatrix, FloatSize());
297 toTransform->apply(toMatrix, FloatSize());
298 FloatBox fromBox = *bounds;
299 FloatBox toBox = *bounds;
300 fromMatrix.transformBox(fromBox);
301 toMatrix.transformBox(toBox);
302 *bounds = fromBox;
303 bounds->expandTo(toBox);
304 continue;
305 }
306 case TransformOperation::Rotate: // This is also RotateZ
307 case TransformOperation::Rotate3D:
308 case TransformOperation::RotateX:
309 case TransformOperation::RotateY:
310 {
311 RefPtr<RotateTransformOperation> identityRotation;
312 const RotateTransformOperation* fromRotation = nullptr;
313 const RotateTransformOperation* toRotation = nullptr;
314 if (fromOperation) {
315 fromRotation = static_cast<const RotateTransformOperation*>( fromOperation.get());
316 if (fromRotation->hasZeroAxis())
317 fromRotation = nullptr;
318 }
319
320 if (toOperation) {
321 toRotation = static_cast<const RotateTransformOperation*>(to Operation.get());
322 if (toRotation->hasZeroAxis())
323 toRotation = nullptr;
324 }
325
326 double fromAngle;
327 double toAngle;
328 FloatPoint3D axis;
329 if (!RotateTransformOperation::shareSameAxis(fromRotation, toRot ation, &axis, &fromAngle, &toAngle)) {
330 return(false);
331 }
332
333 if (!fromRotation) {
334 identityRotation = RotateTransformOperation::create(axis.x() , axis.y(), axis.z(), 0, fromOperation ? fromOperation->type() : toOperation->ty pe());
335 fromRotation = identityRotation.get();
336 }
337
338 if (!toRotation) {
339 if (!identityRotation)
340 identityRotation = RotateTransformOperation::create(axis .x(), axis.y(), axis.z(), 0, fromOperation ? fromOperation->type() : toOperation ->type());
341 toRotation = identityRotation.get();
342 }
343
344 FloatBox fromBox = *bounds;
345 bool first = true;
346 for (size_t i = 0; i < 2; ++i) {
347 for (size_t j = 0; j < 2; ++j) {
348 for (size_t k = 0; k < 2; ++k) {
349 FloatBox boundsForArc;
350 FloatPoint3D corner(fromBox.x(), fromBox.y(), fromBo x.z());
351 corner += FloatPoint3D(i * fromBox.width(),
352 j * fromBox.height(),
353 k * fromBox.depth());
354 boundingBoxForArc(corner, *fromRotation, *toRotation , minProgress, maxProgress, boundsForArc);
355 if (first) {
356 *bounds = boundsForArc;
357 first = false;
358 } else {
359 bounds->expandTo(boundsForArc);
360 }
361 }
362 }
363 }
364 }
365 continue;
366 case TransformOperation::None:
367 continue;
368 case TransformOperation::Matrix:
369 case TransformOperation::Matrix3D:
370 case TransformOperation::Interpolated:
371 return(false);
372 }
373 }
374
375 return true;
376 }
Ian Vollick 2014/06/17 15:54:56 Nit: extra ws
awoloszyn 2014/06/17 20:06:02 Done.
377
378
112 TransformOperations TransformOperations::add(const TransformOperations& addend) const 379 TransformOperations TransformOperations::add(const TransformOperations& addend) const
113 { 380 {
114 TransformOperations result; 381 TransformOperations result;
115 result.m_operations = operations(); 382 result.m_operations = operations();
116 result.m_operations.appendVector(addend.operations()); 383 result.m_operations.appendVector(addend.operations());
117 return result; 384 return result;
118 } 385 }
119 386
120 } // namespace WebCore 387 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698