1:////////////////////////////////////////////////////////////////////////////// 2:// 3:// CMOTHERBOARD.CPP 4:// Implementation file for CMotherboard, CWhisp classes 5:// 6:// - CMotherboard defines a 3D fly-through of a motherboard 7:// - CWhip is a whisp of light used in the motherboard scene 8:// - Tabs set at 3. (Tronster prefers real tabs, Moby Disk prefers spaces.) 9:// 10:////////////////////////////////////////////////////////////////////////////// 11: 12:#pragma warning(disable:4786) 13:#include <stdlib.h> // Header has rand() 14:#include "CMotherboard.h" 15:#include "loaders3d.h" // GeoGL: 3SO file loader 16:#include "tesselate3d.h" // GeoGL: Object tesselator 17: 18:// Define in CMotherboard header for manual control 19:#ifdef MANUAL_CONTROL 20:#include <iostream> // Manual control supports console output 21:#endif MANUAL_CONTROL 22: 23:// Import geoGL and STL namespaces 24:using namespace geoGL; 25:using namespace std; 26: 27:// User interface control settings 28:#define MOTIONSPEED 0.5f // Speed of manual control 29: 30:// Nifty variations on appearance 31:#define FLUXINESS 0.75f // How much the glowing dots waver around 32:#define WHISP_SIZE (5.0f/3.0f) // Size of whispy lights 33:#define SOCKET_XSIZE 15.0f // Size of CPU socket 34:#define SOCKET_YSIZE 15.0f 35:#define LIGHT_HOVER_Z 10 // Height of lighting light ball above -->motherboard 36: 37:// RGB colors defining "background" of mindware microchip logo 38:#define BACK_GRAY 128 39:#define BACK_RED 128 40:#define BACK_GREEN 128 41:#define BACK_BLUE 128 42: 43:// Light map settings 44:#define LIGHT_FWD_DIST 25 45:#define LIGHT_PWR2 6 46:#define LIGHT_DIM (1<<LIGHT_PWR2) 47:#define LIGHT_SIZE 10.0f 48:#define PHONG 64 49: 50:// Times in MS for start and duration of events 51:#define GLOWSTART 65000 // Glowing starts 52:#define GLOWTIME 4000 53:#define CHIPSTART (GLOWSTART+5000) // Chip starts falling 54:#define CHIPTIME 5000 55:#define ANIMSTART (CHIPSTART+CHIPTIME+GLOWTIME) // Chip logo animates 56:#define ANIMTIME 5000 57:#define FADESTART (ANIMSTART+5000) // Fadeout 58:#define FADETIME 3000 59:#define FINALSTART (FADESTART+FADETIME+3000) 60:#define FINALTIME 1500 61: 62:/******************************** Non-members *********************************/ 63: 64:// Random floating point number 0..1 65:static inline float frand01() { return rand() / static_cast<float>(RAND_MAX); } 66:// Random floating point number -1..1 67:static inline float frand11() { return (rand()/ static_cast<float>(RAND_MAX)) * 2 - 1; } 68: 69:// Generic min/max routines 70:template <class T> static inline T TMAX(T T1, T T2) { return (T1>T2 ? T1 : T2); } 71:template <class T> static inline T TMIN(T T1, T T2) { return (T1<T2 ? T1 : T2); } 72: 73:////////////////////////////////////////////////////////////////////////////// 74:// 75:// Compute animation factor 0..1 76:// - Uses the current & start times and durations to compute a number 0..1 77:// 78:// 79:// RETURNS: 0 = start of effect or before effect 80:// 0-1 = lienar progression between start/end time 81:// 1 = end of effect or after effect 82:// 83:////////////////////////////////////////////////////////////////////////////// 84:static float calcFactor(unsigned int nElapsedTime, unsigned int nStartTime, unsigned int -->nDuration) 85:{ 86: if (nElapsedTime<nStartTime) return 0; 87: if (nElapsedTime>nStartTime+nDuration) return 1; 88: return static_cast<float>(nElapsedTime-nStartTime) / nDuration; 89:} 90: 91:////////////////////////////////////////////////////////////////////////////// 92:// 93:// Load a bitmap texture 94:// - Load image using mediaduke (PNG/BMP/whatever) 95:// - Create mipmapped texture 96:// - Add to geoGL texture list (so object loader can access them) 97:// 98:// ARGS: mediaDuke, Mediaduke object for image loading 99:// filename, name+ext of image file to load 100:// textureName, unique string name of texture for use by object loader 101:// 102:// RETURNS: texture ID number 103:// 104:////////////////////////////////////////////////////////////////////////////// 105:GLuint CMotherboard::loadGLTexture( 106: md::CmediaDuke &mediaDuke, char *filename, char *textureName/*=NULL*/) 107:{ 108: GLuint nTexture; // Texture ID number 109: md::Cimage textureImage; // Mediaduke image 110: 111: // Load image, return on failure 112: if (!mediaDuke.read(filename,textureImage)) 113: { 114: char temp[200]; 115: sprintf(temp,"Unable to read \"%s\"",filename); 116: throw temp; 117: } 118: throwMessage("Unable to read \"%s\"",filename); 119: 120: // Cimage create an opengl texture - returns -1 on error 121: nTexture = textureImage.makeGLTexture(m_oEnvInfo.glWantMipmap, m_oEnvInfo.glWantLinear); 122: 123: // Unable to create texture? Throw an error 124: if (nTexture<=0) { 125: char temp[200]; 126: sprintf(temp,"Unable to create texture \"%s\"",filename); 127: throw temp; 128: } 129: if (nTexture<=0) 130: throwMessage("Unable to create textures \"%s\"",filename); 131: 132: // Add texture to map using unique name. GeoGL object loader can now use this texture. 133: if (textureName) 134: mapTextures[string(textureName)] = nTexture; 135: 136: // Return texture id 137: return nTexture; 138:} 139: 140:/******************************** CDemoEffect *********************************/ 141: 142: 143:////////////////////////////////////////////////////////////////////////////// 144:// 145:// Construct motherboard effect 146:// - Store a reference to the environment information 147:// 148:////////////////////////////////////////////////////////////////////////////// 149:CMotherboard::CMotherboard(CEnvInfo *oEnvInfo) : m_oEnvInfo(*oEnvInfo) {} 150: 151: 152:////////////////////////////////////////////////////////////////////////////// 153:// 154:// Destroy the motherboard 155:// - Has Tronster's cool destructor tracking (for memory leaks) 156:// 157:////////////////////////////////////////////////////////////////////////////// 158:CMotherboard::~CMotherboard() 159:{ 160: MSG("~CMotherboard()") 161: unInit(); 162: MSGEND 163:} 164: 165: 166:////////////////////////////////////////////////////////////////////////////// 167:// 168:// Start the motherboard effect 169:// - Called by demo just before first frame 170:// - Apply opengl settings that other effect may have overridden 171:// - Begin time counter 172:// 173:// RETURNS: true on success (always) 174:// 175:////////////////////////////////////////////////////////////////////////////// 176:bool CMotherboard::start() 177:{ 178: initGLstuff(); // Initialize opengl settings 179: 180: // Setup view frustum 181: glMatrixMode(GL_PROJECTION); 182: glLoadIdentity(); 183: gluPerspective(45.0f,static_cast<float>(m_oEnvInfo.nWinWidth)/m_oEnvInfo.nWinHeight,2,270.0f); --> 184: frustum.init (45.0f,static_cast<float>(m_oEnvInfo.nWinWidth)/m_oEnvInfo.nWinHeight,2,270.0f); --> 185: // force 4/3 aspect ratio even if the window is stretched 186: gluPerspective(45.0f, 4.0f/3.0f, 2,270.0f); 187: frustum.init (45.0f, 4.0f/3.0f, 2,270.0f); 188: glMatrixMode(GL_MODELVIEW); 189: 190: // Save start time, and start the fly through 191: nTimeStart = m_oEnvInfo.getMusicTime(); 192: flight.start(); 193: flight.start(0); 194: 195: // Doesn't bother to check for errors, but it should 196: return true; 197:} 198: 199:////////////////////////////////////////////////////////////////////////////// 200:// 201:// Stop the motherboard effect 202:// - Clear any lighting and weird stuff so other effects are happy 203:// 204:// RETURNS: true on success (always) 205:// 206:////////////////////////////////////////////////////////////////////////////// 207:bool CMotherboard::stop() 208:{ 209: // Disable light attenuation 210: glLightf(GL_LIGHT0+light0.nLightID,GL_LINEAR_ATTENUATION,0); 211: 212: // Turn off all our lights 213: light0.off(); 214: lightSocket.off(); 215: 216: // Doesn't bother to check for errors, but it should 217: return true; 218:} 219: 220:////////////////////////////////////////////////////////////////////////////// 221:// 222:// Initialize and load the motherboard 223:// - Precompute quality values 224:// - Load objects 225:// - Initialize manual control if applicable 226:// 227:// RETURNS: true on success (always) 228:// 229:////////////////////////////////////////////////////////////////////////////// 230:bool CMotherboard::init() 231:{ 232: // Grab demo quality and scale things according to it 233: // It can range 0..10..infinity 234: int nQuality = m_oEnvInfo.nDemoQuality; 235: 236: // Number of whisps to display at each quality setting (0..10) 237: static const float num_Whispy[11] = {32,66,100,134,166,200,280,400,530,660,800}; 238: static const int num_Whispy[11] = {32,66,100,134,166,200,280,400,530,660,800}; 239: if (nQuality<11) 240: nWhispy = num_Whispy[nQuality]; // Normal range (0..10) lookup in table 241: else 242: nWhispy = num_Whispy[10]*nQuality/10; // Above 10, scale lineaarly beyond... 243: nWhispy = num_Whispy[10]*nQuality/10; // Above 10, scale linearly beyond... 244: 245: // How much to tesselate objects 246: // - The BIGGER this is the LESS tesselated 247: // - The SMALLER this is, the MORE tesselated 248: // - This factor will actually refer to the length of the longest side in a 249: // tesselated object. This results in a very nonlinear growth in # of sides! 250: if (nQuality<=2) 251: fTesselationFactor = 1000; // Insanely large, never tesselate 252: else 253: fTesselationFactor = 5.0f/nQuality; // Use quality to determine tesselation 254: 255: // Determine bump map to use 256: // <=5 -- no bump map 257: // 6,7 -- 256x256 bump map 258: // 8+ -- 512x512 bump map 259: if (nQuality>=8) m_szBumpFile = "mb_bump512.png"; else 260: if (nQuality>=6) m_szBumpFile = "mb_bump256.png"; else 261: m_szBumpFile = NULL; 262: 263: 264: // Initialize objects, textures, camera... 265: initObjects(); 266: 267: // Initialize the light map tables for bump map (if doing bump map) 268: if (m_szBumpFile) 269: initLight(); 270: 271: // If under manual control, set the start position 272: #ifdef MANUAL_CONTROL 273: motion = zero3D; 274: rotation= zero3D; 275: #endif 276: 277: // Doesn't bother to check for errors, but it should 278: return true; 279:} 280: 281:////////////////////////////////////////////////////////////////////////////// 282:// 283:// Uninitialize 284:// - Unload objects, textures, etc. Generally free memory. 285:// 286:// RETURNS: true on success (always) 287:// 288:////////////////////////////////////////////////////////////////////////////// 289:// ???WHG??? Add methods to cleanup geometry3d classes 290:bool CMotherboard::unInit() 291:{ 292: // Doesn't bother to check for errors, but it should 293: return true; 294:} 295: 296:////////////////////////////////////////////////////////////////////////////// 297:// 298:// Load all textures 299:// - Load PNG files using mediaduke object (available through CEnvInfo) 300:// - Create procedural textures (for animating mindware logo) 301:// 302:////////////////////////////////////////////////////////////////////////////// 303:void CMotherboard::loadGLTextures() 304:{ 305: // Load generic PNG textures in the "smart" texture IDs 306: text_cap32 = loadGLTexture(m_oEnvInfo.oMedia,"cap32.png", "cap32"); 307: text_res32 = loadGLTexture(m_oEnvInfo.oMedia,"res32.png", "res32"); 308: text_circuit = loadGLTexture(m_oEnvInfo.oMedia,"chip2.png", "circuit"); 309: text_flare1 = loadGLTexture(m_oEnvInfo.oMedia,"flare1.png", "flare1"); 310: text_flare3 = loadGLTexture(m_oEnvInfo.oMedia,"flare3.png", "flare3"); 311: text_mbmap = loadGLTexture(m_oEnvInfo.oMedia,"mb_map.png", "mb_map"); 312: text_socket = loadGLTexture(m_oEnvInfo.oMedia,"socket.png", "socket"); 313: text_slot = loadGLTexture(m_oEnvInfo.oMedia,"slot.png", "slot"); 314: text_metal1 = loadGLTexture(m_oEnvInfo.oMedia,"metal.png", "metal1"); 315: text_microchip1 = loadGLTexture(m_oEnvInfo.oMedia,"microchip1.png", "microchip1"); 316: text_microchip2 = loadGLTexture(m_oEnvInfo.oMedia,"mindwarethreesomecoma2.png","microchip2") -->; 317: text_greenchip = loadGLTexture(m_oEnvInfo.oMedia,"creditschip.png","greenchip"); 318: 319: //////////////// Custom mindware procedural texture //////////////// 320: // This is a texture that starts out blank, but will get drawn on as the effect 321: // progresses. So we load the final image (img_mindware) and hold on to it. Then 322: // another image of matching dimensions is created. This image is made into a texture 323: // that will be used on the actual object. 324: 325: // Load mindware logo 326: if (!m_oEnvInfo.oMedia.read("mindware.png",img_mindware)) 327: { 328: char temp[200]; 329: sprintf(temp,"Unable to read \"%s\"","mindware.png"); 330: throw temp; 331: } 332: throwMessage("Unable to read \"%s\"","mindware.png"); 333: 334: // Convert to RGB 335: // - This would be done automatically if we created a texture out of it 336: if (img_mindware.palette) 337: img_mindware.makeDataRGB(); 338: 339: // Create RGB image to draw on, then fill with neutral color 340: img_mindware0.create(img_mindware.x,img_mindware.y,3); 341: memset(img_mindware0.data, BACK_GRAY, img_mindware0.x*img_mindware0.y*3); 342: 343: // Make image into a texture - throw error if problem arises 344: text_mindware = img_mindware0.makeGLTexture(m_oEnvInfo.glWantLinear, m_oEnvInfo.glWantLinear); --> 345: 346: if (text_mindware<=0) { 347: char temp[200]; 348: sprintf(temp,"Unable to create procedural texture mindware0"); 349: throw temp; 350: } 351: if (text_mindware<=0) 352: throwMessage("Unable to create procedural texture mindware0"); 353: 354: ///////////////////// Custom mindware lightmap ///////////////////// 355: // Load motherboard bump map -- if we are using one 356: if (m_szBumpFile) 357: { 358: if (!m_oEnvInfo.oMedia.read(m_szBumpFile,img_bump)) 359: { 360: char temp[200]; 361: sprintf(temp,"Unable to read \"%s\"",m_szBumpFile); 362: throw temp; 363: } 364: throwMessage("Unable to read \"%s\"",m_szBumpFile); 365: 366: // Verify bump map is 8-bit 367: if (img_bump.bytesPerPixel != 1) 368: throw "Bump map should be 256 color grayscale!"; 369: throwMessage("Bump map should be 256 color grayscale!"); 370: 371: // Create RGB image to draw on, then fill with neutral color 372: img_lightMap.create(img_bump.x,img_bump.y,3); 373: memset(img_lightMap.data, 0, img_lightMap.x*img_lightMap.y*3); 374: 375: // Make image into a texture - throw error if problem arises 376: text_lightMap = img_lightMap.makeGLTexture(m_oEnvInfo.glWantLinear, m_oEnvInfo. -->glWantLinear); 377: 378: if (text_lightMap<=0) { 379: char temp[200]; 380: sprintf(temp,"Unable to create procedural texture text_lightMap"); 381: throw temp; 382: } 383: if (text_lightMap<=0) 384: throwMessage("Unable to create procedural texture text_lightMap"); 385: } else 386: text_lightMap = 0; // Done bump map 387: 388: 389: //////////////// Light beam 1D procedural texture //////////////// 390: // And you thought 1D textures were useless... 391: // Then light beam does not strike on the background color - only on texels 392: // that are going to change. To do this, the light beam uses a 1D texture 393: // as a "mask" for where to draw a line, and where not to draw it 394: 395: // Create a "1D" image 396: // The width is same as the logo, but the height is 1 397: img_animate.create(img_mindware.x,1,3); 398: for (int zz=0; zz<img_animate.x; zz++) { 399: img_animate.data[zz*3+0] = zz; 400: img_animate.data[zz*3+1] = 0; 401: img_animate.data[zz*3+2] = zz; 402: } 403: 404: // Allocate Texture ID using GeoGL "smart" texture object 405: text_animate.create(); 406: 407: // Create a 1D texture 408: // - MediaDuke doesn't have a nice function to do this for me 409: 410: // Bind 1D texture 411: glBindTexture(GL_TEXTURE_2D, 0); 412: glBindTexture(GL_TEXTURE_1D, text_animate); 413: 414: // Use linear interpolation, mipmaps would be silly 415: glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,m_oEnvInfo.glWantLinear); 416: glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,m_oEnvInfo.glWantLinear); 417: 418: // Create the texture 419: glTexImage1D(GL_TEXTURE_1D,0,3,img_animate.x,0, 420: GL_RGB,GL_UNSIGNED_BYTE,img_animate.data); 421: 422: // Release the 1D texture binding 423: glBindTexture(GL_TEXTURE_1D, 0); 424:} 425: 426:////////////////////////////////////////////////////////////////////////////// 427:// 428:// Create circular light 429:// - Computes simple light into img_light image 430:// 431:////////////////////////////////////////////////////////////////////////////// 432:void CMotherboard::initLight() 433:{ 434: // Create a circular light 435: img_light.create(LIGHT_DIM,LIGHT_DIM,1); 436: for (int j=0; j<LIGHT_DIM; j++) 437: { 438: for (int i=0; i<LIGHT_DIM; i++) 439: { 440: float dist = (LIGHT_DIM/2-i)*(LIGHT_DIM/2-i) + (LIGHT_DIM/2-j)*(LIGHT_DIM/2-j); 441: if (fabsf(dist)>1) 442: dist = sqrtf(dist); 443: int c = (int)(LIGHT_SIZE*dist); //???WHG Random deviation + (rand()%7)-3; 444: if (c<0) c = 0; 445: if (c>255) c = 255; 446: img_light.data[(j<<LIGHT_PWR2)+i] = 255-c; 447: } 448: } 449:} 450: 451:////////////////////////////////////////////////////////////////////////////// 452:// 453:// Set light attenuation 454:// - Some sucky opengl drivers don't support this. Maybe we need an option 455:// to disable it. 456:// 457:////////////////////////////////////////////////////////////////////////////// 458:void CMotherboard::setAttenuation() 459:{ 460: // For those not versed in light attenuation: 461: // Attenuation causes light to affect distant objects less than near ones 462: // It can be constant, linear, or quadratic. 463: // Just a slight linear falloff allows a bit of realizm and cloaks 464: // far away details(and artifacts) until nearby 465: 466: // Maybe GeoGL's Light3D class should support this 467: glLightf(GL_LIGHT0+light0.nLightID,GL_LINEAR_ATTENUATION,0.05f); 468:} 469: 470:////////////////////////////////////////////////////////////////////////////// 471:// 472:// Apply opengl settings, fog, attenuation, light... 473:// - Use glEnable to setup things that other demo effects may have changed 474:// - Setup the lights and the ambient light 475:// 476:////////////////////////////////////////////////////////////////////////////// 477:void CMotherboard::initGLstuff() // All Setup For OpenGL Goes Here 478:{ 479:// OpenGL setup 480: glEnable(GL_DEPTH_TEST); // Enables Depth Testing 481: glEnable(GL_CULL_FACE); // Cull back faces 482: glDisable(GL_NORMALIZE); // GeoGL creates unit normals at load 483: glShadeModel(GL_SMOOTH); // Enable Smooth Shading 484: glDepthFunc(GL_LEQUAL); // Allows blends to be drawn over objects 485: glEnable(GL_LIGHTING); // Lighting is key... 486: 487: setAttenuation(); // Set light attenuation 488: 489:// Light setup 490: 491: // Disable any lights left around by other effects 492: for (int i=0; i<1; i++) 493: glDisable(GL_LIGHT0+i); 494: 495: // No scene ambient light - the individual lights handle this 496: Light3D::setSceneAmbient(fRGBA(0,0,0,0)); 497: 498: // Light at viewer is on at full white 499: light0.setLight(1.0f,1.0f,1.0f,1); 500: light0.position(0.0f,0.0f,0.0f); 501: light0.on(); 502: 503: // Light at CPU socket comes later 504: lightSocket.off(); 505:} 506: 507:////////////////////////////////////////////////////////////////////////////// 508:// 509:// Initialize openGL objects 510:// - Load objects with GeoGL object loader 511:// - Customize texture, light, position, transparency 512:// 513:////////////////////////////////////////////////////////////////////////////// 514:void CMotherboard::initObjects() 515:{ 516: // Load fly through path 517: flight.Load("data.md/flythrough.dat"); 518: 519: // Load all textures before objects 520: loadGLTextures(); 521: 522: // ABOUT GEOGL OBJECT LOADING 523: // - Objects are loaded at the origin. The motherboard is on the XY plane, so 524: // other objects are placed above it (+z) at various positions 525: // - Objects may be tesselated so the triangle-mesh is more detailed. This can 526: // aid lighting effects (particularly specular light) but eats memory+T&L time 527: // - When objects are loaded, GeoGL will use the texture and light settings 528: // specified in the 3SO file. Some objects are "generic" (cube, plane) and 529: // need to have the texture, color, etc. set manually. Custom objects load 530: // exactly as needed (resistor, CPU chip) 531: 532: // COMPUTER CASE: load, scale, position 533: // - It is a 2-sided cube (2-sided else inside is culled) 534: // - Metal texture is specified in the 3SO file 535: computer = Load3SO("data.md/cube2s.3so",NULL,false); 536: computer.rescale(80,120,40); 537: computer.compile(); 538: 539: // MOTHERBOARD: load, tesselate, scale, position 540: // - Tesselated since lighting must be computed at more just the 4 corners! 541: // - Uses large, detailed 512x512 texture 542: motherboard = Load3SO("data.md/mb_map.3so",NULL,false); 543: motherboard = splitObj(motherboard,0.5f); 544: motherboard.rescale(70,80,1); 545: motherboard.position(0,-20,-37); 546: motherboard.compile(); 547: 548: // CPU SOCKET: load, scale, position 549: // - Uses simple texture showing holes in socket 550: socket = Load3SO("data.md/socket.3so",NULL,false); 551: socket.rescale(SOCKET_XSIZE,SOCKET_YSIZE,0.8); 552: socket.position = motherboard.position + fVector3D(0,49,0.8); 553: socket.compile(); 554: 555: // SOCKET HANDLE: load, scale, position, orient, 556: // - Reorient with the motherboard 557: socketHandle = Load3SO("data.md/handle.3so",NULL,false); 558: socketHandle.rescale(1,0.5f,36.5f); 559: socketHandle.position = motherboard.position + fVector3D(21.5f,33.5f,0); 560: socketHandle.direction(0,-90,0); 561: socketHandle.compile(); 562: 563: // CPU CHIP: load, scale, position, set texture 564: // - Created from a generic cube so the texture must be set 565: // - Size is slightly smaller than the socket 566: CPUchip = Load3SO("data.md/cube.3so",NULL,false); 567: CPUchip.rescale(SOCKET_XSIZE - 0.2f,SOCKET_YSIZE - 0.2f,0.5); 568: CPUchip.position = socket.position + fVector3D(0,0,100); 569: FOROBJSET(CPUchip,chipobj) 570: chipobj.nTextureID = text_mindware; 571: ENDFOROBJSET 572: CPUchip.compile(); 573: 574: // COOLCHIP: load, tesselate, scale, position 575: // - Tesselated for nice specular highlight 576: // - Created from a generic cube so the texture must be set 577: // - Play with the default lighting too 578: // - This used to be a big green chip, now it shows the credits 579: coolchip = Load3SO("data.md/cube.3so",NULL,false); 580: coolchip = splitObj(coolchip,0.75f*fTesselationFactor); 581: coolchip.rescale(11,10,0.5); 582: coolchip.position = motherboard.position + fVector3D(7,13,0.6); 583: FOROBJSET(coolchip,chipobj) 584: chipobj.nTextureID = text_greenchip; 585: chipobj.color(0.6f,1.0f,0.6f); 586: chipobj.setLight(0.15f,1.0f,0,1.5f,10); 587: chipobj.bSpecularBlend = true; // Apply 2-pass specular blend 588: chipobj.bDrawSmooth = true; 589: ENDFOROBJSET 590: coolchip.compile(); 591: 592: // CAPACITOR TABLE 593: // - This is the coordinates of all the capacitors on the motherboard 594: fVector3D cap_pos[num_Cap] = { 595: fVector3D(-45,50,0), fVector3D(-45,44,0), fVector3D(-45,38,0), 596: fVector3D(-45,32,0), fVector3D(-45,26,0), 597: 598: fVector3D(-39,-6,0), fVector3D(-38.5,-12,0), 599: fVector3D(-35,-32,0), fVector3D(-6,-33,0), 600: fVector3D(-12,-44,0), fVector3D(7,-53,0), 601: fVector3D(30,-44,0), fVector3D(34,-13,0), 602: fVector3D(30,68,0), fVector3D(21,69,0), 603: fVector3D(16,68,0), fVector3D(3,68,0), 604: fVector3D(-1.5,68.5,0), fVector3D(-9,68.2,0) 605: }; 606: 607: // - This is the orientation of all the capacitors on the motherboard 608: fVector3D cap_dir[num_Cap] = { 609: fVector3D(0,270,10), fVector3D(4,320,6), fVector3D(-1,130,0), 610: fVector3D(11,200,7), fVector3D(0,110,0), 611: fVector3D(20,360,5), fVector3D(-19,210,0), 612: fVector3D(0,140,-8), fVector3D(7,90,-13), 613: fVector3D(-5,110,3), fVector3D(12,120,0), 614: fVector3D(15,60,-1), fVector3D(0,70,0), 615: fVector3D(-3,280,0), fVector3D(2,150,-7), 616: fVector3D(13,40,4), fVector3D(0,10,0), 617: fVector3D(-16,80,0), fVector3D(13,256,2) 618: }; 619: 620: // MAIN CAPACITOR: load, tesselate, scale, position, reorient 621: // - Tesselated for specular highlight 622: ObjectSet3D cap_main = Load3SO("data.md/cap.3so",NULL,false); 623: cap_main = splitObj(cap_main,0.75f*fTesselationFactor); 624: cap_main.rescale(2.0f,1.5f,2.0f); 625: cap_main.direction(90,0,0); 626: cap_main.position = motherboard.position + fVector3D(0,0,1.5f*1.5f); 627: cap_main.objects[0].bSpecularBlend = true; 628: 629: // Loop through capacitor table and create a capacitor for each position 630: // - Copies of the original capacitor object (share vertices) 631: // - Position & orientation from the above tables 632: // - Random colors, 50% are specular 633: for (int nCap=0; nCap<num_Cap; nCap++) { 634: capacitor[nCap] = cap_main; // Copy original 635: capacitor[nCap].position +=cap_pos[nCap]; // Add to position, direction 636: capacitor[nCap].direction+=cap_dir[nCap]; 637: 638: // Every other one 639: if (nCap % 2==0) 640: { 641: // Is given a random color change of about 50% 642: Object3D &obj = capacitor[nCap].objects[0]; 643: obj.diffuse.r = obj.diffuse.r*(frand01()/2 + 0.5f); 644: obj.diffuse.g = obj.diffuse.g*(frand01()/2 + 0.5f); 645: obj.diffuse.b = obj.diffuse.b*(frand01()/2 + 0.5f); 646: } 647: // And every other one is specular 648: cap_main.objects[0].bSpecularBlend = (nCap % 2==0); 649: capacitor[nCap].compile(); 650: } 651: 652: // RESISTOR TABLE 653: // - This is the coordinates of all the capacitors on the motherboard 654: fVector3D res_pos[num_Res] = { 655: fVector3D(-55,68,0), fVector3D(-55,65,0), 656: fVector3D(-55,62,0), fVector3D(-55,59,0), 657: }; 658: 659: // - This is the orientation of all the capacitors on the motherboard 660: fVector3D res_dir[num_Res] = { 661: fVector3D(0,0,90), fVector3D(0,0,90), 662: fVector3D(0,0,90), fVector3D(0,0,90), 663: }; 664: 665: // MAIN RESISTOR: load, scale, position 666: // - Tesselated for specular highlight 667: ObjectSet3D res_main = Load3SO("data.md/res.3so",NULL,false); 668: res_main.position = motherboard.position + fVector3D(0,0,1.0f); 669: res_main.compile(); 670: 671: // Loop through resistor table and create a resistor for each position 672: // - Copies of the original resistor object (share vertices) 673: // - Position & orientation from the above tables 674: for (int nRes=0; nRes<num_Res; nRes++) { 675: resistor[nRes] = res_main; 676: resistor[nRes].position +=res_pos[nRes]; 677: resistor[nRes].direction+=res_dir[nRes]; 678: } 679: 680: // MAIN PCI SLOT: load, tesselate, scale, position 681: // - Created from a generic cube so the texture must be set 682: PCI[0] = Load3SO("data.md/slot.3so",NULL,false); 683: PCI[0] = splitObj(PCI[0],1*fTesselationFactor); 684: PCI[0].rescale(28,2,2); 685: PCI[0].position = motherboard.position + fVector3D(-13,-27,1); 686: PCI[0].compile(); 687: 688: // Loop creating PCI slots, next to each other 689: // - Each idential 690: for (int nPCI=1; nPCI<num_PCI; nPCI++) { 691: PCI[nPCI] = PCI[0]; 692: PCI[nPCI].position+=fVector3D(0,-11*nPCI,0); 693: } 694: 695: // AGP SLOT: load, tesselate, scale, position 696: // - Uses PCI slot object, but is a lighter color 697: AGP = Load3SO("data.md/slot.3so",NULL,false); 698: AGP = splitObj(AGP,1*fTesselationFactor); 699: AGP.rescale(24,2,2); 700: AGP.position= PCI[0].position + fVector3D(13,12,0); 701: FOROBJSET(AGP,obj) 702: obj.color(1,0.85f,0.48f); 703: obj.setLight(0.1,0.4,0,0,0); 704: ENDFOROBJSET 705: AGP.compile(); 706: 707: // ISA SLOT : load, tesselate, scale, position 708: // - Uses PCI slot object, but is a darker color 709: ISA = Load3SO("data.md/slot.3so",NULL,false); 710: ISA = splitObj(ISA,1*fTesselationFactor); 711: ISA.rescale(45,2,2); 712: ISA.position= PCI[num_PCI-1].position + fVector3D(7,-6,0); 713: FOROBJSET(ISA,obj) 714: obj.diffuse = PCI[0].objects[0].diffuse / 4; 715: ENDFOROBJSET 716: ISA.compile(); 717: 718: // MAIN DIMM SLOT: load, tesselate, scale, position 719: // - Uses PCI slot object, but is darker, thinner, shorter 720: ObjectSet3D DIMM0 = Load3SO("data.md/slot.3so",NULL,false); 721: DIMM0 = splitObj(DIMM0,1*fTesselationFactor); 722: DIMM0.rescale(17,1,1); 723: DIMM0.direction = fVector3D(0,0,90); 724: DIMM0.position = motherboard.position+fVector3D(47,54,0.5f); 725: FOROBJSET(DIMM0,obj) 726: obj.diffuse = PCI[0].objects[0].diffuse / 4; 727: ENDFOROBJSET 728: DIMM0.compile(); 729: 730: // DIMM SLOTS: create 3 dimm slots (each pair forms one memory slot) 731: DIMM[0] = DIMM0; DIMM[0].position += fVector3D( 0, 0,0); 732: DIMM[1] = DIMM0; DIMM[1].position += fVector3D( 0,-34,0); 733: DIMM[2] = DIMM0; DIMM[2].position += fVector3D(-3, 0,0); 734: DIMM[3] = DIMM0; DIMM[3].position += fVector3D(-3,-34,0); 735: DIMM[4] = DIMM0; DIMM[4].position += fVector3D(-6, 0,0); 736: DIMM[5] = DIMM0; DIMM[5].position += fVector3D(-6,-34,0); 737: 738: // RAM CHIP: load, tesselate, scale, position 739: // - Created from a generic cube so the texture must be set 740: RAM = Load3SO("data.md/cube.3so",NULL,false); 741: RAM.rescale(0.4f,33,7); 742: RAM.position = motherboard.position+fVector3D(47,37,3.5f); 743: FOROBJSET(RAM,obj) 744: obj.nTextureID = text_circuit; 745: ENDFOROBJSET 746: RAM.compile(); 747: 748: // SOME MICROCHIPS: load, scale, position, orientation 749: // - Created from a generic cube so the texture must be set 750: microchip[0] = Load3SO("data.md/chip.3so",NULL,false); 751: microchip[0].rescale(11,1,5); 752: microchip[0].direction = fVector3D(90,90,180); 753: microchip[0].position = motherboard.position + fVector3D(-47,-62,1); 754: microchip[0].compile(); 755: 756: microchip[1] = Load3SO("data.md/chip.3so",NULL,false); 757: microchip[1].objects[0].nTextureID = text_microchip2; 758: microchip[1].rescale(6,1,3.5f); 759: microchip[1].position = motherboard.position + fVector3D(-48,-44,1); 760: microchip[1].direction = fVector3D(90,0,180); 761: microchip[1].compile(); 762: 763: microchip[2] = Load3SO("data.md/chip.3so",NULL,false); 764: microchip[2].rescale(5,0.75f,2.5f); 765: microchip[2].position = motherboard.position + fVector3D(30,-5,0.75f); 766: microchip[2