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