blob: f26b7659918e70e283651d9182e07915d59233b4 [file] [log] [blame]
Jason Samsd19f10d2009-05-22 14:03:28 -07001/*
2 * Copyright (C) 2009 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#include "rsContext.h"
18
19using namespace android;
20using namespace android::renderscript;
21
22#include <GLES/gl.h>
23#include <GLES/glext.h>
24
Jason Samsd19f10d2009-05-22 14:03:28 -070025TriangleMesh::TriangleMesh()
26{
27 mVertexElement = NULL;
28 mIndexElement = NULL;
29 mVertexData = NULL;
30 mIndexData = NULL;
31 mTriangleCount = 0;
32 mVertexDataSize = 0;
33 mIndexDataSize = 0;
34
35 mBufferObjects[0] = 0;
36 mBufferObjects[1] = 0;
37
38 mOffsetCoord = 0;
39 mOffsetTex = 0;
40 mOffsetNorm = 0;
41
42 mSizeCoord = 0;
43 mSizeTex = 0;
44 mSizeNorm = 0;
45
46}
47
48TriangleMesh::~TriangleMesh()
49{
50 free(mVertexData);
51 free(mIndexData);
52}
53
54
55
56TriangleMeshContext::TriangleMeshContext()
57{
58 clear();
59}
60
61TriangleMeshContext::~TriangleMeshContext()
62{
63}
64
65void TriangleMeshContext::clear()
66{
67 mVertexElement = NULL;
68 mVertexSizeBits = 0;
69 mIndexElement = NULL;
70 mIndexSizeBits = 0;
71 mTriangleCount = 0;
72 mVertexData.clear();
73 mIndexData.clear();
74}
75
76void TriangleMesh::analyzeElement()
77{
78 for (uint32_t ct=0; ct < mVertexElement->getComponentCount(); ct++) {
79 const Component *c = mVertexElement->getComponent(ct);
80
81 if (c->getKind() == Component::X) {
82 rsAssert(mSizeCoord == 0);
83 mSizeCoord = 1;
84 mOffsetCoord = ct;
85 }
86 if (c->getKind() == Component::Y) {
87 rsAssert(mSizeCoord == 1);
88 mSizeCoord = 2;
89 }
90 if (c->getKind() == Component::Z) {
91 rsAssert(mSizeCoord == 2);
92 mSizeCoord = 3;
93 }
94 if (c->getKind() == Component::W) {
95 rsAssert(mSizeCoord == 4);
96 mSizeCoord = 4;
97 }
98
99 if (c->getKind() == Component::NX) {
100 rsAssert(mSizeNorm == 0);
101 mSizeNorm = 1;
102 mOffsetNorm = ct;
103 }
104 if (c->getKind() == Component::NY) {
105 rsAssert(mSizeNorm == 1);
106 mSizeNorm = 2;
107 }
108 if (c->getKind() == Component::NZ) {
109 rsAssert(mSizeNorm == 2);
110 mSizeNorm = 3;
111 }
112
113 if (c->getKind() == Component::S) {
114 rsAssert(mSizeTex == 0);
115 mSizeTex = 1;
116 mOffsetTex = ct;
117 }
118 if (c->getKind() == Component::T) {
119 rsAssert(mSizeTex == 1);
120 mSizeTex = 2;
121 }
122 }
123 LOGE("TriangleMesh %i,%i %i,%i %i,%i", mSizeCoord, mOffsetCoord, mSizeNorm, mOffsetNorm, mSizeTex, mOffsetTex);
124
125}
126
127
128namespace android {
129namespace renderscript {
130
131void rsi_TriangleMeshBegin(Context *rsc, RsElement vertex, RsElement index)
132{
133 //LOGE("tmb %p %p", vertex, index);
134 TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
135
136 tmc->clear();
137 tmc->mVertexElement = static_cast<Element *>(vertex);
138 tmc->mVertexSizeBits = tmc->mVertexElement->getSizeBits();
139 tmc->mIndexElement = static_cast<Element *>(index);
140 tmc->mIndexSizeBits = tmc->mIndexElement->getSizeBits();
141
142 //LOGE("Element sizes %i %i", tmc->mVertexSizeBits, tmc->mIndexSizeBits);
143
144 assert(!(tmc->mVertexSizeBits & 0x7));
145 assert(!(tmc->mIndexSizeBits & 0x7));
146}
147
148void rsi_TriangleMeshAddVertex(Context *rsc, const void *data)
149{
150 TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
151
152 // todo: Make this efficient.
153 for (uint32_t ct = 0; (ct * 8) < tmc->mVertexSizeBits; ct++) {
154 tmc->mVertexData.add(static_cast<const uint8_t *>(data) [ct]);
155 }
156}
157
158void rsi_TriangleMeshAddTriangle(Context *rsc, uint32_t idx1, uint32_t idx2, uint32_t idx3)
159{
160 TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
161
162 // todo: Make this efficient.
163 switch(tmc->mIndexSizeBits) {
164 case 16:
165 tmc->mIndexData.add(idx1);
166 tmc->mIndexData.add(idx2);
167 tmc->mIndexData.add(idx3);
168 break;
169 default:
170 assert(0);
171 }
172
173 tmc->mTriangleCount++;
174}
175
176RsTriangleMesh rsi_TriangleMeshCreate(Context *rsc)
177{
178 TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
179
180 TriangleMesh * tm = new TriangleMesh();
181 if (!tm) {
182 LOGE("rsTriangleMeshCreate: Error OUT OF MEMORY");
183 // error
184 return 0;
185 }
186
187 tm->mTriangleCount = tmc->mTriangleCount;
188 tm->mIndexDataSize = tmc->mIndexData.size() * tmc->mIndexSizeBits >> 3;
189 tm->mVertexDataSize = tmc->mVertexData.size();
190 tm->mIndexElement = tmc->mIndexElement;
191 tm->mVertexElement = tmc->mVertexElement;
192
193 tm->mIndexData = malloc(tm->mIndexDataSize);
194 tm->mVertexData = malloc(tm->mVertexDataSize);
195 if (!tm->mIndexData || !tm->mVertexData) {
196 LOGE("rsTriangleMeshCreate: Error OUT OF MEMORY");
197 delete tm;
198 return 0;
199 }
200
201 LOGE("Create mesh, triangleCount %i", tm->mTriangleCount);
202
203 memcpy(tm->mVertexData, tmc->mVertexData.array(), tm->mVertexDataSize);
204 memcpy(tm->mIndexData, tmc->mIndexData.array(), tm->mIndexDataSize);
205 tm->analyzeElement();
206
207 return tm;
208}
209
210void rsi_TriangleMeshDestroy(Context *rsc, RsTriangleMesh vtm)
211{
212 TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
213 TriangleMesh * tm = static_cast<TriangleMesh *>(vtm);
214
215 free(tm->mIndexData);
216 free(tm->mVertexData);
217 delete tm;
218}
219
220
221
222void rsi_TriangleMeshRenderRange(Context *rsc, RsTriangleMesh vtm, uint32_t first, uint32_t count)
223{
224 TriangleMesh * tm = static_cast<TriangleMesh *>(vtm);
225
226 rsc->setupCheck();
227
228 //LOGE("1 %p ", vtm);
229 //LOGE("1.1 %p %p", tm->mVertexData, tm->mIndexData);
230 if (!tm->mBufferObjects[0]) {
231 glGenBuffers(2, &tm->mBufferObjects[0]);
232
233 glBindBuffer(GL_ARRAY_BUFFER, tm->mBufferObjects[0]);
234 glBufferData(GL_ARRAY_BUFFER, tm->mVertexDataSize, tm->mVertexData, GL_STATIC_DRAW);
235 glBindBuffer(GL_ARRAY_BUFFER, 0);
236
237 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
238 glBufferData(GL_ELEMENT_ARRAY_BUFFER, tm->mIndexDataSize, tm->mIndexData, GL_STATIC_DRAW);
239 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
240 }
241
242 //LOGE("1.2");
243 if (first >= tm->mTriangleCount) {
244 return;
245 }
246 if (count >= (tm->mTriangleCount - first)) {
247 count = tm->mTriangleCount - first;
248 }
249 if (!count) {
250 return;
251 }
252
253 const float *f = (const float *)tm->mVertexData;
254
255 //LOGE("2");
256 glBindBuffer(GL_ARRAY_BUFFER, tm->mBufferObjects[0]);
257 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
258
259 glEnableClientState(GL_VERTEX_ARRAY);
260 glVertexPointer(tm->mSizeCoord,
261 GL_FLOAT,
262 tm->mVertexElement->getSizeBytes(),
263 (void *)tm->mVertexElement->getComponentOffsetBytes(tm->mOffsetCoord));
264
265 if (tm->mSizeTex) {
266 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
267 glTexCoordPointer(tm->mSizeTex,
268 GL_FLOAT,
269 tm->mVertexElement->getSizeBytes(),
270 (void *)tm->mVertexElement->getComponentOffsetBytes(tm->mOffsetTex));
271 } else {
272 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
273 }
274
275 if (tm->mSizeNorm) {
276 glEnableClientState(GL_NORMAL_ARRAY);
277 glNormalPointer(GL_FLOAT,
278 tm->mVertexElement->getSizeBytes(),
279 (void *)tm->mVertexElement->getComponentOffsetBytes(tm->mOffsetNorm));
280 } else {
281 glDisableClientState(GL_NORMAL_ARRAY);
282 }
283
284 glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_SHORT, (GLvoid *)(first * 3 * 2));
285
286 //LOGE("4");
287
288 glBindBuffer(GL_ARRAY_BUFFER, 0);
289 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
290}
291
292void rsi_TriangleMeshRender(Context *rsc, RsTriangleMesh vtm)
293{
294 rsi_TriangleMeshRenderRange(rsc, vtm, 0, 0xffffff);
295}
296
297}}