|
1 /* |
|
2 * Name : Object.cpp |
|
3 * Description : |
|
4 * Project : This file is part of OpenMAR, an Open Mobile Augmented Reality browser |
|
5 * Website : http://OpenMAR.org |
|
6 * |
|
7 * Copyright (c) 2010 David Caabeiro |
|
8 * |
|
9 * All rights reserved. This program and the accompanying materials are made available |
|
10 * under the terms of the Eclipse Public License v1.0 which accompanies this |
|
11 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html |
|
12 * |
|
13 */ |
|
14 |
|
15 #include "Object.h" |
|
16 |
|
17 #include "IconLoader.h" |
|
18 #include "Vector3d.h" |
|
19 |
|
20 #include <bitdev.h> |
|
21 #include <bitstd.h> |
|
22 #include <fbs.h> |
|
23 #include <GulIcon.h> |
|
24 #include <GLES/egl.h> |
|
25 |
|
26 #include <Landmarks_0x2002E1AF.mbg> |
|
27 |
|
28 #include "Logger.h" |
|
29 |
|
30 CLMXObject* CLMXObject::NewL(OpenMAR::CPOIProvider* aProvider) |
|
31 { |
|
32 CLMXObject* self = new(ELeave) CLMXObject(aProvider); |
|
33 CleanupStack::PushL(self); |
|
34 self->ConstructL(); |
|
35 CleanupStack::Pop(self); |
|
36 |
|
37 return self; |
|
38 } |
|
39 |
|
40 CLMXObject::~CLMXObject() |
|
41 { |
|
42 ::glDeleteTextures(1, &iTextureId); |
|
43 } |
|
44 |
|
45 CLMXObject::CLMXObject(OpenMAR::CPOIProvider* aProvider) |
|
46 : OpenMAR::CPOIObject(*aProvider) |
|
47 {} |
|
48 |
|
49 /* |
|
50 * Landmark objects will make use of an SVG file for rendering (demo purposes) |
|
51 */ |
|
52 void CLMXObject::ConstructL() |
|
53 { |
|
54 _LIT(KIconFile, "\\resource\\apps\\Landmarks_0x2002E1AF.mif"); |
|
55 |
|
56 CGulIcon* icon = CreateIconL(KIconFile, EMbmLandmarks_0x2002e1afIcon, EMbmLandmarks_0x2002e1afIcon_mask); |
|
57 CleanupStack::PushL(icon); |
|
58 |
|
59 CFbsBitmap* bitmap = icon->Bitmap(); // Ownership NOT transferred |
|
60 CFbsBitmap* mask = icon->Mask(); // Ownership NOT transferred |
|
61 |
|
62 // Always expect 16M bitmap to make conversion to GL_RGBA easier |
|
63 if (bitmap->DisplayMode() != EColor16M) |
|
64 { |
|
65 bitmap = new(ELeave) CFbsBitmap; |
|
66 CleanupStack::PushL(bitmap); |
|
67 |
|
68 User::LeaveIfError(bitmap->Create(icon->Bitmap()->SizeInPixels(), EColor16M)); |
|
69 |
|
70 CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(bitmap); |
|
71 CleanupStack::PushL(bitmapDevice); |
|
72 |
|
73 CFbsBitGc* bitmapContext = 0; |
|
74 User::LeaveIfError(bitmapDevice->CreateContext(bitmapContext)); |
|
75 CleanupStack::PushL(bitmapContext); |
|
76 |
|
77 bitmapContext->BitBlt(TPoint(0, 0), icon->Bitmap()); |
|
78 |
|
79 CleanupStack::PopAndDestroy(2, bitmapDevice); |
|
80 |
|
81 icon->SetBitmap(bitmap); // Ownership transferred |
|
82 |
|
83 CleanupStack::Pop(bitmap); |
|
84 } |
|
85 |
|
86 // Always expect 256 mask to make conversion to GL_RGBA easier |
|
87 if (mask->DisplayMode() != EGray256) |
|
88 { |
|
89 mask = new(ELeave) CFbsBitmap; |
|
90 CleanupStack::PushL(mask); |
|
91 |
|
92 User::LeaveIfError(mask->Create(icon->Mask()->SizeInPixels(), EGray256)); |
|
93 |
|
94 CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(mask); |
|
95 CleanupStack::PushL(bitmapDevice); |
|
96 |
|
97 CFbsBitGc* bitmapContext = 0; |
|
98 User::LeaveIfError(bitmapDevice->CreateContext(bitmapContext)); |
|
99 CleanupStack::PushL(bitmapContext); |
|
100 |
|
101 bitmapContext->BitBlt(TPoint(0, 0), icon->Mask()); |
|
102 |
|
103 CleanupStack::PopAndDestroy(2, bitmapDevice); |
|
104 |
|
105 icon->SetMask(mask); // Ownership transferred |
|
106 |
|
107 CleanupStack::Pop(mask); |
|
108 } |
|
109 |
|
110 // Now bitmap and mask point to either original or converted bitmaps, |
|
111 // and ownership belongs to icon |
|
112 |
|
113 const TSize bitmapSize = bitmap->SizeInPixels(); |
|
114 |
|
115 // sizeof(TUint32) == sizeof(RGBA) |
|
116 const TInt dataSize = bitmapSize.iWidth * bitmapSize.iHeight * sizeof(TUint32); |
|
117 TUint8* data = new(ELeave) TUint8[dataSize]; |
|
118 |
|
119 // Perform copy and conversion from BGR(A) to RGB(A) |
|
120 bitmap->LockHeap(); |
|
121 mask->LockHeap(); |
|
122 |
|
123 // TODO: Alpha component removed, as it seems to be corrupted from |
|
124 // subsequent reads from SVG file |
|
125 |
|
126 TUint8* rgb = reinterpret_cast<TUint8*>(bitmap->DataAddress()); |
|
127 // TUint8* alpha = reinterpret_cast<TUint8*>(mask->DataAddress()); |
|
128 |
|
129 for(TInt i = 0, j = 0; i < dataSize; i += 4, j += 3) |
|
130 { |
|
131 data[i + 0] = rgb[j + 2]; |
|
132 data[i + 1] = rgb[j + 1]; |
|
133 data[i + 2] = rgb[j + 0]; |
|
134 data[i + 3] = 0xc0; //alpha[i / 4]; |
|
135 } |
|
136 |
|
137 // Generate OpenGL texture |
|
138 ::glGenTextures(1, &iTextureId); |
|
139 ::glBindTexture(GL_TEXTURE_2D, iTextureId); |
|
140 |
|
141 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
|
142 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
|
143 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
|
144 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
|
145 |
|
146 ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmapSize.iWidth, bitmapSize.iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); |
|
147 |
|
148 mask->UnlockHeap(); |
|
149 bitmap->UnlockHeap(); |
|
150 |
|
151 delete data; |
|
152 |
|
153 CleanupStack::PopAndDestroy(icon); |
|
154 } |
|
155 |
|
156 void CLMXObject::Render() const |
|
157 { |
|
158 /* |
|
159 * This is a special case for points or planes in space. Given that a usual POI |
|
160 * does not provide of any transformation to be applied on it, we determine the |
|
161 * angle in the XY plane with respect to the observer and apply that rotation to |
|
162 * the object. |
|
163 * |
|
164 * This way, all POIs will face the observer regardless their position. Other |
|
165 * objects (3D Landmarks, etc) should provide their own transformations in some |
|
166 * proper way. |
|
167 */ |
|
168 |
|
169 TReal angle = 0; |
|
170 Math::ATan(angle, iPosition.mX, iPosition.mY); |
|
171 angle *= -KRadToDeg; |
|
172 |
|
173 /* |
|
174 * We could also apply some scaling calculation to compensate the size of |
|
175 * objects projected at a long distance from the camera. |
|
176 * For now we just use a constant value |
|
177 */ |
|
178 |
|
179 TReal scale = 64.0f; |
|
180 |
|
181 // Apply transformations to the object and render it |
|
182 |
|
183 const TInt unity = 1 << 16; |
|
184 |
|
185 GLfixed vertices[] = { |
|
186 -unity / 2, 0, 0, |
|
187 unity / 2, 0, 0, |
|
188 -unity / 2, 0, unity, |
|
189 unity / 2, 0, unity, |
|
190 }; |
|
191 |
|
192 GLfixed texCoords[] = { |
|
193 0, unity, |
|
194 unity, unity, |
|
195 0, 0, |
|
196 unity, 0 |
|
197 }; |
|
198 |
|
199 ::glPushMatrix(); |
|
200 |
|
201 ::glTranslatef(iPosition.mX, iPosition.mY, iPosition.mZ); |
|
202 ::glRotatef(angle, 0, 0, 1); |
|
203 ::glScalef(scale, 1.0f, scale); |
|
204 |
|
205 ::glEnable(GL_TEXTURE_2D); |
|
206 ::glBindTexture(GL_TEXTURE_2D, iTextureId); |
|
207 ::glVertexPointer(3, GL_FIXED, 0, vertices); |
|
208 ::glTexCoordPointer(2, GL_FIXED, 0, texCoords); |
|
209 ::glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
|
210 ::glDisable(GL_TEXTURE_2D); |
|
211 |
|
212 ::glPopMatrix(); |
|
213 } |