155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui/* 255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Copyright (C) 2013 The Android Open Source Project 355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Licensed under the Apache License, Version 2.0 (the "License"); 555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * you may not use this file except in compliance with the License. 655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * You may obtain a copy of the License at 755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * http://www.apache.org/licenses/LICENSE-2.0 955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 1055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Unless required by applicable law or agreed to in writing, software 1155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * distributed under the License is distributed on an "AS IS" BASIS, 1255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * See the License for the specific language governing permissions and 1455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * limitations under the License. 1555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui */ 1655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 1755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#define LOG_TAG "OpenGLRenderer" 1887f9df880e4a5bfba65d2ed413b3ead649595129Chris Craik#define ATRACE_TAG ATRACE_TAG_VIEW 1955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 2055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include <math.h> 2155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include <utils/Log.h> 2287f9df880e4a5bfba65d2ed413b3ead649595129Chris Craik#include <utils/Trace.h> 2355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 2455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "AmbientShadow.h" 25f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik#include "Caches.h" 2655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "ShadowTessellator.h" 277b4516e7ea552ad08d6e7277d311ef11bd8f12e8ztenghui#include "SpotShadow.h" 2855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 2955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace android { 3055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace uirenderer { 3155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 3205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid ShadowTessellator::tessellateAmbientShadow(bool isCasterOpaque, 3350ecf849cb7ccc3482517b74d2214b347927791eztenghui const Vector3* casterPolygon, int casterVertexCount, 34af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui const Vector3& centroid3d, const Rect& casterBounds, 35af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui const Rect& localClip, float maxZ, VertexBuffer& shadowVertexBuffer) { 3687f9df880e4a5bfba65d2ed413b3ead649595129Chris Craik ATRACE_CALL(); 3787f9df880e4a5bfba65d2ed413b3ead649595129Chris Craik 3855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui // A bunch of parameters to tweak the shadow. 3955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui // TODO: Allow some of these changable by debug settings or APIs. 408def74de33b197c0c5ec8774576b1d71c7ec4f1bztenghui float heightFactor = 1.0f / 128; 417b4516e7ea552ad08d6e7277d311ef11bd8f12e8ztenghui const float geomFactor = 64; 4255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 43f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik Caches& caches = Caches::getInstance(); 44f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik if (CC_UNLIKELY(caches.propertyAmbientRatio > 0.0f)) { 45f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik heightFactor *= caches.propertyAmbientRatio; 46f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik } 47f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik 48af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui Rect ambientShadowBounds(casterBounds); 49af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui ambientShadowBounds.outset(maxZ * geomFactor * heightFactor); 50af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui 51af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui if (!localClip.intersects(ambientShadowBounds)) { 52af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui#if DEBUG_SHADOW 53af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui ALOGD("Ambient shadow is out of clip rect!"); 54af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui#endif 5505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return; 56af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui } 57af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui 5805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik AmbientShadow::createAmbientShadow(isCasterOpaque, casterPolygon, 5950ecf849cb7ccc3482517b74d2214b347927791eztenghui casterVertexCount, centroid3d, heightFactor, geomFactor, 6050ecf849cb7ccc3482517b74d2214b347927791eztenghui shadowVertexBuffer); 6155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui} 6255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 6305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque, 64c50a03d78aaedd0003377e98710e7038bda330e9ztenghui const Vector3* casterPolygon, int casterVertexCount, const Vector3& casterCentroid, 65797b95b26bbb7557678af78b9a2a61830158920fChris Craik const mat4& receiverTransform, const Vector3& lightCenter, int lightRadius, 66797b95b26bbb7557678af78b9a2a61830158920fChris Craik const Rect& casterBounds, const Rect& localClip, VertexBuffer& shadowVertexBuffer) { 6787f9df880e4a5bfba65d2ed413b3ead649595129Chris Craik ATRACE_CALL(); 6887f9df880e4a5bfba65d2ed413b3ead649595129Chris Craik 69f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik Caches& caches = Caches::getInstance(); 70f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik 71797b95b26bbb7557678af78b9a2a61830158920fChris Craik Vector3 adjustedLightCenter(lightCenter); 72f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik if (CC_UNLIKELY(caches.propertyLightPosY > 0)) { 73797b95b26bbb7557678af78b9a2a61830158920fChris Craik adjustedLightCenter.y = - caches.propertyLightPosY; // negated since this shifts up 74f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik } 75f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik if (CC_UNLIKELY(caches.propertyLightPosZ > 0)) { 76797b95b26bbb7557678af78b9a2a61830158920fChris Craik adjustedLightCenter.z = caches.propertyLightPosZ; 77f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik } 78f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik 797b4516e7ea552ad08d6e7277d311ef11bd8f12e8ztenghui#if DEBUG_SHADOW 80797b95b26bbb7557678af78b9a2a61830158920fChris Craik ALOGD("light center %f %f %f", 81797b95b26bbb7557678af78b9a2a61830158920fChris Craik adjustedLightCenter.x, adjustedLightCenter.y, adjustedLightCenter.z); 827b4516e7ea552ad08d6e7277d311ef11bd8f12e8ztenghui#endif 833197cded4e265bc99dc82d695bbb7163fe134ed4Chris Craik 843197cded4e265bc99dc82d695bbb7163fe134ed4Chris Craik // light position (because it's in local space) needs to compensate for receiver transform 853197cded4e265bc99dc82d695bbb7163fe134ed4Chris Craik // TODO: should apply to light orientation, not just position 863197cded4e265bc99dc82d695bbb7163fe134ed4Chris Craik Matrix4 reverseReceiverTransform; 873197cded4e265bc99dc82d695bbb7163fe134ed4Chris Craik reverseReceiverTransform.loadInverse(receiverTransform); 88797b95b26bbb7557678af78b9a2a61830158920fChris Craik reverseReceiverTransform.mapPoint3d(adjustedLightCenter); 893197cded4e265bc99dc82d695bbb7163fe134ed4Chris Craik 90726118b35240957710d4d85fb5747e2ba8b934f7Chris Craik const int lightVertexCount = 8; 91f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik if (CC_UNLIKELY(caches.propertyLightDiameter > 0)) { 92797b95b26bbb7557678af78b9a2a61830158920fChris Craik lightRadius = caches.propertyLightDiameter; 93f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik } 94f5be3ca5cc5b3a10747b577f60059a99862bb9a8Chris Craik 95af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui // Now light and caster are both in local space, we will check whether 96af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui // the shadow is within the clip area. 97797b95b26bbb7557678af78b9a2a61830158920fChris Craik Rect lightRect = Rect(adjustedLightCenter.x - lightRadius, adjustedLightCenter.y - lightRadius, 98797b95b26bbb7557678af78b9a2a61830158920fChris Craik adjustedLightCenter.x + lightRadius, adjustedLightCenter.y + lightRadius); 99af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui lightRect.unionWith(localClip); 100af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui if (!lightRect.intersects(casterBounds)) { 101af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui#if DEBUG_SHADOW 102af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui ALOGD("Spot shadow is out of clip rect!"); 103af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui#endif 10405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik return; 105af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui } 106af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui 107c50a03d78aaedd0003377e98710e7038bda330e9ztenghui SpotShadow::createSpotShadow(isCasterOpaque, adjustedLightCenter, lightRadius, 108c50a03d78aaedd0003377e98710e7038bda330e9ztenghui casterPolygon, casterVertexCount, casterCentroid, shadowVertexBuffer); 109c50a03d78aaedd0003377e98710e7038bda330e9ztenghui 11050ecf849cb7ccc3482517b74d2214b347927791eztenghui#if DEBUG_SHADOW 11150ecf849cb7ccc3482517b74d2214b347927791eztenghui if(shadowVertexBuffer.getVertexCount() <= 0) { 11250ecf849cb7ccc3482517b74d2214b347927791eztenghui ALOGD("Spot shadow generation failed %d", shadowVertexBuffer.getVertexCount()); 11350ecf849cb7ccc3482517b74d2214b347927791eztenghui } 11450ecf849cb7ccc3482517b74d2214b347927791eztenghui#endif 1157b4516e7ea552ad08d6e7277d311ef11bd8f12e8ztenghui} 11663d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui 11763d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghuivoid ShadowTessellator::generateShadowIndices(uint16_t* shadowIndices) { 11863d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui int currentIndex = 0; 11963d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui const int rays = SHADOW_RAY_COUNT; 12063d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui // For the penumbra area. 12150ecf849cb7ccc3482517b74d2214b347927791eztenghui for (int layer = 0; layer < 2; layer ++) { 12250ecf849cb7ccc3482517b74d2214b347927791eztenghui int baseIndex = layer * rays; 12350ecf849cb7ccc3482517b74d2214b347927791eztenghui for (int i = 0; i < rays; i++) { 12450ecf849cb7ccc3482517b74d2214b347927791eztenghui shadowIndices[currentIndex++] = i + baseIndex; 12550ecf849cb7ccc3482517b74d2214b347927791eztenghui shadowIndices[currentIndex++] = rays + i + baseIndex; 12650ecf849cb7ccc3482517b74d2214b347927791eztenghui } 12750ecf849cb7ccc3482517b74d2214b347927791eztenghui // To close the loop, back to the ray 0. 12850ecf849cb7ccc3482517b74d2214b347927791eztenghui shadowIndices[currentIndex++] = 0 + baseIndex; 12950ecf849cb7ccc3482517b74d2214b347927791eztenghui // Note this is the same as the first index of next layer loop. 13050ecf849cb7ccc3482517b74d2214b347927791eztenghui shadowIndices[currentIndex++] = rays + baseIndex; 13163d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui } 13263d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui 13363d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui#if DEBUG_SHADOW 13450ecf849cb7ccc3482517b74d2214b347927791eztenghui if (currentIndex != MAX_SHADOW_INDEX_COUNT) { 13550ecf849cb7ccc3482517b74d2214b347927791eztenghui ALOGW("vertex index count is wrong. current %d, expected %d", 13650ecf849cb7ccc3482517b74d2214b347927791eztenghui currentIndex, MAX_SHADOW_INDEX_COUNT); 13763d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui } 13850ecf849cb7ccc3482517b74d2214b347927791eztenghui for (int i = 0; i < MAX_SHADOW_INDEX_COUNT; i++) { 13963d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui ALOGD("vertex index is (%d, %d)", i, shadowIndices[i]); 14063d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui } 14163d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui#endif 14263d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui} 14363d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui 14463d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui/** 14563d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui * Calculate the centroid of a 2d polygon. 14663d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui * 14763d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui * @param poly The polygon, which is represented in a Vector2 array. 14863d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui * @param polyLength The length of the polygon in terms of number of vertices. 14963d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui * @return the centroid of the polygon. 15063d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui */ 15163d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghuiVector2 ShadowTessellator::centroid2d(const Vector2* poly, int polyLength) { 15263d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui double sumx = 0; 15363d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui double sumy = 0; 15463d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui int p1 = polyLength - 1; 15563d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui double area = 0; 15663d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui for (int p2 = 0; p2 < polyLength; p2++) { 15763d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui double x1 = poly[p1].x; 15863d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui double y1 = poly[p1].y; 15963d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui double x2 = poly[p2].x; 16063d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui double y2 = poly[p2].y; 16163d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui double a = (x1 * y2 - x2 * y1); 16263d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui sumx += (x1 + x2) * a; 16363d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui sumy += (y1 + y2) * a; 16463d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui area += a; 16563d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui p1 = p2; 16663d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui } 16763d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui 16863d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui Vector2 centroid = poly[0]; 16963d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui if (area != 0) { 1701aa5d2d7068147ff781cfe911a93f01593a68c79John Reck centroid = (Vector2){static_cast<float>(sumx / (3 * area)), 1711aa5d2d7068147ff781cfe911a93f01593a68c79John Reck static_cast<float>(sumy / (3 * area))}; 17263d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui } else { 17350ecf849cb7ccc3482517b74d2214b347927791eztenghui ALOGW("Area is 0 while computing centroid!"); 17463d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui } 17563d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui return centroid; 17663d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui} 17763d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui 178c50a03d78aaedd0003377e98710e7038bda330e9ztenghui// Make sure p1 -> p2 is going CW around the poly. 179c50a03d78aaedd0003377e98710e7038bda330e9ztenghuiVector2 ShadowTessellator::calculateNormal(const Vector2& p1, const Vector2& p2) { 180c50a03d78aaedd0003377e98710e7038bda330e9ztenghui Vector2 result = p2 - p1; 181c50a03d78aaedd0003377e98710e7038bda330e9ztenghui if (result.x != 0 || result.y != 0) { 182c50a03d78aaedd0003377e98710e7038bda330e9ztenghui result.normalize(); 183c50a03d78aaedd0003377e98710e7038bda330e9ztenghui // Calculate the normal , which is CCW 90 rotate to the delta. 184c50a03d78aaedd0003377e98710e7038bda330e9ztenghui float tempy = result.y; 185c50a03d78aaedd0003377e98710e7038bda330e9ztenghui result.y = result.x; 186c50a03d78aaedd0003377e98710e7038bda330e9ztenghui result.x = -tempy; 187c50a03d78aaedd0003377e98710e7038bda330e9ztenghui } 188c50a03d78aaedd0003377e98710e7038bda330e9ztenghui return result; 189c50a03d78aaedd0003377e98710e7038bda330e9ztenghui} 1902e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui/** 1912e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui * Test whether the polygon is order in clockwise. 1922e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui * 1932e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui * @param polygon the polygon as a Vector2 array 1942e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui * @param len the number of points of the polygon 1952e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui */ 1962e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghuibool ShadowTessellator::isClockwise(const Vector2* polygon, int len) { 197f11310f395a135ac7ef204ced5b3d3facf491422ztenghui if (len < 2 || polygon == NULL) { 198f11310f395a135ac7ef204ced5b3d3facf491422ztenghui return true; 199f11310f395a135ac7ef204ced5b3d3facf491422ztenghui } 2002e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui double sum = 0; 2012e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui double p1x = polygon[len - 1].x; 2022e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui double p1y = polygon[len - 1].y; 2032e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui for (int i = 0; i < len; i++) { 2042e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui 2052e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui double p2x = polygon[i].x; 2062e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui double p2y = polygon[i].y; 2072e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui sum += p1x * p2y - p2x * p1y; 2082e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui p1x = p2x; 2092e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui p1y = p2y; 2102e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui } 2112e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui return sum < 0; 2122e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui} 2132e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui 2142e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghuibool ShadowTessellator::isClockwisePath(const SkPath& path) { 2152e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui SkPath::Iter iter(path, false); 2162e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui SkPoint pts[4]; 2172e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui SkPath::Verb v; 2182e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui 2192e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui Vector<Vector2> arrayForDirection; 2202e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui while (SkPath::kDone_Verb != (v = iter.next(pts))) { 2212e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui switch (v) { 2222e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui case SkPath::kMove_Verb: 2231aa5d2d7068147ff781cfe911a93f01593a68c79John Reck arrayForDirection.add((Vector2){pts[0].x(), pts[0].y()}); 2242e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui break; 2252e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui case SkPath::kLine_Verb: 2261aa5d2d7068147ff781cfe911a93f01593a68c79John Reck arrayForDirection.add((Vector2){pts[1].x(), pts[1].y()}); 2272e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui break; 2282e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui case SkPath::kQuad_Verb: 2291aa5d2d7068147ff781cfe911a93f01593a68c79John Reck arrayForDirection.add((Vector2){pts[1].x(), pts[1].y()}); 2301aa5d2d7068147ff781cfe911a93f01593a68c79John Reck arrayForDirection.add((Vector2){pts[2].x(), pts[2].y()}); 2312e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui break; 2322e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui case SkPath::kCubic_Verb: 2331aa5d2d7068147ff781cfe911a93f01593a68c79John Reck arrayForDirection.add((Vector2){pts[1].x(), pts[1].y()}); 2341aa5d2d7068147ff781cfe911a93f01593a68c79John Reck arrayForDirection.add((Vector2){pts[2].x(), pts[2].y()}); 2351aa5d2d7068147ff781cfe911a93f01593a68c79John Reck arrayForDirection.add((Vector2){pts[3].x(), pts[3].y()}); 2362e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui break; 2372e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui default: 2382e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui break; 2392e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui } 2402e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui } 2412e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui 2422e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui return isClockwise(arrayForDirection.array(), arrayForDirection.size()); 2432e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui} 2442e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui 2452e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghuivoid ShadowTessellator::reverseVertexArray(Vertex* polygon, int len) { 2462e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui int n = len / 2; 2472e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui for (int i = 0; i < n; i++) { 2482e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui Vertex tmp = polygon[i]; 2492e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui int k = len - 1 - i; 2502e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui polygon[i] = polygon[k]; 2512e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui polygon[k] = tmp; 2522e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui } 2532e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui} 2542e023f3827dfc0dfc1ed7c3dd54d02b4a993f0b4ztenghui 255512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghuiint ShadowTessellator::getExtraVertexNumber(const Vector2& vector1, 256512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui const Vector2& vector2, float divisor) { 257512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui // When there is no distance difference, there is no need for extra vertices. 258512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui if (vector1.lengthSquared() == 0 || vector2.lengthSquared() == 0) { 259512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui return 0; 260512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui } 261512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui // The formula is : 262512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui // extraNumber = floor(acos(dot(n1, n2)) / (M_PI / EXTRA_VERTEX_PER_PI)) 263512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui // The value ranges for each step are: 264512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui // dot( ) --- [-1, 1] 265512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui // acos( ) --- [0, M_PI] 266512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui // floor(...) --- [0, EXTRA_VERTEX_PER_PI] 267512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui float dotProduct = vector1.dot(vector2); 268512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui // TODO: Use look up table for the dotProduct to extraVerticesNumber 269512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui // computation, if needed. 270512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui float angle = acosf(dotProduct); 271512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui return (int) floor(angle / divisor); 272512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui} 273512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui 274512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghuivoid ShadowTessellator::checkOverflow(int used, int total, const char* bufferName) { 275512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui LOG_ALWAYS_FATAL_IF(used > total, "Error: %s overflow!!! used %d, total %d", 276512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui bufferName, used, total); 277512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui} 278512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui 27955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace uirenderer 28055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace android 281