3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
12 import "DisplaySystem"
15 import "BitmapResource"
17 import "LFBDisplayDriver"
19 // TOFIX: Temporary until we pass Display instead of DisplaySystem to FontExtent
20 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
21 import "GDIDisplayDriver"
24 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
34 public enum RenderState { fillMode = 1, depthTest, depthWrite, fogDensity, fogColor, blend, ambient, alphaWrite, antiAlias, vSync };
36 public enum FillModeValue { solid, wireframe };
38 public class DisplayFlags
40 public bool fullScreen:1, flipping:1, alpha:1, memBackBuffer:1, text:1, scrolling:1, printer:1;
42 public class FontFlags
44 public bool bold:1, italic:1, underline:1;
47 static void DummyFunction()
52 public class DisplayDriver
55 class_data char * name;
56 class_data bool textMode;
57 class_data bool printer;
58 class_data DisplaySystem displaySystem;
60 class_property DisplaySystem displaySystem
62 set { class_data(displaySystem) = value; }
63 get { return class_data(displaySystem); }
66 class_property char * name
68 set { class_data(name) = value; }
69 get { return class_data(name); }
72 class_property bool printer
74 set { class_data(printer) = value; }
75 get { return class_data(printer); }
78 // Constructor / Destructor
79 virtual bool ::CreateDisplaySystem(DisplaySystem);
80 virtual void ::DestroyDisplaySystem(DisplaySystem);
82 virtual bool ::CreateDisplay(Display);
83 virtual void ::DestroyDisplay(Display);
85 // Display Position and Size
86 virtual bool ::DisplaySize(Display, int, int);
87 virtual void ::DisplayPosition(Display, int, int);
90 virtual void ::SetPalette(Display, ColorAlpha *, bool);
91 virtual void ::RestorePalette(Display);
93 // Display the back buffer content
94 virtual void ::StartUpdate(Display);
95 virtual void ::Scroll(Display, Box, int, int, Extent);
96 virtual void ::Update(Display, Box);
97 virtual void ::EndUpdate(Display);
99 // Allocate/free a bitmap
100 virtual bool ::AllocateBitmap(DisplaySystem, Bitmap, int, int, int, PixelFormat, bool);
101 virtual void ::FreeBitmap(DisplaySystem, Bitmap);
104 virtual bool ::LockSystem(DisplaySystem displaySystem);
105 virtual void ::UnlockSystem(DisplaySystem displaySystem);
107 virtual bool ::Lock(Display);
108 virtual void ::Unlock(Display);
110 // Get/release a surface
111 virtual bool ::GetSurface(Display, Surface surface, int,int,Box);
112 virtual bool ::GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int,int,Box);
113 virtual void ::ReleaseSurface(Display this, Surface);
116 virtual void ::Clip(Display, Surface, Box);
118 // Grab from the screen
119 virtual bool ::GrabScreen(Display, Bitmap, int, int, unsigned int, unsigned int);
121 // Converts a bitmap format
122 virtual bool ::ConvertBitmap(DisplaySystem, Bitmap, PixelFormat, ColorAlpha *);
124 // Converts an LFB bitmap into an offscreen bitmap for this device
125 virtual bool ::MakeDDBitmap(DisplaySystem, Bitmap, bool);
128 virtual Font ::LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags);
129 virtual void ::UnloadFont(DisplaySystem, Font);
132 virtual void ::SetForeground(Display, Surface, ColorAlpha);
133 virtual void ::SetBackground(Display, Surface, ColorAlpha);
134 virtual void ::LineStipple(Display, Surface, uint);
135 virtual ColorAlpha ::GetPixel(Display, Surface, int, int);
136 virtual void ::PutPixel(Display, Surface, int, int);
137 virtual void ::DrawLine(Display, Surface, int, int, int, int);
138 virtual void ::Rectangle(Display, Surface,int,int,int,int);
139 virtual void ::Area(Display, Surface,int,int,int,int);
140 virtual void ::Clear(Display, Surface, ClearType);
141 virtual void ::Blit(Display, Surface, Bitmap, int, int, int, int, int, int);
142 virtual void ::Stretch(Display, Surface, Bitmap, int, int, int, int, int, int,int,int);
143 virtual void ::Filter(Display, Surface, Bitmap, int, int, int, int, int, int,int,int);
144 virtual void ::BlitDI(Display, Surface, Bitmap, int, int, int, int, int, int);
145 virtual void ::StretchDI(Display, Surface, Bitmap, int, int, int, int, int, int,int,int);
146 virtual void ::FilterDI(Display, Surface, Bitmap, int, int, int, int, int, int, int,int);
147 virtual void ::TextFont(Display, Surface, Font);
148 virtual void ::TextOpacity(Display, Surface, bool);
149 virtual void ::WriteText(Display, Surface, int, int, char *, int);
150 virtual void ::TextExtent(Display, Surface, char *, int, int *, int *);
151 virtual void ::FontExtent(DisplaySystem, Font, char *, int, int *, int *);
152 virtual void ::DrawingChar(Display, Surface, char);
153 virtual void ::NextPage(Display);
154 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
156 virtual void ::SetRenderState(Display, RenderState, uint);
157 virtual void ::SetLight(Display, int, Light);
158 virtual void ::SetCamera(Display, Surface, Camera);
159 virtual bool ::AllocateMesh(DisplaySystem, Mesh);
160 virtual void ::FreeMesh(DisplaySystem, Mesh);
161 virtual bool ::LockMesh(DisplaySystem, Mesh, MeshFeatures flags);
162 virtual void ::UnlockMesh(DisplaySystem, Mesh, MeshFeatures flags);
163 virtual void * ::AllocateIndices(DisplaySystem, int nIndices, bool indices32bit);
164 virtual void ::FreeIndices(DisplaySystem, void * indices);
165 virtual uint16 * ::LockIndices(DisplaySystem, void * indices);
166 virtual void ::UnlockIndices(DisplaySystem, void * indices, bool indices32bit, int nIndices);
167 virtual void ::SelectMesh(Display, Mesh);
168 virtual void ::ApplyMaterial(Display, Material, Mesh);
169 virtual void ::DrawPrimitives(Display, PrimitiveSingle *, Mesh mesh);
170 virtual void ::PushMatrix(Display);
171 virtual void ::PopMatrix(Display, bool);
172 virtual void ::SetTransform(Display, Matrix, bool, bool);
174 virtual void ::SetBlitTint(Display, Surface, ColorAlpha);
177 public enum Alignment { left, right, center };
178 public enum ClearType { colorBuffer, depthBuffer, colorAndDepth };
180 subclass(DisplayDriver) GetDisplayDriver(char * driverName)
185 for(link = class(DisplayDriver).derivatives.first; link; link = link.next)
187 subclass(DisplayDriver) displayDriver = link.data;
188 if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName))
189 return displayDriver;
195 DisplaySystem GetDisplaySystem(char * driverName)
197 subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName);
198 return displayDriver ? displayDriver.displaySystem : null;
201 define textCellW = 8;
202 define textCellH = 16;
204 public enum PixelFormat // : byte MESSES UP GuiApplication
206 pixelFormat4, pixelFormat8, pixelFormat444, pixelFormat555, pixelFormat565, pixelFormat888, pixelFormatAlpha, pixelFormatText, pixelFormatRGBA
208 public enum Resolution : int
210 resText80x25, res320x200, res320x240, res320x400, res360x480, res400x256, res400x300, res512x256, res512x384,
211 res640x200, res640x350, res640x400, res640x480, res720x348, res800x600, res856x480, res960x720, res1024x768,
212 res1152x864, res1280x1024, res1600x1200, res768x480
215 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
216 public class LightFlags
218 public bool off:1, spot:1, omni:1, attenuation:1;
228 Quaternion orientation;
241 define NumberOfLights = 8;
243 // Painter's algorithm
245 public class HitRecord : struct
248 HitRecord prev, next;
252 void * tags[1]; // More tags may follow
254 int Compare(HitRecord recordB, void * unused)
256 if(center.z > recordB.center.z)
258 else if(center.z < recordB.center.z)
260 else if(pos > recordB.pos)
262 else if(pos < recordB.pos)
269 #define EPSILON 0.00001
273 PrimitiveSingle * triangle;
280 int Compare(SortPrimitive primitive2)
283 if(ZOverlap(primitive2) && Sgn(plane.d) != Sgn(primitive2.plane.d))
284 value = plane.d - primitive2.plane.d;
286 value = middle.z - primitive2.middle.z;
290 else if(value<-EPSILON)
296 bool ZOverlap(SortPrimitive poly2)
298 if(min.z > poly2.max.z - EPSILON || poly2.min.z > max.z - EPSILON)
304 bool XYOverlap(SortPrimitive poly2)
306 if(min.x > poly2.max.x - EPSILON || poly2.min.x > max.x - EPSILON )
308 if(min.y > poly2.max.y - EPSILON || poly2.min.y > max.y - EPSILON )
313 bool SurfaceOutside(SortPrimitive poly2)
317 PrimitiveSingle * primitive = triangle;
318 Mesh mesh = object.mesh;
319 Matrix * matrix = &object.matrix;
321 float a = poly2.plane.a, b = poly2.plane.b, c = poly2.plane.c, d = poly2.plane.d;
327 d = - (a * poly2.middle.x + b * poly2.middle.y + c * poly2.middle.z);
330 for(v = 0; v < primitive->nIndices; v++)
333 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
336 vertex.MultMatrix(local, matrix);
338 surface = a * vertex.x + b * vertex.y + c * vertex.z + d;
340 if(surface < EPSILON)
353 int SurfaceInside(SortPrimitive poly2)
357 PrimitiveSingle * primitive = poly2.triangle;
358 Mesh mesh = poly2.object.mesh;
359 Matrix * matrix = &poly2.object.matrix;
361 float a = plane.a, b = plane.b, c = plane.c, d = plane.d;
367 d = - (a * middle.x + b * middle.y + c * middle.z);
370 for(v = 0; v < primitive->nIndices; v++)
373 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
376 vertex.Transform(local, matrix);
378 surface = a * vertex.x + b * vertex.y + c * vertex.z + d;
379 if(surface > -EPSILON)
392 bool ShouldBeSwapped(SortPrimitive poly2)
394 if (!XYOverlap(poly2)) return false;
395 if (SurfaceOutside(poly2)) return false;
396 if (SurfaceInside(poly2)) return false;
404 #define MAX_CLIP_POINTS 50
413 displaySystem.numDisplays--;
414 displaySystem.driver.DestroyDisplay(this);
416 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
421 bool Create(DisplaySystem displaySystem, void * window)
426 this.displaySystem = displaySystem;
427 this.window = window;
428 displaySystem.numDisplays++;
429 if(displaySystem.driver.CreateDisplay(this))
431 // if(!result) LogErrorCode(DisplayInitFailed, displaySystem.driver.name);
436 Surface GetSurface(int x, int y, Box clip)
438 Surface result = null;
442 Box box { -x, -y, -x + width - 1, -y + height - 1 };
445 surface.width = width - x;
446 surface.height = height - y;
447 surface.driver = displaySystem.driver;
448 surface.displaySystem = displaySystem;
449 surface.display = this;
451 if(displaySystem.driver.GetSurface(this, surface, x, y, box))
459 bool Resize(int width, int height)
461 return displaySystem.driver.DisplaySize(this, width, height);
464 void Position(int x, int y)
466 displaySystem.driver.DisplayPosition(this, x,y);
469 void StartUpdate(void)
471 displaySystem.driver.StartUpdate(this);
474 void Scroll(Box scroll, int x, int y, Extent dirty)
476 displaySystem.driver.Scroll(this, scroll, x, y, dirty);
479 void Update(Box updateBox)
481 displaySystem.driver.Update(this, updateBox);
486 displaySystem.driver.EndUpdate(this);
491 displaySystem.driver.NextPage(this);
494 bool Grab(Bitmap bitmap, int x, int y, int w, int h)
497 if(bitmap && w > 0 && h > 0 &&
498 displaySystem.driver.GrabScreen(this, bitmap, x, y, w, h))
505 void FontExtent(Font font, char * text, int len, int * width, int * height)
507 // Fix for OnLoadGraphics time alpha blended window text extent on GDI
508 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
509 if(this && alphaBlend && pixelFormat == pixelFormat888 &&
510 displaySystem.driver == class(GDIDisplayDriver))
512 Surface s = GetSurface(0,0,null);
516 s.TextExtent(text, len, width, height);
522 // TODO: Should really pass display here...
523 DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height);
526 void SetPalette(ColorAlpha * palette, bool colorMatch)
528 displaySystem.driver.SetPalette(this, palette, colorMatch);
531 void RestorePalette(void)
533 displaySystem.driver.RestorePalette(this);
536 bool Lock(bool render)
541 for(c = 0; c<current; c++)
543 Logf("Locking (%d)\n", current+1);
546 // TOCHECK: Why is displaySystem null with GISDesigner?
547 result = displaySystem && displaySystem.Lock();
553 result = displaySystem.driver.Lock(this);
569 for(c = 0; c<current; c++)
571 Logf("Unlocking (%d)\n", current);
574 if(!current && displaySystem)
575 displaySystem.driver.Unlock(this);
579 displaySystem.Unlock();
582 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
583 // *** 3D GRAPHICS ***
584 void SetCamera(Surface surface, Camera camera)
588 display3D = Display3D { };
590 if(!display3D.selection)
595 if(!display3D.selection)
596 displaySystem.driver.SelectMesh(this, null);
598 display3D.material = null;
599 display3D.mesh = null;
601 if(!display3D.selection)
603 displaySystem.driver.SetCamera(this, surface, camera);
606 this.display3D.camera = camera;
611 camera.Setup(width, height, null);
613 // Always calling Update() here had broken interpolation in OrbitWithMouse!
617 if(display3D.selection)
619 // Compute Picking Planes
621 Vector3D point { 0,0,0 };
623 Angle fovLeft, fovRight, fovTop, fovBottom;
626 double l = camera.origin.x - (display3D.pickX - display3D.pickWidth/2.0f);
627 double r = camera.origin.x - (display3D.pickX + display3D.pickWidth/2.0f);
628 double t = (display3D.pickY - display3D.pickHeight/2.0f) - camera.origin.y;
629 double b = (display3D.pickY + display3D.pickHeight/2.0f) - camera.origin.y;
631 fovLeft = atan(l / camera.focalX);
632 fovRight = atan(r / camera.focalX);
633 fovTop = atan(t / camera.focalY);
634 fovBottom = atan(b / camera.focalY);
637 quat.Yaw(fovLeft - Pi/2);
638 quat.ToDirection(normal);
639 display3D.viewPickingPlanes[left].FromPointNormal(normal, point);
642 quat.Yaw(fovRight + Pi/2);
643 quat.ToDirection(normal);
644 display3D.viewPickingPlanes[right].FromPointNormal(normal, point);
647 quat.Pitch(fovTop + Pi/2);
648 quat.ToDirection(normal);
649 display3D.viewPickingPlanes[top].FromPointNormal(normal, point);
652 quat.Pitch(fovBottom - Pi/2);
653 quat.ToDirection(normal);
654 display3D.viewPickingPlanes[bottom].FromPointNormal(normal, point);
657 normal.x = 0; normal.y = 0; normal.z = 1;
658 point.z = camera.zMin;
659 display3D.viewPickingPlanes[near].FromPointNormal(normal, point);
662 normal.x = 0; normal.y = 0; normal.z = -1;
663 point.z = camera.zMax;
664 display3D.viewPickingPlanes[far].FromPointNormal(normal, point);
666 for(c = 0; c<ClippingPlane::enumSize; c++)
667 display3D.worldPickingPlanes[c].MultMatrix(display3D.viewPickingPlanes[c], camera.inverseTranspose);
669 // Compute picking ray
672 display3D.rayView.p0 = { 0, 0, 0 };
673 p.x = display3D.pickX;
674 p.y = display3D.pickY;
676 camera.Unproject(p, display3D.rayView.delta);
678 // Convert ray to world space
679 camera.Untransform(display3D.rayView.p0, display3D.rayWorld.p0);
680 camera.Untransform(display3D.rayView.delta, p);
681 display3D.rayWorld.delta.Subtract(p, display3D.rayWorld.p0);
688 void SetLight(int id, Light light)
690 displaySystem.driver.SetLight(this, id, light);
693 void SetLights(Object object)
696 display3D._SetLights(this, object, 0);
699 // --- Transformations ---
701 void SetTransform(Matrix matrix, bool viewSpace)
703 if(display3D.selection)
707 transpose.Transpose(matrix);
711 for(c = 0; c<ClippingPlane::enumSize; c++)
712 display3D.localPickingPlanes[c].MultMatrix(display3D.viewPickingPlanes[c], transpose);
716 for(c = 0; c<ClippingPlane::enumSize; c++)
717 display3D.localPickingPlanes[c].MultMatrix(display3D.worldPickingPlanes[c], transpose);
721 if(display3D.intersecting)
725 p2.Add(display3D.rayView.p0, display3D.rayView.delta);
727 p2.Add(display3D.rayWorld.p0, display3D.rayWorld.delta);
729 display3D.rayLocal.p0.DivideMatrix(display3D.rayWorld.p0, matrix);
730 tp2.DivideMatrix(p2, matrix);
731 display3D.rayLocal.delta.Subtract(tp2, display3D.rayLocal.p0);
735 displaySystem.driver.SetTransform(this, matrix, viewSpace, viewSpace ? false : true);
738 void PushMatrix(void)
740 displaySystem.driver.PushMatrix(this);
745 displaySystem.driver.PopMatrix(this, true);
749 void ApplyMaterial(Material material, Mesh mesh)
751 if(material != display3D.material)
753 display3D.material = material;
754 displaySystem.driver.ApplyMaterial(this, material, mesh);
758 void DrawPrimitives(PrimitiveSingle primitive, Mesh mesh)
760 displaySystem.driver.DrawPrimitives(this, primitive, mesh);
763 void SelectMesh(Mesh mesh)
765 displaySystem.driver.SelectMesh(this, mesh);
766 display3D.mesh = mesh;
769 bool DrawMesh(Object object)
772 if(display3D.selection)
773 result = display3D.PickMesh(object, null);
776 Mesh mesh = object.mesh;
777 Material objectMaterial = object.material;
779 if(mesh.groups.first)
781 PrimitiveGroup group;
782 displaySystem.driver.SelectMesh(this, mesh);
783 display3D.mesh = mesh;
785 for(group = mesh.groups.first; group; group = group.next)
787 Material material = group.material ? group.material : objectMaterial;
788 if(!material) material = defaultMaterial;
790 if(material != display3D.material)
792 display3D.material = material;
793 displaySystem.driver.ApplyMaterial(this, material, mesh);
796 // *** Render Vertex Arrays ***
797 displaySystem.driver.DrawPrimitives(this, (PrimitiveSingle *)&group.type, mesh);
801 if(object.flags.translucent)
804 Matrix inverse, inverseTranspose;
807 if(object.flags.viewSpace)
808 matrix = object.matrix;
811 Camera camera = display3D.camera;
812 Matrix temp = object.matrix;
813 temp.m[3][0] -= camera.cPosition.x;
814 temp.m[3][1] -= camera.cPosition.y;
815 temp.m[3][2] -= camera.cPosition.z;
816 matrix.Multiply(temp, camera.viewMatrix);
819 inverse.Inverse(matrix);
820 inverseTranspose.Transpose(inverse);
822 for(c = 0; c < mesh.nPrimitives; c++)
824 PrimitiveSingle * triangle = &mesh.primitives[c];
825 SortPrimitive * sort;
826 Plane * plane = &triangle->plane;
827 if(display3D.nTriangles >= display3D.maxTriangles)
829 display3D.maxTriangles = display3D.maxTriangles ? (display3D.maxTriangles * 3 / 2) : 32768;
830 display3D.triangles = renew display3D.triangles SortPrimitive[display3D.maxTriangles];
832 sort = &display3D.triangles[display3D.nTriangles++];
833 sort->object = object;
834 sort->triangle = triangle;
835 sort->middle.MultMatrix(triangle->middle, matrix);
836 sort->middle.z *= -1;
837 // sort->plane.MultMatrix(triangle->plane, inverseTranspose);
838 sort->plane.d = plane->a * inverseTranspose.m[0][3] +
839 plane->b * inverseTranspose.m[1][3] +
840 plane->c * inverseTranspose.m[2][3] +
841 plane->d * inverseTranspose.m[3][3];
847 displaySystem.driver.SelectMesh(this, mesh);
848 display3D.mesh = mesh;
850 for(c = 0; c<mesh.nPrimitives; c++)
852 PrimitiveSingle * primitive = &mesh.primitives[c];
854 Material material = primitive->material ? primitive->material : objectMaterial;
855 if(!material) material = defaultMaterial;
857 if(material != display3D.material)
859 display3D.material = material;
860 displaySystem.driver.ApplyMaterial(this, material, mesh);
863 displaySystem.driver.DrawPrimitives(this, primitive, display3D.mesh);
871 bool IsObjectVisible(Object object)
874 if(display3D.selection || !display3D.camera)
875 planes = object.flags.viewSpace ? display3D.viewPickingPlanes : display3D.worldPickingPlanes;
877 planes = object.flags.viewSpace ? display3D.camera.viewClippingPlanes : display3D.camera.worldClippingPlanes;
878 return object.InsideFrustum(planes) != outside;
881 bool DrawObject(Object object)
884 if(object && object.volume)
887 FrustumPlacement visible;
889 Camera camera = display3D.camera;
891 if(display3D.selection || !camera)
892 planes = object.flags.viewSpace ? display3D.viewPickingPlanes : display3D.worldPickingPlanes;
894 planes = object.flags.viewSpace ? camera.viewClippingPlanes : camera.worldClippingPlanes;
896 visible = object.InsideFrustum(planes);
898 if(visible || display3D.pickingPlanes)
900 if(display3D.collectingHits && object.tag)
902 /*if(object.flags.root)
903 this.tags[display3D.tagIndex] = object.tag;
905 this.tags[++display3D.tagIndex] = object.tag;
907 display3D.tags[display3D.tagIndex++] = object.tag;
910 if(object.flags.mesh && object.mesh)
912 if(!display3D.selection && displaySystem.driver.PushMatrix)
913 displaySystem.driver.PushMatrix(this);
915 SetTransform(object.matrix, object.flags.viewSpace);
916 if(display3D.selection)
918 if(visible == intersecting || display3D.intersecting)
920 Vector3D rayIntersect;
921 if(display3D.PickMesh(object, rayIntersect))
923 if(display3D.intersecting)
925 Vector3D wresult, vresult;
926 wresult.MultMatrix(rayIntersect, object.matrix);
927 if(!object.flags.viewSpace)
928 camera.TransformPoint(vresult, wresult);
932 if(vresult.z < display3D.rayIntersect.z)
933 display3D.rayIntersect = vresult;
934 display3D.intersected = true;
944 result |= DrawMesh(object);
945 if(displaySystem.driver.PopMatrix)
946 displaySystem.driver.PopMatrix(this, true);
948 if(display3D.collectingHits && result /*&& object.tag*/)
951 HitRecord hit = (HitRecord)new0 byte[sizeof(class HitRecord) + sizeof(void *) * (display3D.tagIndex/*+1*/)];
952 display3D.hitList.Add(hit);
953 hit.pos = display3D.hitList.count-1;
954 hit.numTags = display3D.tagIndex /*+ 1*/;
955 for(c = 0; c</*=*/display3D.tagIndex; c++)
957 hit.tags[c] = display3D.tags[c];
960 if(!object.flags.viewSpace)
961 camera.TransformPoint(hit.center, object.wcenter);
963 hit.center = object.wcenter;
967 for(child = object.children.first; child; child = child.next)
968 result |= DrawObject(child);
970 if(display3D.collectingHits && /*!object.flags.root && */object.tag)
971 display3D.tagIndex--;
977 void DrawTranslucency(void)
981 // *** Render translucent primitives ***
982 if(display3D.nTriangles)
984 Matrix * matrix = null;
989 display3D.SortTriangles();
993 displaySystem.driver.PushMatrix(this);
994 for(c=0; c<display3D.nTriangles; c++)
996 SortPrimitive * sort = &display3D.triangles[c];
997 Mesh mesh = sort->object.mesh;
998 PrimitiveSingle * primitive = sort->triangle;
1001 if(&sort->object.matrix != matrix)
1003 matrix = &sort->object.matrix;
1005 displaySystem.driver.PopMatrix(this, false);
1006 displaySystem.driver.PushMatrix(this);
1007 SetTransform(matrix, sort->object.flags.viewSpace);
1009 if(mesh != display3D.mesh)
1011 displaySystem.driver.SelectMesh(this, mesh);
1012 display3D.mesh = mesh;
1015 material = primitive->material ? primitive->material : sort->object.material;
1016 if(!material) material = defaultMaterial;
1018 if(material != display3D.material)
1020 displaySystem.driver.ApplyMaterial(this, material, display3D.mesh);
1021 display3D.material = material;
1026 Material testMaterial { };
1029 amount = (display3D.triangles[0].middle.z - display3D.triangles[c].middle.z) /
1030 (display3D.triangles[0].middle.z - display3D.triangles[display3D.nTriangles-1].middle.z);
1032 testMaterial.flags.doubleSided = { doubleSided = true, translucent = true };
1033 testMaterial.diffuse.a = 1;
1034 testMaterial.emissive.r = testMaterial.emissive.g = testMaterial.emissive.b = amount;
1035 testMaterial.baseMap = material->baseMap;
1037 displaySystem.driver.ApplyMaterial(this, testMaterial, display3D.mesh);
1041 // *** Render primitive ***
1042 // if(sort->plane.d > 0)
1043 displaySystem.driver.DrawPrimitives(this, primitive, display3D.mesh);
1045 displaySystem.driver.PopMatrix(this, true);
1047 display3D.nTriangles = 0;
1054 void StartSelection(int pickX, int pickY, int pickW, int pickH)
1058 display3D = Display3D { };
1060 display3D.pickX = (float)pickX;
1061 display3D.pickY = (float)pickY;
1062 display3D.pickWidth = (float)pickW;
1063 display3D.pickHeight = (float)pickH;
1064 display3D.selection = true;
1067 void CollectHits(void)
1069 display3D.collectingHits = true;
1072 int GetHits(OldList list)
1074 display3D.collectingHits = false;
1075 display3D.hitList.Sort(HitRecord::Compare, null);
1076 list = display3D.hitList;
1077 display3D.hitList.Clear();
1081 void IntersectPolygons(void)
1083 display3D.rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1084 display3D.intersected = false;
1085 display3D.intersecting = true;
1088 bool GetIntersect(Vector3D intersect)
1090 intersect = display3D.rayIntersect;
1091 display3D.intersecting = false;
1092 return display3D.intersected;
1095 void StopSelection(void)
1097 display3D.selection = false;
1100 // --- Rendering States ---
1101 property FillModeValue fillMode { set { displaySystem.driver.SetRenderState(this, fillMode, value); } };
1102 property bool depthTest { set { displaySystem.driver.SetRenderState(this, depthTest, value); } };
1103 property bool depthWrite { set { displaySystem.driver.SetRenderState(this, depthWrite, value); } };
1104 property float fogDensity { set { displaySystem.driver.SetRenderState(this, fogDensity, *(uint *)(void *)&value); } };
1105 property Color fogColor { set { displaySystem.driver.SetRenderState(this, fogColor, value); } };
1106 property bool blend { set { displaySystem.driver.SetRenderState(this, blend, value); } };
1107 property Color ambient { set { displaySystem.driver.SetRenderState(this, ambient, value); } };
1108 property bool alphaWrite { set { displaySystem.driver.SetRenderState(this, alphaWrite, value); } };
1109 property bool antiAlias { set { displaySystem.driver.SetRenderState(this, antiAlias, value); } };
1110 property bool vSync { set { displaySystem.driver.SetRenderState(this, vSync, value); } };
1112 property bool pickingPlanes { set { display3D.pickingPlanes = value; } };
1114 property DisplayFlags flags { get { return displaySystem.flags; } }
1115 property PixelFormat pixelFormat { get { return /*alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat; } }
1116 property bool alphaBlend { set { alphaBlend = value; } get { return alphaBlend; } };
1117 property bool useSharedMemory { set { useSharedMemory = value; } get { return useSharedMemory; } };
1118 property void * systemWindow { get { return window; } };
1119 property DisplaySystem displaySystem { get { return displaySystem; } };
1126 DisplaySystem displaySystem;
1132 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1133 Display3D display3D;
1136 void * windowDriverData;
1137 bool useSharedMemory;
1140 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1141 private class Display3D
1145 SortPrimitive * triangles;
1147 Vector3D points[MAX_CLIP_POINTS];
1148 Vector3D newPoints[MAX_CLIP_POINTS];
1149 byte goodPoints[MAX_CLIP_POINTS];
1154 Plane viewPickingPlanes[ClippingPlane], worldPickingPlanes[ClippingPlane];
1155 Plane localPickingPlanes[ClippingPlane];
1157 bool collectingHits, selection, intersecting, intersected, pickingPlanes;
1158 float pickX, pickY, pickWidth, pickHeight;
1163 Line rayView, rayWorld, rayLocal;
1164 Vector3D rayIntersect;
1171 int _SetLights(Display display, Object object, int id)
1173 if(id < NumberOfLights)
1177 if(object.flags.light && !object.light.flags.off)
1178 display.SetLight(id++, object.light);
1180 for(child = object.children.first; child; child = child.next)
1182 id = _SetLights(display, child, id);
1188 //#define TRESHOLD -1
1189 //#define TRESHOLD -0.25
1190 #define TRESHOLD -0.0025
1192 bool PickPrimitives(Mesh mesh, PrimitiveSingle primitive, Vector3D rayDiff, Vector3D rayIntersect)
1194 Plane * planes = localPickingPlanes;
1196 int nIndex = 1, nPoints = 1;
1198 bool result = false;
1199 Vector3D * points = this.points;
1200 Vector3D * newPoints = this.newPoints;
1201 byte * goodPoints = this.goodPoints;
1202 int nVertices = primitive.type.vertexRange ? primitive.nVertices : primitive.nIndices;
1205 bool i32bit = primitive.type.indices32bit;
1206 uint32 * indices32 = primitive.indices;
1207 uint16 * indices16 = primitive.indices;
1209 switch(primitive.type.primitiveType)
1211 case triangles: nIndex = 3; nPoints = 3; break;
1212 case quads: nIndex = 4; nPoints = 4; break;
1215 nIndex = 1; nPoints = 3;
1217 tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first] : mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
1218 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1219 tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first+1] : mesh.vertices[(i32bit ? indices32[1] : indices16[1])];
1220 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1224 for(c = offset; c<nVertices; c += nIndex)
1226 bool outside = false;
1233 if(primitive.type.vertexRange)
1235 if(primitive.type.primitiveType == triStrip)
1237 tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 1) : (c - 2)];
1238 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1239 tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 2) : (c - 1)];
1240 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1242 else if(primitive.type.primitiveType == triFan)
1244 tmp = mesh.vertices[primitive.first + 0];
1245 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1246 tmp = mesh.vertices[primitive.first + c - 1];
1247 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1249 for(i = 0; i<nIndex; i++)
1251 tmp = mesh.vertices[primitive.first + c+i];
1252 points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1257 if(primitive.type.primitiveType == triStrip)
1259 i = (c & 1) ? (c - 1) : (c - 2);
1260 tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
1261 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1263 i = (c & 1) ? (c - 2) : (c - 1);
1264 tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
1265 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1267 else if(primitive.type.primitiveType == triFan)
1269 tmp = mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
1270 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1271 tmp = mesh.vertices[(i32bit ? indices32[c-1] : indices16[c-1])];
1272 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1274 for(i = 0; i<nIndex; i++)
1276 tmp = mesh.vertices[(i32bit ? indices32[c+i] : indices16[c+i])];
1277 points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1281 for(p = 0; p < 6; p++)
1283 Plane * plane = &planes[p];
1285 int numGoodPoints = 0;
1287 memset(goodPoints, 0, n);
1288 for(i = 0; i < n; i++)
1290 double dot = plane->normal.DotProduct(points[i]);
1291 double distance = dot + plane->d;
1292 if(distance > TRESHOLD)
1303 if(numGoodPoints < n)
1314 newPoints[newN++] = points[j];
1323 for(lastGood = n-1; !goodPoints[lastGood]; lastGood--);
1325 edge.p0 = points[lastGood];
1326 edge.delta.Subtract(points[j], edge.p0);
1327 plane->IntersectLine(edge, newPoints[newN++]);
1329 for(next = j+1; next != j; next++)
1331 if(next == n) next = 0;
1332 if(goodPoints[next])
1334 int prev = next - 1;
1335 if(prev < 0) prev = n-1;
1337 edge.p0 = points[prev];
1338 edge.delta.Subtract(points[next], edge.p0);
1339 plane->IntersectLine(edge, newPoints[newN++]);
1349 // Use the new points
1350 memcpy(points, newPoints, newN * sizeof(Vector3D));
1359 // TODO: Implement intersection with TriStrip, TriFan...
1362 // Intersect primitives
1364 Vector3D intersect, diff;
1365 int i0 = c, i1 = c+1, i2 = c+2;
1367 if(primitive.type.primitiveType == triStrip)
1369 i0 = (c & 1) ? (c - 1) : (c - 2);
1370 i1 = (c & 1) ? (c - 2) : (c - 1);
1373 else if(primitive.type.primitiveType == triFan)
1380 if(primitive.type.vertexRange)
1382 mesh.vertices[primitive.first + i0],
1383 mesh.vertices[primitive.first + i1],
1384 mesh.vertices[primitive.first + i2]);
1387 mesh.vertices[(i32bit ? indices32[i0] : indices16[i0])],
1388 mesh.vertices[(i32bit ? indices32[i1] : indices16[i1])],
1389 mesh.vertices[(i32bit ? indices32[i2] : indices16[i2])]);
1391 plane.IntersectLine(rayLocal, intersect);
1392 diff.Subtract(intersect, rayLocal.p0);
1393 diff.x /= rayLocal.delta.x;
1394 diff.y /= rayLocal.delta.y;
1395 diff.z /= rayLocal.delta.z;
1396 if(diff.x < rayDiff.x || diff.y < rayDiff.y || diff.z < rayDiff.z)
1399 rayIntersect = intersect;
1406 switch(primitive.type)
1409 points[strip] = points[2];
1413 points[1] = points[2];
1420 bool PickMesh(Object object, Vector3D rayIntersect)
1422 Mesh mesh = object.mesh;
1423 bool result = false;
1424 Vector3D rayDiff { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1425 if(rayIntersect != null)
1426 rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1428 if(mesh.groups.first)
1430 PrimitiveGroup group;
1432 for(group = mesh.groups.first; group; group = group.next)
1434 if(PickPrimitives(mesh, (PrimitiveSingle *)&group.type, rayDiff, rayIntersect))
1445 for(c = 0; c < mesh.nPrimitives; c++)
1447 if(PickPrimitives(mesh, mesh.primitives[c], rayDiff, rayIntersect))
1458 void SortTriangles(void)
1461 Object object = null;
1463 for(c=0; c<nTriangles; c++)
1465 SortPrimitive * sort = &triangles[c];
1466 Mesh mesh = sort->object.mesh;
1467 PrimitiveSingle * primitive = sort->triangle;
1468 Vector3Df min { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1469 Vector3Df max { -MAXFLOAT, -MAXFLOAT, -MAXFLOAT };
1471 if(object != sort->object)
1473 object = sort->object;
1474 if(object.flags.viewSpace)
1475 matrix = object.matrix;
1478 Camera camera = this.camera;
1479 Matrix temp = object.matrix;
1480 temp.m[3][0] -= camera.cPosition.x;
1481 temp.m[3][1] -= camera.cPosition.y;
1482 temp.m[3][2] -= camera.cPosition.z;
1483 matrix.Multiply(temp, camera.viewMatrix);
1487 for(v = 0; v<primitive->nIndices; v++)
1489 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1492 vertex.MultMatrix(local, &matrix);
1494 if(vertex.x > max.x) max.x = vertex.x;
1495 if(vertex.y > max.y) max.y = vertex.y;
1496 if(vertex.z > max.z) max.z = vertex.z;
1497 if(vertex.x < min.x) min.x = vertex.x;
1498 if(vertex.y < min.y) min.y = vertex.y;
1499 if(vertex.z < min.z) min.z = vertex.z;
1505 sort->marked = false;
1509 Logf("========= Before Sort ==========\n");
1510 for(c=0; c<nTriangles; c++)
1512 SortPrimitive * sort = &triangles[c];
1514 Mesh mesh = sort->mesh;
1515 PrimitiveSingle * primitive = sort->triangle;
1517 Logf("Triangle %d (%s):\n", c, primitive->material->name);
1519 for(v = 0; v<primitive->nIndices; v++)
1521 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1525 vertex.<MultMatrix(local, sort->matrix);
1527 Logf("Vertex %d:", v);
1529 // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
1530 Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
1534 Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
1535 Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
1539 // *** Sort translucent primitives ***
1540 qsort((void*) triangles, nTriangles, sizeof(SortPrimitive), SortPrimitive::Compare);
1542 Logf("\n\n========= After Sort ==========\n");
1543 for(c=0; c<nTriangles; c++)
1545 SortPrimitive * sort = &triangles[c];
1547 Mesh mesh = sort->mesh;
1548 PrimitiveSingle * primitive = sort->triangle;
1550 Logf("Triangle %d (%s):\n", c, primitive->material->name);
1552 for(v = 0; v<primitive->nIndices; v++)
1554 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1558 vertex.MultMatrix(local, sort->matrix);
1560 Logf("Vertex %d:", v);
1562 // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
1563 Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
1567 Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
1568 Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
1575 If all five tests fail for a particular Q,
1576 then P might obscure Q. Now Q must be tested.
1577 First, the algorithm checks if Q has been "marked."
1578 If Q is marked, then Q was "moved around" in the list
1579 during a previous iteration of the loop. The algorithm
1580 only allows a polygon to be moved once, to avoid the possibility
1581 of infinite loops. If Q is not marked, it is tested to see
1582 if it might obscure P. If Q cannot obscure P, then Q is possibly
1583 behind P and so it is good candidate to be drawn next.
1584 Therefore, the algorithm "abandons" the current P (that is, it
1585 stops testing Q's against the current P) and moves the current
1586 Q to the end of the list to become the next P.
1591 for(p = 0; p<nTriangles; p++)
1593 SortPrimitive * poly1 = &triangles[p];
1596 for(q = p+1; q<nTriangles; q++)
1600 SortPrimitive * poly2 = &triangles[q];
1601 if(poly1->ZOverlap(poly2) && !poly2->marked)
1603 if(poly1->ShouldBeSwapped(poly2))
1605 if(!poly2->ShouldBeSwapped(poly1))
1607 SortPrimitive temp = *poly2;
1608 memmove(triangles+1, triangles, sizeof(SortPrimitive)*q);
1609 triangles[0] = temp;
1610 triangles[0].marked = true;
1624 for(p = 0; p<nTriangles; p++)
1626 SortPrimitive * poly1 = &triangles[p];
1629 // for(q = p+1; q<nTriangles; q++)
1630 for(q = 0; q<nTriangles; q++)
1634 SortPrimitive * poly2 = &triangles[q];
1635 if(poly1->ZOverlap(poly2) && !poly2->marked)
1637 if(poly1->ShouldBeSwapped(poly2))
1639 if(!poly2->ShouldBeSwapped(poly1))
1641 SortPrimitive temp = *poly2;
1642 memmove(triangles+1, triangles, sizeof(SortPrimitive)*q);
1643 triangles[0] = temp;
1644 triangles[0].marked = true;
1657 for(p = nTriangles-1; p>=0; p--)
1659 SortPrimitive * poly1 = &triangles[p];
1662 for(q = nTriangles-1; q>=0; q--)
1666 SortPrimitive * poly2 = &triangles[q];
1667 if(poly1->ZOverlap(poly2) && !poly2->marked)
1669 if(poly1->ShouldBeSwapped(poly2))
1671 if(!poly2->ShouldBeSwapped(poly1))
1673 SortPrimitive temp = *poly2;
1674 memmove(triangles + q, triangles + q + 1, sizeof(SortPrimitive)*q);
1676 triangles[nTriangles-1] = temp;
1689 for(c=0; c<nTriangles; c++)
1692 SortPrimitive * poly1 = &triangles[c];
1694 // for(b=0; b<nTriangles; b++)
1695 //for(b=c+1; b<nTriangles; b++)
1697 if(b<this.nTriangles)
1699 SortPrimitive * poly2 = &this.triangles[b];
1701 if(poly1->ZOverlap(poly2) && poly1->ShouldBeSwapped(poly2))
1703 SortPrimitive temp = *poly1;
1715 bool IsDriverTextMode(char * driverName)
1717 subclass(DisplayDriver) driver = GetDisplayDriver(driverName);
1718 return driver ? driver.textMode : false;
1721 bool IsDriverPrinter(char * driverName)
1723 subclass(DisplayDriver) driver = GetDisplayDriver(driverName);
1724 return driver ? driver.printer : false;
1727 static ColorAlpha defaultPalette[256] =
1731 0xFF000000,0xFF000080,0xFF008000,0xFF008080,0xFF800000,0xFF800080,0xFF808000,0xFFC0C0C0,
1732 0xFF808080,0xFF0000FF,0xFF00FF00,0xFF00FFFF,0xFFFF0000,0xFFFF00FF,0xFFFFFF00,0xFFFFFFFF,
1734 0xFF000000,0xFF0000AA,0xFF00AA00,0xFF00AAAA,0xFFAA0000,0xFFAA00AA,0xFFAAAA00,0xFFABABAB,
1735 0xFF555555,0xFF5555FF,0xFF55FF55,0xFF55FFFF,0xFFFF5555,0xFFFF55FF,0xFFFFFF55,0xFFFFFFFF,
1737 // 6 x 6 x 6 Color Cube
1738 0xFF000000, 0xFF000033, 0xFF000066, 0xFF000099, 0xFF0000CC, 0xFF0000FF,
1739 0xFF003300, 0xFF003333, 0xFF003366, 0xFF003399, 0xFF0033CC, 0xFF0033FF,
1740 0xFF006600, 0xFF006633, 0xFF006666, 0xFF006699, 0xFF0066CC, 0xFF0066FF,
1741 0xFF009900, 0xFF009933, 0xFF009966, 0xFF009999, 0xFF0099CC, 0xFF0099FF,
1742 0xFF00CC00, 0xFF00CC33, 0xFF00CC66, 0xFF00CC99, 0xFF00CCCC, 0xFF00CCFF,
1743 0xFF00FF00, 0xFF00FF33, 0xFF00FF66, 0xFF00FF99, 0xFF00FFCC, 0xFF00FFFF,
1745 0xFF330000, 0xFF330033, 0xFF330066, 0xFF330099, 0xFF3300CC, 0xFF3300FF,
1746 0xFF333300, 0xFF333333, 0xFF333366, 0xFF333399, 0xFF3333CC, 0xFF3333FF,
1747 0xFF336600, 0xFF336633, 0xFF336666, 0xFF336699, 0xFF3366CC, 0xFF3366FF,
1748 0xFF339900, 0xFF339933, 0xFF339966, 0xFF339999, 0xFF3399CC, 0xFF3399FF,
1749 0xFF33CC00, 0xFF33CC33, 0xFF33CC66, 0xFF33CC99, 0xFF33CCCC, 0xFF33CCFF,
1750 0xFF33FF00, 0xFF33FF33, 0xFF33FF66, 0xFF33FF99, 0xFF33FFCC, 0xFF33FFFF,
1752 0xFF660000, 0xFF660033, 0xFF660066, 0xFF660099, 0xFF6600CC, 0xFF6600FF,
1753 0xFF663300, 0xFF663333, 0xFF663366, 0xFF663399, 0xFF6633CC, 0xFF6633FF,
1754 0xFF666600, 0xFF666633, 0xFF666666, 0xFF666699, 0xFF6666CC, 0xFF6666FF,
1755 0xFF669900, 0xFF669933, 0xFF669966, 0xFF669999, 0xFF6699CC, 0xFF6699FF,
1756 0xFF66CC00, 0xFF66CC33, 0xFF66CC66, 0xFF66CC99, 0xFF66CCCC, 0xFF66CCFF,
1757 0xFF66FF00, 0xFF66FF33, 0xFF66FF66, 0xFF66FF99, 0xFF66FFCC, 0xFF66FFFF,
1759 0xFF990000, 0xFF990033, 0xFF990066, 0xFF990099, 0xFF9900CC, 0xFF9900FF,
1760 0xFF993300, 0xFF993333, 0xFF993366, 0xFF993399, 0xFF9933CC, 0xFF9933FF,
1761 0xFF996600, 0xFF996633, 0xFF996666, 0xFF996699, 0xFF9966CC, 0xFF9966FF,
1762 0xFF999900, 0xFF999933, 0xFF999966, 0xFF999999, 0xFF9999CC, 0xFF9999FF,
1763 0xFF99CC00, 0xFF99CC33, 0xFF99CC66, 0xFF99CC99, 0xFF99CCCC, 0xFF99CCFF,
1764 0xFF99FF00, 0xFF99FF33, 0xFF99FF66, 0xFF99FF99, 0xFF99FFCC, 0xFF99FFFF,
1766 0xFFCC0000, 0xFFCC0033, 0xFFCC0066, 0xFFCC0099, 0xFFCC00CC, 0xFFCC00FF,
1767 0xFFCC3300, 0xFFCC3333, 0xFFCC3366, 0xFFCC3399, 0xFFCC33CC, 0xFFCC33FF,
1768 0xFFCC6600, 0xFFCC6633, 0xFFCC6666, 0xFFCC6699, 0xFFCC66CC, 0xFFCC66FF,
1769 0xFFCC9900, 0xFFCC9933, 0xFFCC9966, 0xFFCC9999, 0xFFCC99CC, 0xFFCC99FF,
1770 0xFFCCCC00, 0xFFCCCC33, 0xFFCCCC66, 0xFFCCCC99, 0xFFCCCCCC, 0xFFCCCCFF,
1771 0xFFCCFF00, 0xFFCCFF33, 0xFFCCFF66, 0xFFCCFF99, 0xFFCCFFCC, 0xFFCCFFFF,
1773 0xFFFF0000, 0xFFFF0033, 0xFFFF0066, 0xFFFF0099, 0xFFFF00CC, 0xFFFF00FF,
1774 0xFFFF3300, 0xFFFF3333, 0xFFFF3366, 0xFFFF3399, 0xFFFF33CC, 0xFFFF33FF,
1775 0xFFFF6600, 0xFFFF6633, 0xFFFF6666, 0xFFFF6699, 0xFFFF66CC, 0xFFFF66FF,
1776 0xFFFF9900, 0xFFFF9933, 0xFFFF9966, 0xFFFF9999, 0xFFFF99CC, 0xFFFF99FF,
1777 0xFFFFCC00, 0xFFFFCC33, 0xFFFFCC66, 0xFFFFCC99, 0xFFFFCCCC, 0xFFFFCCFF,
1778 0xFFFFFF00, 0xFFFFFF33, 0xFFFFFF66, 0xFFFFFF99, 0xFFFFFFCC, 0xFFFFFFFF,
1780 // 16 Shades of gray
1781 0xFF000000,0xFF101010,0xFF202020,0xFF303030,0xFF404040,0xFF505050,0xFF606060,0xFF707070,
1782 0xFF808080,0xFF909090,0xFFA0A0A0,0xFFB0B0B0,0xFFC0C0C0,0xFFD0D0D0,0xFFE0E0E0,0xFFF0F0F0,
1785 0xFF080808,0xFF101010,0xFF585858,0xFF606060,0xFFA8A8A8,0xFFB0B0B0,0xFFF8F8F8,0xFFFFFFFF
1789 0xFF080000,0xFF100000,0xFF180000,0xFF200000,0xFF280000,0xFF300000,0xFF380000,0xFF400000,
1790 0xFF480000,0xFF500000,0xFF580000,0xFF600000,0xFF680000,0xFF700000,0xFF780000,0xFF800000,
1791 0xFF880000,0xFF900000,0xFF980000,0xFFA00000,0xFFA80000,0xFFB00000,0xFFB80000,0xFFC00000,
1792 0xFFC80000,0xFFD00000,0xFFD80000,0xFFE00000,0xFFE80000,0xFFF00000,0xFFF80000,0xFFFF0000,
1794 0xFF000800,0xFF001000,0xFF001800,0xFF002000,0xFF002800,0xFF003000,0xFF003800,0xFF004000,
1795 0xFF004800,0xFF005000,0xFF005800,0xFF006000,0xFF006800,0xFF007000,0xFF007800,0xFF008000,
1796 0xFF008800,0xFF009000,0xFF009800,0xFF00A000,0xFF00A800,0xFF00B000,0xFF00B800,0xFF00C000,
1797 0xFF00C800,0xFF00D000,0xFF00D800,0xFF00E000,0xFF00E800,0xFF00F000,0xFF00F800,0xFF00FF00,
1799 0xFF000808,0xFF001010,0xFF001818,0xFF002020,0xFF002828,0xFF003030,0xFF003838,0xFF004040,
1800 0xFF004848,0xFF005050,0xFF005858,0xFF006060,0xFF006868,0xFF007070,0xFF007878,0xFF008080,
1801 0xFF008888,0xFF009090,0xFF009898,0xFF00A0A0,0xFF00A8A8,0xFF00B0B0,0xFF00B8B8,0xFF00C0C0,
1802 0xFF00C8C8,0xFF00D0D0,0xFF00D8D8,0xFF00E0E0,0xFF00E8E8,0xFF00F0F0,0xFF00F8F8,0xFF00FFFF,
1804 0xFF000008,0xFF000010,0xFF000018,0xFF000020,0xFF000028,0xFF000030,0xFF000038,0xFF000040,
1805 0xFF000048,0xFF000050,0xFF000058,0xFF000060,0xFF000068,0xFF000070,0xFF000078,0xFF000080,
1806 0xFF000088,0xFF000090,0xFF000098,0xFF0000A0,0xFF0000A8,0xFF0000B0,0xFF0000B8,0xFF0000C0,
1807 0xFF0000C8,0xFF0000D0,0xFF0000D8,0xFF0000E0,0xFF0000E8,0xFF0000F0,0xFF0000F8,0xFF0000FF,
1809 0xFF080008,0xFF100010,0xFF180018,0xFF200020,0xFF280028,0xFF300030,0xFF380038,0xFF400040,
1810 0xFF480048,0xFF500050,0xFF580058,0xFF600060,0xFF680068,0xFF700070,0xFF780078,0xFF800080,
1811 0xFF880088,0xFF900090,0xFF980098,0xFFA000A0,0xFFA800A8,0xFFB000B0,0xFFB800B8,0xFFC000C0,
1812 0xFFC800C8,0xFFD000D0,0xFFD800D8,0xFFE000E0,0xFFE800E8,0xFFF000F0,0xFFF800F8,0xFFFF00FF,
1814 0xFF080800,0xFF101000,0xFF181800,0xFF202000,0xFF282800,0xFF303000,0xFF383800,0xFF404000,
1815 0xFF484800,0xFF505000,0xFF585800,0xFF606000,0xFF686800,0xFF707000,0xFF787800,0xFF808000,
1816 0xFF888800,0xFF909000,0xFF989800,0xFFA0A000,0xFFA8A800,0xFFB0B000,0xFFB8B800,0xFFC0C000,
1817 0xFFC8C800,0xFFD0D000,0xFFD8D800,0xFFE0E000,0xFFE8E800,0xFFF0F000,0xFFF8F800,0xFFFFFF00,
1819 0xFF080808,0xFF101010,0xFF181818,0xFF202020,0xFF282828,0xFF303030,0xFF383838,0xFF404040,
1820 0xFF484848,0xFF505050,0xFF585858,0xFF606060,0xFF686868,0xFF707070,0xFF787878,0xFF808080,
1821 0xFF888888,0xFF909090,0xFF989898,0xFFA0A0A0,0xFFA8A8A8,0xFFB0B0B0,0xFFB8B8B8,0xFFC0C0C0,
1822 0xFFC8C8C8,0xFFD0D0D0,0xFFD8D8D8,0xFFE0E0E0,0xFFE8E8E8,0xFFF0F0F0,0xFFF8F8F8,0xFFFFFFFF
1826 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1827 static Material defaultMaterial
1830 diffuse = { 1.0f, 1.0f, 1.0f },
1831 ambient = { 1.0f, 1.0f, 1.0f },
1832 flags = { doubleSided = true, noFog = true };
1836 static byte colorDepthShifts[PixelFormat] = { 0,0,1,1,1,2,0,1,2 };
1837 static Size resolutions[Resolution] =
1840 {320,200},{320,240},{320,400},{360,480},
1841 {400,256},{400,300},{512,256},{512,384},
1842 {640,200},{640,350},{640,400},{640,480},
1843 {720,348},{800,600},{856,480},{960,720},
1844 {1024,768},{1152,864},{1280,1024},{1600,1200},
1847 static int colorDepths[PixelFormat] = {4,8,12,15,16,32,8,16,32};
1849 // --- Query utilities ---
1851 public int GetResolutionWidth(Resolution resolution)
1853 return resolutions[resolution].w;
1856 public int GetResolutionHeight(Resolution resolution)
1858 return resolutions[resolution].h;
1861 public int GetDepthBits(PixelFormat colorDepth)
1863 return colorDepths[colorDepth];
1866 public byte GetColorDepthShifts(PixelFormat format)
1868 return colorDepthShifts[format];
1871 public ColorAlpha * GetDefaultPalette()
1873 return (ColorAlpha *)defaultPalette;
1875 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1876 public Material GetDefaultMaterial()
1878 return defaultMaterial;
1881 public int BestColorMatch(ColorAlpha * palette, int start, int end, Color rgb)
1887 int bestscore = MAXINT,score;
1888 byte r = rgb.r, g = rgb.g, b = rgb.b;
1891 for(c = start; c <= end; c++)
1894 current = palette[c];
1895 if(rgb && !c) continue;
1899 score = Abs(dr) + Abs(dg) + Abs(db);
1900 if(score <= bestscore)