1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app.wallpapereffectsgeneration;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.SystemApi;
22 import android.graphics.Bitmap;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 
29 /**
30  * The textured mesh representation, including a texture (bitmap) to sample from when rendering,
31  * and a mesh consisting of primitives such as triangles. The mesh is represented by an indices
32  * array describing the set of primitives in the mesh, and a vertices array that the indices
33  * refer to.
34  *
35  * @hide
36  */
37 @SystemApi
38 public final class TexturedMesh implements Parcelable {
39     /**
40      * The texture to sample from when rendering mesh.
41      */
42     @NonNull
43     private Bitmap mBitmap;
44 
45     /**
46      * The set of primitives as pointers into the vertices.
47      */
48     @NonNull
49     private int[] mIndices;
50 
51     /**
52      * The specific vertices that the indices refer to.
53      */
54     @NonNull
55     private float[] mVertices;
56 
57     /** @hide */
58     @IntDef(prefix = {"INDICES_LAYOUT_"}, value = {
59             INDICES_LAYOUT_UNDEFINED,
60             INDICES_LAYOUT_TRIANGLES})
61     @Retention(RetentionPolicy.SOURCE)
62     public @interface IndicesLayoutType {
63     }
64 
65     /** Undefined indices layout */
66     public static final int INDICES_LAYOUT_UNDEFINED = 0;
67     /**
68      * Indices layout is triangle. Vertices are grouped into 3 and each
69      * group forms a triangle.
70      */
71     public static final int INDICES_LAYOUT_TRIANGLES = 1;
72 
73     @IndicesLayoutType
74     private int mIndicesLayoutType;
75 
76     /** @hide */
77     @IntDef(prefix = {"VERTICES_LAYOUT_"}, value = {
78             VERTICES_LAYOUT_UNDEFINED,
79             VERTICES_LAYOUT_POSITION3_UV2})
80     @Retention(RetentionPolicy.SOURCE)
81     public @interface VerticesLayoutType {
82     }
83 
84     /**
85      * Undefined vertices layout.
86      */
87     public static final int VERTICES_LAYOUT_UNDEFINED = 0;
88     /**
89      * The vertices array uses 5 numbers to represent a point, in the format
90      * of [x1, y1, z1, u1, v1, x2, y2, z2, u2, v2, ...].
91      */
92     public static final int VERTICES_LAYOUT_POSITION3_UV2 = 1;
93 
94     @VerticesLayoutType
95     private int mVerticesLayoutType;
96 
TexturedMesh(Parcel in)97     private TexturedMesh(Parcel in) {
98         this.mIndicesLayoutType = in.readInt();
99         this.mVerticesLayoutType = in.readInt();
100         this.mBitmap = in.readTypedObject(Bitmap.CREATOR);
101         Parcel data = Parcel.obtain();
102         try {
103             byte[] bytes = in.readBlob();
104             data.unmarshall(bytes, 0, bytes.length);
105             data.setDataPosition(0);
106             this.mIndices = data.createIntArray();
107             this.mVertices = data.createFloatArray();
108         } finally {
109             data.recycle();
110         }
111     }
112 
TexturedMesh(@onNull Bitmap bitmap, @NonNull int[] indices, @NonNull float[] vertices, @IndicesLayoutType int indicesLayoutType, @VerticesLayoutType int verticesLayoutType)113     private TexturedMesh(@NonNull Bitmap bitmap, @NonNull int[] indices,
114             @NonNull float[] vertices, @IndicesLayoutType int indicesLayoutType,
115             @VerticesLayoutType int verticesLayoutType) {
116         mBitmap = bitmap;
117         mIndices = indices;
118         mVertices = vertices;
119         mIndicesLayoutType = indicesLayoutType;
120         mVerticesLayoutType = verticesLayoutType;
121     }
122 
123     /** Get the bitmap, which is the texture to sample from when rendering. */
124     @NonNull
getBitmap()125     public Bitmap getBitmap() {
126         return mBitmap;
127     }
128 
129     /**
130      * Get the indices as pointers to the vertices array. Depending on the getIndicesLayoutType(),
131      * the primitives may have different shapes. For example, with INDICES_LAYOUT_TRIANGLES,
132      * indices 0, 1, 2 forms a triangle, indices 3, 4, 5 form another triangle.
133      */
134     @NonNull
getIndices()135     public int[] getIndices() {
136         return mIndices;
137     }
138 
139     /**
140      * Get the vertices that the index array refers to. Depending on the getVerticesLayoutType()
141      * result, the vertices array can represent different per-vertex coordinates. For example,
142      * with VERTICES_LAYOUT_POSITION3_UV2 type, vertices are in the format of
143      * [x1, y1, z1, u1, v1, x2, y2, z2, u2, v2, ...].
144      */
145     @NonNull
getVertices()146     public float[] getVertices() {
147         return mVertices;
148     }
149 
150     /** Get the indices layout type. */
151     @IndicesLayoutType
152     @NonNull
getIndicesLayoutType()153     public int getIndicesLayoutType() {
154         return mIndicesLayoutType;
155     }
156 
157     /** Get the indices layout type. */
158     @VerticesLayoutType
159     @NonNull
getVerticesLayoutType()160     public int getVerticesLayoutType() {
161         return mVerticesLayoutType;
162     }
163 
164     @NonNull
165     public static final Creator<TexturedMesh> CREATOR = new Creator<TexturedMesh>() {
166         @Override
167         public TexturedMesh createFromParcel(Parcel in) {
168             return new TexturedMesh(in);
169         }
170 
171         @Override
172         public TexturedMesh[] newArray(int size) {
173             return new TexturedMesh[size];
174         }
175     };
176 
177     @Override
writeToParcel(@onNull Parcel out, int flags)178     public void writeToParcel(@NonNull Parcel out, int flags) {
179         out.writeInt(mIndicesLayoutType);
180         out.writeInt(mVerticesLayoutType);
181         out.writeTypedObject(mBitmap, flags);
182 
183         // Indices and vertices can reach 5MB. Write the data as a Blob,
184         // which will be written to ashmem if too large.
185         Parcel data = Parcel.obtain();
186         try {
187             data.writeIntArray(mIndices);
188             data.writeFloatArray(mVertices);
189             out.writeBlob(data.marshall());
190         } finally {
191             data.recycle();
192         }
193     }
194 
195     @Override
describeContents()196     public int describeContents() {
197         return 0;
198     }
199 
200     /**
201      * A builder for {@link TexturedMesh}
202      *
203      * @hide
204      */
205     @SystemApi
206     public static final class Builder {
207         private Bitmap mBitmap;
208         private int[] mIndices;
209         private float[] mVertices;
210         @IndicesLayoutType
211         private int mIndicesLayoutType;
212         @VerticesLayoutType
213         private int mVerticesLayouttype;
214 
215         /**
216          * Constructor with bitmap.
217          *
218          * @hide
219          */
220         @SystemApi
Builder(@onNull Bitmap bitmap)221         public Builder(@NonNull Bitmap bitmap) {
222             mBitmap = bitmap;
223         }
224 
225         /**
226          * Set the required indices. The indices should represent the primitives. For example,
227          * with INDICES_LAYOUT_TRIANGLES, indices 0, 1, 2 forms a triangle, indices 3, 4, 5
228          * form another triangle.
229          */
230         @NonNull
setIndices(@onNull int[] indices)231         public Builder setIndices(@NonNull int[] indices) {
232             mIndices = indices;
233             return this;
234         }
235 
236         /**
237          * Set the required vertices. The vertices array should represent per-vertex coordinates.
238          * For example, with VERTICES_LAYOUT_POSITION3_UV2 type, vertices are in the format of
239          * [x1, y1, z1, u1, v1, x2, y2, z2, u2, v2, ...].
240          *
241          */
242         @NonNull
setVertices(@onNull float[] vertices)243         public Builder setVertices(@NonNull float[] vertices) {
244             mVertices = vertices;
245             return this;
246         }
247 
248         /**
249          * Set the required indices layout type.
250          */
251         @NonNull
setIndicesLayoutType(@ndicesLayoutType int indicesLayoutType)252         public Builder setIndicesLayoutType(@IndicesLayoutType int indicesLayoutType) {
253             mIndicesLayoutType = indicesLayoutType;
254             return this;
255         }
256 
257         /**
258          * Set the required vertices layout type.
259          */
260         @NonNull
setVerticesLayoutType(@erticesLayoutType int verticesLayoutype)261         public Builder setVerticesLayoutType(@VerticesLayoutType int verticesLayoutype) {
262             mVerticesLayouttype = verticesLayoutype;
263             return this;
264         }
265 
266         /** Builds a TexturedMesh based on the given parameters. */
267         @NonNull
build()268         public TexturedMesh build() {
269             return new TexturedMesh(mBitmap, mIndices, mVertices, mIndicesLayoutType,
270                     mVerticesLayouttype);
271         }
272     }
273 }
274