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; } };
1123 DisplaySystem displaySystem;
1125 public int width, height;
1130 public void * driverData;
1131 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1132 Display3D display3D;
1135 void * windowDriverData;
1136 bool useSharedMemory;
1139 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1140 private class Display3D
1144 SortPrimitive * triangles;
1146 Vector3D points[MAX_CLIP_POINTS];
1147 Vector3D newPoints[MAX_CLIP_POINTS];
1148 byte goodPoints[MAX_CLIP_POINTS];
1153 Plane viewPickingPlanes[ClippingPlane], worldPickingPlanes[ClippingPlane];
1154 Plane localPickingPlanes[ClippingPlane];
1156 bool collectingHits, selection, intersecting, intersected, pickingPlanes;
1157 float pickX, pickY, pickWidth, pickHeight;
1162 Line rayView, rayWorld, rayLocal;
1163 Vector3D rayIntersect;
1170 int _SetLights(Display display, Object object, int id)
1172 if(id < NumberOfLights)
1176 if(object.flags.light && !object.light.flags.off)
1177 display.SetLight(id++, object.light);
1179 for(child = object.children.first; child; child = child.next)
1181 id = _SetLights(display, child, id);
1187 //#define TRESHOLD -1
1188 //#define TRESHOLD -0.25
1189 #define TRESHOLD -0.0025
1191 bool PickPrimitives(Mesh mesh, PrimitiveSingle primitive, Vector3D rayDiff, Vector3D rayIntersect)
1193 Plane * planes = localPickingPlanes;
1195 int nIndex = 1, nPoints = 1;
1197 bool result = false;
1198 Vector3D * points = this.points;
1199 Vector3D * newPoints = this.newPoints;
1200 byte * goodPoints = this.goodPoints;
1201 int nVertices = primitive.type.vertexRange ? primitive.nVertices : primitive.nIndices;
1204 bool i32bit = primitive.type.indices32bit;
1205 uint32 * indices32 = primitive.indices;
1206 uint16 * indices16 = primitive.indices;
1208 switch(primitive.type.primitiveType)
1210 case triangles: nIndex = 3; nPoints = 3; break;
1211 case quads: nIndex = 4; nPoints = 4; break;
1214 nIndex = 1; nPoints = 3;
1216 tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first] : mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
1217 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1218 tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first+1] : mesh.vertices[(i32bit ? indices32[1] : indices16[1])];
1219 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1223 for(c = offset; c<nVertices; c += nIndex)
1225 bool outside = false;
1232 if(primitive.type.vertexRange)
1234 if(primitive.type.primitiveType == triStrip)
1236 tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 1) : (c - 2)];
1237 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1238 tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 2) : (c - 1)];
1239 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1241 else if(primitive.type.primitiveType == triFan)
1243 tmp = mesh.vertices[primitive.first + 0];
1244 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1245 tmp = mesh.vertices[primitive.first + c - 1];
1246 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1248 for(i = 0; i<nIndex; i++)
1250 tmp = mesh.vertices[primitive.first + c+i];
1251 points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1256 if(primitive.type.primitiveType == triStrip)
1258 i = (c & 1) ? (c - 1) : (c - 2);
1259 tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
1260 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1262 i = (c & 1) ? (c - 2) : (c - 1);
1263 tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
1264 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1266 else if(primitive.type.primitiveType == triFan)
1268 tmp = mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
1269 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1270 tmp = mesh.vertices[(i32bit ? indices32[c-1] : indices16[c-1])];
1271 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1273 for(i = 0; i<nIndex; i++)
1275 tmp = mesh.vertices[(i32bit ? indices32[c+i] : indices16[c+i])];
1276 points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1280 for(p = 0; p < 6; p++)
1282 Plane * plane = &planes[p];
1284 int numGoodPoints = 0;
1286 memset(goodPoints, 0, n);
1287 for(i = 0; i < n; i++)
1289 double dot = plane->normal.DotProduct(points[i]);
1290 double distance = dot + plane->d;
1291 if(distance > TRESHOLD)
1302 if(numGoodPoints < n)
1313 newPoints[newN++] = points[j];
1322 for(lastGood = n-1; !goodPoints[lastGood]; lastGood--);
1324 edge.p0 = points[lastGood];
1325 edge.delta.Subtract(points[j], edge.p0);
1326 plane->IntersectLine(edge, newPoints[newN++]);
1328 for(next = j+1; next != j; next++)
1330 if(next == n) next = 0;
1331 if(goodPoints[next])
1333 int prev = next - 1;
1334 if(prev < 0) prev = n-1;
1336 edge.p0 = points[prev];
1337 edge.delta.Subtract(points[next], edge.p0);
1338 plane->IntersectLine(edge, newPoints[newN++]);
1348 // Use the new points
1349 memcpy(points, newPoints, newN * sizeof(Vector3D));
1358 // TODO: Implement intersection with TriStrip, TriFan...
1361 // Intersect primitives
1363 Vector3D intersect, diff;
1364 int i0 = c, i1 = c+1, i2 = c+2;
1366 if(primitive.type.primitiveType == triStrip)
1368 i0 = (c & 1) ? (c - 1) : (c - 2);
1369 i1 = (c & 1) ? (c - 2) : (c - 1);
1372 else if(primitive.type.primitiveType == triFan)
1379 if(primitive.type.vertexRange)
1381 mesh.vertices[primitive.first + i0],
1382 mesh.vertices[primitive.first + i1],
1383 mesh.vertices[primitive.first + i2]);
1386 mesh.vertices[(i32bit ? indices32[i0] : indices16[i0])],
1387 mesh.vertices[(i32bit ? indices32[i1] : indices16[i1])],
1388 mesh.vertices[(i32bit ? indices32[i2] : indices16[i2])]);
1390 plane.IntersectLine(rayLocal, intersect);
1391 diff.Subtract(intersect, rayLocal.p0);
1392 diff.x /= rayLocal.delta.x;
1393 diff.y /= rayLocal.delta.y;
1394 diff.z /= rayLocal.delta.z;
1395 if(diff.x < rayDiff.x || diff.y < rayDiff.y || diff.z < rayDiff.z)
1398 rayIntersect = intersect;
1405 switch(primitive.type)
1408 points[strip] = points[2];
1412 points[1] = points[2];
1419 bool PickMesh(Object object, Vector3D rayIntersect)
1421 Mesh mesh = object.mesh;
1422 bool result = false;
1423 Vector3D rayDiff { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1424 if(rayIntersect != null)
1425 rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1427 if(mesh.groups.first)
1429 PrimitiveGroup group;
1431 for(group = mesh.groups.first; group; group = group.next)
1433 if(PickPrimitives(mesh, (PrimitiveSingle *)&group.type, rayDiff, rayIntersect))
1444 for(c = 0; c < mesh.nPrimitives; c++)
1446 if(PickPrimitives(mesh, mesh.primitives[c], rayDiff, rayIntersect))
1457 void SortTriangles(void)
1460 Object object = null;
1462 for(c=0; c<nTriangles; c++)
1464 SortPrimitive * sort = &triangles[c];
1465 Mesh mesh = sort->object.mesh;
1466 PrimitiveSingle * primitive = sort->triangle;
1467 Vector3Df min { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1468 Vector3Df max { -MAXFLOAT, -MAXFLOAT, -MAXFLOAT };
1470 if(object != sort->object)
1472 object = sort->object;
1473 if(object.flags.viewSpace)
1474 matrix = object.matrix;
1477 Camera camera = this.camera;
1478 Matrix temp = object.matrix;
1479 temp.m[3][0] -= camera.cPosition.x;
1480 temp.m[3][1] -= camera.cPosition.y;
1481 temp.m[3][2] -= camera.cPosition.z;
1482 matrix.Multiply(temp, camera.viewMatrix);
1486 for(v = 0; v<primitive->nIndices; v++)
1488 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1491 vertex.MultMatrix(local, &matrix);
1493 if(vertex.x > max.x) max.x = vertex.x;
1494 if(vertex.y > max.y) max.y = vertex.y;
1495 if(vertex.z > max.z) max.z = vertex.z;
1496 if(vertex.x < min.x) min.x = vertex.x;
1497 if(vertex.y < min.y) min.y = vertex.y;
1498 if(vertex.z < min.z) min.z = vertex.z;
1504 sort->marked = false;
1508 Logf("========= Before Sort ==========\n");
1509 for(c=0; c<nTriangles; c++)
1511 SortPrimitive * sort = &triangles[c];
1513 Mesh mesh = sort->mesh;
1514 PrimitiveSingle * primitive = sort->triangle;
1516 Logf("Triangle %d (%s):\n", c, primitive->material->name);
1518 for(v = 0; v<primitive->nIndices; v++)
1520 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1524 vertex.<MultMatrix(local, sort->matrix);
1526 Logf("Vertex %d:", v);
1528 // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
1529 Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
1533 Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
1534 Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
1538 // *** Sort translucent primitives ***
1539 qsort((void*) triangles, nTriangles, sizeof(SortPrimitive), SortPrimitive::Compare);
1541 Logf("\n\n========= After Sort ==========\n");
1542 for(c=0; c<nTriangles; c++)
1544 SortPrimitive * sort = &triangles[c];
1546 Mesh mesh = sort->mesh;
1547 PrimitiveSingle * primitive = sort->triangle;
1549 Logf("Triangle %d (%s):\n", c, primitive->material->name);
1551 for(v = 0; v<primitive->nIndices; v++)
1553 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1557 vertex.MultMatrix(local, sort->matrix);
1559 Logf("Vertex %d:", v);
1561 // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
1562 Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
1566 Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
1567 Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
1574 If all five tests fail for a particular Q,
1575 then P might obscure Q. Now Q must be tested.
1576 First, the algorithm checks if Q has been "marked."
1577 If Q is marked, then Q was "moved around" in the list
1578 during a previous iteration of the loop. The algorithm
1579 only allows a polygon to be moved once, to avoid the possibility
1580 of infinite loops. If Q is not marked, it is tested to see
1581 if it might obscure P. If Q cannot obscure P, then Q is possibly
1582 behind P and so it is good candidate to be drawn next.
1583 Therefore, the algorithm "abandons" the current P (that is, it
1584 stops testing Q's against the current P) and moves the current
1585 Q to the end of the list to become the next P.
1590 for(p = 0; p<nTriangles; p++)
1592 SortPrimitive * poly1 = &triangles[p];
1595 for(q = p+1; q<nTriangles; q++)
1599 SortPrimitive * poly2 = &triangles[q];
1600 if(poly1->ZOverlap(poly2) && !poly2->marked)
1602 if(poly1->ShouldBeSwapped(poly2))
1604 if(!poly2->ShouldBeSwapped(poly1))
1606 SortPrimitive temp = *poly2;
1607 memmove(triangles+1, triangles, sizeof(SortPrimitive)*q);
1608 triangles[0] = temp;
1609 triangles[0].marked = true;
1623 for(p = 0; p<nTriangles; p++)
1625 SortPrimitive * poly1 = &triangles[p];
1628 // for(q = p+1; q<nTriangles; q++)
1629 for(q = 0; q<nTriangles; q++)
1633 SortPrimitive * poly2 = &triangles[q];
1634 if(poly1->ZOverlap(poly2) && !poly2->marked)
1636 if(poly1->ShouldBeSwapped(poly2))
1638 if(!poly2->ShouldBeSwapped(poly1))
1640 SortPrimitive temp = *poly2;
1641 memmove(triangles+1, triangles, sizeof(SortPrimitive)*q);
1642 triangles[0] = temp;
1643 triangles[0].marked = true;
1656 for(p = nTriangles-1; p>=0; p--)
1658 SortPrimitive * poly1 = &triangles[p];
1661 for(q = nTriangles-1; q>=0; q--)
1665 SortPrimitive * poly2 = &triangles[q];
1666 if(poly1->ZOverlap(poly2) && !poly2->marked)
1668 if(poly1->ShouldBeSwapped(poly2))
1670 if(!poly2->ShouldBeSwapped(poly1))
1672 SortPrimitive temp = *poly2;
1673 memmove(triangles + q, triangles + q + 1, sizeof(SortPrimitive)*q);
1675 triangles[nTriangles-1] = temp;
1688 for(c=0; c<nTriangles; c++)
1691 SortPrimitive * poly1 = &triangles[c];
1693 // for(b=0; b<nTriangles; b++)
1694 //for(b=c+1; b<nTriangles; b++)
1696 if(b<this.nTriangles)
1698 SortPrimitive * poly2 = &this.triangles[b];
1700 if(poly1->ZOverlap(poly2) && poly1->ShouldBeSwapped(poly2))
1702 SortPrimitive temp = *poly1;
1714 bool IsDriverTextMode(char * driverName)
1716 subclass(DisplayDriver) driver = GetDisplayDriver(driverName);
1717 return driver ? driver.textMode : false;
1720 bool IsDriverPrinter(char * driverName)
1722 subclass(DisplayDriver) driver = GetDisplayDriver(driverName);
1723 return driver ? driver.printer : false;
1726 static ColorAlpha defaultPalette[256] =
1730 0xFF000000,0xFF000080,0xFF008000,0xFF008080,0xFF800000,0xFF800080,0xFF808000,0xFFC0C0C0,
1731 0xFF808080,0xFF0000FF,0xFF00FF00,0xFF00FFFF,0xFFFF0000,0xFFFF00FF,0xFFFFFF00,0xFFFFFFFF,
1733 0xFF000000,0xFF0000AA,0xFF00AA00,0xFF00AAAA,0xFFAA0000,0xFFAA00AA,0xFFAAAA00,0xFFABABAB,
1734 0xFF555555,0xFF5555FF,0xFF55FF55,0xFF55FFFF,0xFFFF5555,0xFFFF55FF,0xFFFFFF55,0xFFFFFFFF,
1736 // 6 x 6 x 6 Color Cube
1737 0xFF000000, 0xFF000033, 0xFF000066, 0xFF000099, 0xFF0000CC, 0xFF0000FF,
1738 0xFF003300, 0xFF003333, 0xFF003366, 0xFF003399, 0xFF0033CC, 0xFF0033FF,
1739 0xFF006600, 0xFF006633, 0xFF006666, 0xFF006699, 0xFF0066CC, 0xFF0066FF,
1740 0xFF009900, 0xFF009933, 0xFF009966, 0xFF009999, 0xFF0099CC, 0xFF0099FF,
1741 0xFF00CC00, 0xFF00CC33, 0xFF00CC66, 0xFF00CC99, 0xFF00CCCC, 0xFF00CCFF,
1742 0xFF00FF00, 0xFF00FF33, 0xFF00FF66, 0xFF00FF99, 0xFF00FFCC, 0xFF00FFFF,
1744 0xFF330000, 0xFF330033, 0xFF330066, 0xFF330099, 0xFF3300CC, 0xFF3300FF,
1745 0xFF333300, 0xFF333333, 0xFF333366, 0xFF333399, 0xFF3333CC, 0xFF3333FF,
1746 0xFF336600, 0xFF336633, 0xFF336666, 0xFF336699, 0xFF3366CC, 0xFF3366FF,
1747 0xFF339900, 0xFF339933, 0xFF339966, 0xFF339999, 0xFF3399CC, 0xFF3399FF,
1748 0xFF33CC00, 0xFF33CC33, 0xFF33CC66, 0xFF33CC99, 0xFF33CCCC, 0xFF33CCFF,
1749 0xFF33FF00, 0xFF33FF33, 0xFF33FF66, 0xFF33FF99, 0xFF33FFCC, 0xFF33FFFF,
1751 0xFF660000, 0xFF660033, 0xFF660066, 0xFF660099, 0xFF6600CC, 0xFF6600FF,
1752 0xFF663300, 0xFF663333, 0xFF663366, 0xFF663399, 0xFF6633CC, 0xFF6633FF,
1753 0xFF666600, 0xFF666633, 0xFF666666, 0xFF666699, 0xFF6666CC, 0xFF6666FF,
1754 0xFF669900, 0xFF669933, 0xFF669966, 0xFF669999, 0xFF6699CC, 0xFF6699FF,
1755 0xFF66CC00, 0xFF66CC33, 0xFF66CC66, 0xFF66CC99, 0xFF66CCCC, 0xFF66CCFF,
1756 0xFF66FF00, 0xFF66FF33, 0xFF66FF66, 0xFF66FF99, 0xFF66FFCC, 0xFF66FFFF,
1758 0xFF990000, 0xFF990033, 0xFF990066, 0xFF990099, 0xFF9900CC, 0xFF9900FF,
1759 0xFF993300, 0xFF993333, 0xFF993366, 0xFF993399, 0xFF9933CC, 0xFF9933FF,
1760 0xFF996600, 0xFF996633, 0xFF996666, 0xFF996699, 0xFF9966CC, 0xFF9966FF,
1761 0xFF999900, 0xFF999933, 0xFF999966, 0xFF999999, 0xFF9999CC, 0xFF9999FF,
1762 0xFF99CC00, 0xFF99CC33, 0xFF99CC66, 0xFF99CC99, 0xFF99CCCC, 0xFF99CCFF,
1763 0xFF99FF00, 0xFF99FF33, 0xFF99FF66, 0xFF99FF99, 0xFF99FFCC, 0xFF99FFFF,
1765 0xFFCC0000, 0xFFCC0033, 0xFFCC0066, 0xFFCC0099, 0xFFCC00CC, 0xFFCC00FF,
1766 0xFFCC3300, 0xFFCC3333, 0xFFCC3366, 0xFFCC3399, 0xFFCC33CC, 0xFFCC33FF,
1767 0xFFCC6600, 0xFFCC6633, 0xFFCC6666, 0xFFCC6699, 0xFFCC66CC, 0xFFCC66FF,
1768 0xFFCC9900, 0xFFCC9933, 0xFFCC9966, 0xFFCC9999, 0xFFCC99CC, 0xFFCC99FF,
1769 0xFFCCCC00, 0xFFCCCC33, 0xFFCCCC66, 0xFFCCCC99, 0xFFCCCCCC, 0xFFCCCCFF,
1770 0xFFCCFF00, 0xFFCCFF33, 0xFFCCFF66, 0xFFCCFF99, 0xFFCCFFCC, 0xFFCCFFFF,
1772 0xFFFF0000, 0xFFFF0033, 0xFFFF0066, 0xFFFF0099, 0xFFFF00CC, 0xFFFF00FF,
1773 0xFFFF3300, 0xFFFF3333, 0xFFFF3366, 0xFFFF3399, 0xFFFF33CC, 0xFFFF33FF,
1774 0xFFFF6600, 0xFFFF6633, 0xFFFF6666, 0xFFFF6699, 0xFFFF66CC, 0xFFFF66FF,
1775 0xFFFF9900, 0xFFFF9933, 0xFFFF9966, 0xFFFF9999, 0xFFFF99CC, 0xFFFF99FF,
1776 0xFFFFCC00, 0xFFFFCC33, 0xFFFFCC66, 0xFFFFCC99, 0xFFFFCCCC, 0xFFFFCCFF,
1777 0xFFFFFF00, 0xFFFFFF33, 0xFFFFFF66, 0xFFFFFF99, 0xFFFFFFCC, 0xFFFFFFFF,
1779 // 16 Shades of gray
1780 0xFF000000,0xFF101010,0xFF202020,0xFF303030,0xFF404040,0xFF505050,0xFF606060,0xFF707070,
1781 0xFF808080,0xFF909090,0xFFA0A0A0,0xFFB0B0B0,0xFFC0C0C0,0xFFD0D0D0,0xFFE0E0E0,0xFFF0F0F0,
1784 0xFF080808,0xFF101010,0xFF585858,0xFF606060,0xFFA8A8A8,0xFFB0B0B0,0xFFF8F8F8,0xFFFFFFFF
1788 0xFF080000,0xFF100000,0xFF180000,0xFF200000,0xFF280000,0xFF300000,0xFF380000,0xFF400000,
1789 0xFF480000,0xFF500000,0xFF580000,0xFF600000,0xFF680000,0xFF700000,0xFF780000,0xFF800000,
1790 0xFF880000,0xFF900000,0xFF980000,0xFFA00000,0xFFA80000,0xFFB00000,0xFFB80000,0xFFC00000,
1791 0xFFC80000,0xFFD00000,0xFFD80000,0xFFE00000,0xFFE80000,0xFFF00000,0xFFF80000,0xFFFF0000,
1793 0xFF000800,0xFF001000,0xFF001800,0xFF002000,0xFF002800,0xFF003000,0xFF003800,0xFF004000,
1794 0xFF004800,0xFF005000,0xFF005800,0xFF006000,0xFF006800,0xFF007000,0xFF007800,0xFF008000,
1795 0xFF008800,0xFF009000,0xFF009800,0xFF00A000,0xFF00A800,0xFF00B000,0xFF00B800,0xFF00C000,
1796 0xFF00C800,0xFF00D000,0xFF00D800,0xFF00E000,0xFF00E800,0xFF00F000,0xFF00F800,0xFF00FF00,
1798 0xFF000808,0xFF001010,0xFF001818,0xFF002020,0xFF002828,0xFF003030,0xFF003838,0xFF004040,
1799 0xFF004848,0xFF005050,0xFF005858,0xFF006060,0xFF006868,0xFF007070,0xFF007878,0xFF008080,
1800 0xFF008888,0xFF009090,0xFF009898,0xFF00A0A0,0xFF00A8A8,0xFF00B0B0,0xFF00B8B8,0xFF00C0C0,
1801 0xFF00C8C8,0xFF00D0D0,0xFF00D8D8,0xFF00E0E0,0xFF00E8E8,0xFF00F0F0,0xFF00F8F8,0xFF00FFFF,
1803 0xFF000008,0xFF000010,0xFF000018,0xFF000020,0xFF000028,0xFF000030,0xFF000038,0xFF000040,
1804 0xFF000048,0xFF000050,0xFF000058,0xFF000060,0xFF000068,0xFF000070,0xFF000078,0xFF000080,
1805 0xFF000088,0xFF000090,0xFF000098,0xFF0000A0,0xFF0000A8,0xFF0000B0,0xFF0000B8,0xFF0000C0,
1806 0xFF0000C8,0xFF0000D0,0xFF0000D8,0xFF0000E0,0xFF0000E8,0xFF0000F0,0xFF0000F8,0xFF0000FF,
1808 0xFF080008,0xFF100010,0xFF180018,0xFF200020,0xFF280028,0xFF300030,0xFF380038,0xFF400040,
1809 0xFF480048,0xFF500050,0xFF580058,0xFF600060,0xFF680068,0xFF700070,0xFF780078,0xFF800080,
1810 0xFF880088,0xFF900090,0xFF980098,0xFFA000A0,0xFFA800A8,0xFFB000B0,0xFFB800B8,0xFFC000C0,
1811 0xFFC800C8,0xFFD000D0,0xFFD800D8,0xFFE000E0,0xFFE800E8,0xFFF000F0,0xFFF800F8,0xFFFF00FF,
1813 0xFF080800,0xFF101000,0xFF181800,0xFF202000,0xFF282800,0xFF303000,0xFF383800,0xFF404000,
1814 0xFF484800,0xFF505000,0xFF585800,0xFF606000,0xFF686800,0xFF707000,0xFF787800,0xFF808000,
1815 0xFF888800,0xFF909000,0xFF989800,0xFFA0A000,0xFFA8A800,0xFFB0B000,0xFFB8B800,0xFFC0C000,
1816 0xFFC8C800,0xFFD0D000,0xFFD8D800,0xFFE0E000,0xFFE8E800,0xFFF0F000,0xFFF8F800,0xFFFFFF00,
1818 0xFF080808,0xFF101010,0xFF181818,0xFF202020,0xFF282828,0xFF303030,0xFF383838,0xFF404040,
1819 0xFF484848,0xFF505050,0xFF585858,0xFF606060,0xFF686868,0xFF707070,0xFF787878,0xFF808080,
1820 0xFF888888,0xFF909090,0xFF989898,0xFFA0A0A0,0xFFA8A8A8,0xFFB0B0B0,0xFFB8B8B8,0xFFC0C0C0,
1821 0xFFC8C8C8,0xFFD0D0D0,0xFFD8D8D8,0xFFE0E0E0,0xFFE8E8E8,0xFFF0F0F0,0xFFF8F8F8,0xFFFFFFFF
1825 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1826 static Material defaultMaterial
1829 diffuse = { 1.0f, 1.0f, 1.0f },
1830 ambient = { 1.0f, 1.0f, 1.0f },
1831 flags = { doubleSided = true, noFog = true };
1835 static byte colorDepthShifts[PixelFormat] = { 0,0,1,1,1,2,0,1,2 };
1836 static Size resolutions[Resolution] =
1839 {320,200},{320,240},{320,400},{360,480},
1840 {400,256},{400,300},{512,256},{512,384},
1841 {640,200},{640,350},{640,400},{640,480},
1842 {720,348},{800,600},{856,480},{960,720},
1843 {1024,768},{1152,864},{1280,1024},{1600,1200},
1846 static int colorDepths[PixelFormat] = {4,8,12,15,16,32,8,16,32};
1848 // --- Query utilities ---
1850 public int GetResolutionWidth(Resolution resolution)
1852 return resolutions[resolution].w;
1855 public int GetResolutionHeight(Resolution resolution)
1857 return resolutions[resolution].h;
1860 public int GetDepthBits(PixelFormat colorDepth)
1862 return colorDepths[colorDepth];
1865 public byte GetColorDepthShifts(PixelFormat format)
1867 return colorDepthShifts[format];
1870 public ColorAlpha * GetDefaultPalette()
1872 return (ColorAlpha *)defaultPalette;
1874 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1875 public Material GetDefaultMaterial()
1877 return defaultMaterial;
1880 public int BestColorMatch(ColorAlpha * palette, int start, int end, Color rgb)
1886 int bestscore = MAXINT,score;
1887 byte r = rgb.r, g = rgb.g, b = rgb.b;
1890 for(c = start; c <= end; c++)
1893 current = palette[c];
1894 if(rgb && !c) continue;
1898 score = Abs(dr) + Abs(dg) + Abs(db);
1899 if(score <= bestscore)