7 class MyApp : GuiApplication
10 // driver = "Direct3D";
15 materialsTest.updateModel();
23 position = Vector3D { 0, 0, -300 },
24 orientation = Euler { }; //30, 30, 0 },
25 fovDirection = vertical,
29 Object cameraTarget { };
33 transform = { position = { 0, 0, -10 }, scaling = { 1, 1, 1 } };
42 specular = white; //blue;
43 //flags = { attenuation = true };
44 lightObject = posLight;
53 orientation = Euler { pitch = 40, yaw = 50 };
60 define rDiamond = 2.42;
62 class MaterialsTest : Window
64 caption = "Materials Test";
66 #if defined(__EMSCRIPTEN__)
67 anchor = { 0, 0, 0, 0 };
69 borderStyle = sizable;
76 // glCapabilities.shaders = true;
80 Sphere roundedCylinder { flattenedBody = 0.3f };
89 size = { 10000, 10000, 10000 },
90 folder = ":watersky", extension = "jpg",
91 cubeMap = waterCubeMap
97 size = { 10000, 10000, 10000 },
98 folder = ":forest", extension = "jpg", newStyle = true,
99 cubeMap = forestCubeMap
103 font = { "Tahoma", 12, true, outlineSize = 3.0, outlineFade = 0.2 };
107 static Time lastTime = 0;
108 Time time = GetTime(), diffTime = lastTime ? (time - lastTime) : 0;
109 Transform transform = model.transform;
110 if(spin.yaw || spin.pitch)
112 int signYaw = 1, signPitch = 1;
113 Radians yaw = spin.yaw, pitch = spin.pitch;
114 Quaternion orientation = transform.orientation;
115 Euler tSpin { yaw * (double)diffTime, pitch * (double)diffTime, 0 };
116 Quaternion thisSpin = tSpin, temp;
118 if(yaw < 0) { yaw = -yaw; signYaw = -1; }
119 if(pitch < 0) { pitch = -pitch; signPitch = -1; }
120 yaw -= (double)diffTime / 3 * yaw;
121 pitch -= (double)diffTime / 3 * pitch;
122 if(yaw < 0.0001) yaw = 0;
123 if(pitch < 0.0001) pitch = 0;
125 spin.yaw = yaw * signYaw;
126 spin.pitch = pitch * signPitch;
128 temp.Multiply(orientation, thisSpin);
129 orientation.Normalize(temp);
131 model.transform.orientation = orientation;
132 //transform.orientation = orientation;
133 //model.transform = transform;
134 model.UpdateTransform();
142 BitmapResource bumpMap { "bumpmap.png", window = this };
143 BitmapResource baseMap { "basetex.bmp", window = this };
145 BitmapResource bumpMap { ":normal.jpg", mipMaps = true, window = this };
146 // BitmapResource bumpMap { ":normal.png", mipMaps = true, window = this };
147 //BitmapResource baseMap { "diffuse.png", mipMaps = true, window = this };
148 // BitmapResource specularMap { "specular.jpg", mipMaps = true, window = this };
149 CubeMap waterCubeMap { };
150 //CubeMap forestCubeMap { };
154 ambient = blue; //white;
155 diffuse = blue; //white;
156 //specular = { 3.0, 3.0, 3.0 };
157 specular = { 1.0, 1.0, 3.0 };
163 separateSpecular = true;
165 uScale = 4, vScale = 4;
167 refractiveIndex = rGlass;
171 void prepareModel(Object model, float s)
173 model.transform.scaling = { s, s, s };
174 model.transform.position = { 0, 0, 0 };
175 model.UpdateTransform();
176 model.SetMinMaxRadius(false);
177 model.mesh.ApplyMaterial(material);
180 void viewModel(Object model, double distance, float uvScale)
182 double r = model.radius * model.transform.scaling.z; //wradius;
183 material.uScale = uvScale;
184 material.vScale = uvScale;
185 camera.position = { 0, 0, -r * distance };
186 cameraTarget.transform.position =
188 (model.max.x + model.min.x) / 2,
189 (model.max.y + model.min.y) / 2,
190 (model.max.z + model.min.z) / 2
196 void selectEnv(SkyBox sky, CubeMap cubeMap)
198 material.envMap = cubeMap;
203 bool OnLoadGraphics()
205 const String faceNames1[] = { ":watersky/rt", ":watersky/lf", ":watersky/up", ":watersky/dn", ":watersky/bk", ":watersky/fr" };
206 //const String faceNames2[] = { ":forest/rt", ":forest/lf", ":forest/up", ":forest/dn", ":forest/bk", ":forest/fr" };
208 //material.bumpMap = bumpMap.bitmap;
209 //material.baseMap = baseMap.bitmap;
210 //material.specularMap = specularMap.bitmap;
211 //material.reflectMap = specularMap.bitmap;
214 if(!waterCubeMap.Load(displaySystem, faceNames1, "jpg", true)) waterBox.cubeMap = null;
216 //if(!forestCubeMap.Load(displaySystem, faceNames2, "jpg", false)) forestBox.cubeMap = null;
218 teapot.Load(":teapot.3DS", null, displaySystem);
219 teapot.Merge(displaySystem);
220 teapot.mesh.ApplyMaterial(material);
221 prepareModel(teapot, 1);
223 roundedCylinder.Create(displaySystem);
224 prepareModel(roundedCylinder, 50);
226 sphere.Create(displaySystem);
227 prepareModel(sphere, 50);
229 cube.Create(displaySystem);
230 prepareModel(cube, 50);
232 camera.target = cameraTarget;
236 waterBox.size = { camera.zMax, camera.zMax, camera.zMax };
237 //forestBox.size = { camera.zMax, camera.zMax, camera.zMax };
238 waterBox.Create(displaySystem);
239 //forestBox.Create(displaySystem);
241 viewModel(sphere, 1.5 * sqrt(2), 4.0);
242 //viewModel(cube, 1.5 * 2, 2);
243 //viewModel(teapot, 1.5 * 2, 2);
244 selectEnv(waterBox, waterCubeMap);
245 // selectEnv(forestBox, forestCubeMap);
249 void OnResize(int w, int h)
251 camera.Setup(w, h, null);
255 void OnRedraw(Surface surface)
260 GetMousePosition(&x, &y);
262 posLight.transform.position =
264 (x - clientSize.w / 2) * 400 / clientSize.w,
265 (y - clientSize.h / 2) * 400 / clientSize.h,
268 posLight.UpdateTransform();
270 surface.Clear(depthBuffer);
272 // Setting the light before the camera means the light is in view space
273 //display.SetLight(0, posLight.light);
274 display.SetLight(0, light);
275 // display.ambient = { };
277 //display.ambient = { 255, 0, 0 };
278 display.SetCamera(surface, camera);
280 // Setting the light before the camera means the light is in world space
281 //display.SetLight(0, light);
283 sky.Render(camera, display);
285 display.DrawObject(model);
286 display.SetCamera(surface, null);
288 surface.outlineColor = black;
289 surface.foreground = white;
291 surface.WriteTextf(10, 10, "('R' to toggle') Reflection: %s, Refraction: %s",
292 material.reflectivity ? "ON" : "OFF",
293 material.refractiveIndex ? "ON" : "OFF");
294 surface.WriteTextf(10, 40, "('C' to toggle') Shape: %s ",
295 model == cube ? "Cube" : model == sphere ? "Sphere" : model == roundedCylinder ? "Rounded Cylinder" : "Teapot");
296 /*surface.WriteTextf(10, 70, "('E' to toggle') Environment: %s",
297 material.envMap == waterCubeMap ? "Water & Sky" : "Forest");*/
298 surface.WriteTextf(10, 100, "('B' to toggle') Normal Map: %s",
299 material.bumpMap ? "ON" : "OFF");
300 surface.WriteTextf(10, 130, "Left-Button Drag: Rotate Camera; Middle-Button Drag: Spin Model; Right-Button Drag: Rotate Light");
301 surface.WriteTextf(10, 160, "Scroll Wheel: Move camera closer / further");
302 #ifndef __EMSCRIPTEN__
303 surface.WriteTextf(10, 200, "Shaders: %s", glCapabilities.shaders ? "ON" : "OFF");
308 bool moving, movingCamera, movingLight;
311 Euler startOrientation;
313 bool OnMiddleButtonDown(int x, int y, Modifiers mods)
315 clickTime = GetTime();
317 startClick = { x, y };
322 bool OnMiddleButtonUp(int x, int y, Modifiers mods)
332 bool OnLeftButtonDown(int x, int y, Modifiers mods)
334 if(!movingCamera && !moving && !movingLight)
338 startOrientation = camera.eulerOrientation;
345 bool OnLeftButtonUp(int x, int y, Modifiers mods)
350 movingCamera = false;
355 bool OnRightButtonDown(int x, int y, Modifiers mods)
357 if(!moving && !movingLight)
361 startOrientation = light.orientation;
368 bool OnRightButtonUp(int x, int y, Modifiers mods)
378 bool OnMouseMove(int x, int y, Modifiers mods)
382 Time time = GetTime(), diffTime = Max(time - clickTime, 0.01);
383 spin.yaw += Degrees { (x - startClick.x) / (25.0 * (double)diffTime) };
384 spin.pitch += Degrees { (startClick.y - y) / (25.0 * (double)diffTime) };
385 startClick = { x, y };
388 else if(movingCamera)
392 startOrientation.yaw - (x - startPosition.x),
393 startOrientation.pitch + (y - startPosition.y),
397 camera.eulerOrientation = euler;
403 light.orientation = Euler
405 startOrientation.yaw - (x - startPosition.x),
406 startOrientation.pitch + (y - startPosition.y),
416 bool OnKeyHit(Key key, unichar ch)
420 case wheelDown: case minus: camera.position.z *= 1.1111111f; Update(null); break;
421 case wheelUp: case plus: camera.position.z *= 0.9f; Update(null); break;
423 glCapabilities.shaders ^= true;
428 viewModel(sphere, 1.5 * sqrt(2), 4);
429 else if(model == sphere)
430 viewModel(roundedCylinder, 1.5 * sqrt(2), 4);
431 else if(model == roundedCylinder)
432 viewModel(teapot, 1.5 * sqrt(2), 1.5);
433 else if(model == teapot)
434 viewModel(cube, 1.5 * 2, 2);
439 selectEnv(forestBox, forestCubeMap);
441 selectEnv(waterBox, waterCubeMap);
445 static bool debugging = false;
447 DefaultShader::shader().debugging(debugging);
452 material.bumpMap = material.bumpMap ? null : bumpMap.bitmap;
456 if(material.reflectivity && material.refractiveIndex)
458 material.refractiveIndex = 0;
459 material.opacity = 1.0;
460 material.reflectivity = 0.8;
462 else if(material.reflectivity)
464 material.reflectivity = 0;
465 material.refractiveIndex = rGlass;
466 material.opacity = 0.3;
468 else if(material.refractiveIndex)
470 material.refractiveIndex = 0.0;
471 material.opacity = 1.0;
475 material.reflectivity = 0.3;
476 material.refractiveIndex = rGlass;
477 material.opacity = 0.3;
486 MaterialsTest materialsTest {};