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 union RenderStateFloat { float f; uint ui; };
38 public enum FillModeValue { solid, wireframe };
40 public class DisplayFlags
42 public bool fullScreen:1, flipping:1, alpha:1, memBackBuffer:1, text:1, scrolling:1, printer:1;
44 public class FontFlags
46 public bool bold:1, italic:1, underline:1;
49 __attribute__((unused)) static void DummyFunction()
51 #if !defined(__EMSCRIPTEN__)
56 public class DisplayDriver
59 class_data const char * name;
60 class_data bool textMode;
61 class_data bool printer;
62 class_data DisplaySystem displaySystem;
64 class_property DisplaySystem displaySystem
66 set { class_data(displaySystem) = value; }
67 get { return class_data(displaySystem); }
70 class_property const char * name
72 set { class_data(name) = value; }
73 get { return class_data(name); }
76 class_property bool printer
78 set { class_data(printer) = value; }
79 get { return class_data(printer); }
82 // Constructor / Destructor
83 virtual bool ::CreateDisplaySystem(DisplaySystem);
84 virtual void ::DestroyDisplaySystem(DisplaySystem);
86 virtual bool ::CreateDisplay(Display);
87 virtual void ::DestroyDisplay(Display);
89 // Display Position and Size
90 virtual bool ::DisplaySize(Display, int, int);
91 virtual void ::DisplayPosition(Display, int, int);
94 virtual void ::SetPalette(Display, ColorAlpha *, bool);
95 virtual void ::RestorePalette(Display);
97 // Display the back buffer content
98 virtual void ::StartUpdate(Display);
99 virtual void ::Scroll(Display, Box, int, int, Extent);
100 virtual void ::Update(Display, Box);
101 virtual void ::EndUpdate(Display);
103 // Allocate/free a bitmap
104 virtual bool ::AllocateBitmap(DisplaySystem, Bitmap, int, int, int, PixelFormat, bool);
105 virtual void ::FreeBitmap(DisplaySystem, Bitmap);
108 virtual bool ::LockSystem(DisplaySystem displaySystem);
109 virtual void ::UnlockSystem(DisplaySystem displaySystem);
111 virtual bool ::Lock(Display);
112 virtual void ::Unlock(Display);
114 // Get/release a surface
115 virtual bool ::GetSurface(Display, Surface surface, int,int,Box);
116 virtual bool ::GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int,int,Box);
117 virtual void ::ReleaseSurface(Display this, Surface);
120 virtual void ::Clip(Display, Surface, Box);
122 // Grab from the screen
123 virtual bool ::GrabScreen(Display, Bitmap, int, int, unsigned int, unsigned int);
125 // Converts a bitmap format
126 virtual bool ::ConvertBitmap(DisplaySystem, Bitmap, PixelFormat, ColorAlpha *);
128 // Converts an LFB bitmap into an offscreen bitmap for this device
129 virtual bool ::MakeDDBitmap(DisplaySystem, Bitmap, bool);
132 virtual Font ::LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags);
133 virtual void ::UnloadFont(DisplaySystem, Font);
136 virtual void ::SetForeground(Display, Surface, ColorAlpha);
137 virtual void ::SetBackground(Display, Surface, ColorAlpha);
138 virtual void ::LineStipple(Display, Surface, uint);
139 virtual ColorAlpha ::GetPixel(Display, Surface, int, int);
140 virtual void ::PutPixel(Display, Surface, int, int);
141 virtual void ::DrawLine(Display, Surface, int, int, int, int);
142 virtual void ::Rectangle(Display, Surface,int,int,int,int);
143 virtual void ::Area(Display, Surface,int,int,int,int);
144 virtual void ::Clear(Display, Surface, ClearType);
145 virtual void ::Blit(Display, Surface, Bitmap, int, int, int, int, int, int);
146 virtual void ::Stretch(Display, Surface, Bitmap, int, int, int, int, int, int,int,int);
147 virtual void ::Filter(Display, Surface, Bitmap, int, int, int, int, int, int,int,int);
148 virtual void ::BlitDI(Display, Surface, Bitmap, int, int, int, int, int, int);
149 virtual void ::StretchDI(Display, Surface, Bitmap, int, int, int, int, int, int,int,int);
150 virtual void ::FilterDI(Display, Surface, Bitmap, int, int, int, int, int, int, int,int);
151 virtual void ::TextFont(Display, Surface, Font);
152 virtual void ::TextOpacity(Display, Surface, bool);
153 virtual void ::WriteText(Display, Surface, int, int, const char *, int);
154 virtual void ::TextExtent(Display, Surface, const char *, int, int *, int *);
155 virtual void ::FontExtent(DisplaySystem, Font, const char *, int, int *, int *);
156 virtual void ::DrawingChar(Display, Surface, char);
157 virtual void ::NextPage(Display);
158 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
160 virtual void ::SetRenderState(Display, RenderState, uint);
161 virtual void ::SetLight(Display, int, Light);
162 virtual void ::SetCamera(Display, Surface, Camera);
163 virtual bool ::AllocateMesh(DisplaySystem, Mesh, MeshFeatures, int nVertices);
164 virtual void ::FreeMesh(DisplaySystem, Mesh);
165 virtual bool ::LockMesh(DisplaySystem, Mesh, MeshFeatures flags);
166 virtual void ::UnlockMesh(DisplaySystem, Mesh, MeshFeatures flags);
167 virtual void * ::AllocateIndices(DisplaySystem, int nIndices, bool indices32bit);
168 virtual void ::FreeIndices(DisplaySystem, void * indices);
169 virtual uint16 * ::LockIndices(DisplaySystem, void * indices);
170 virtual void ::UnlockIndices(DisplaySystem, void * indices, bool indices32bit, int nIndices);
171 virtual void ::SelectMesh(Display, Mesh);
172 virtual void ::ApplyMaterial(Display, Material, Mesh);
173 virtual void ::DrawPrimitives(Display, PrimitiveSingle *, Mesh mesh);
174 virtual void ::PushMatrix(Display);
175 virtual void ::PopMatrix(Display, bool);
176 virtual void ::SetTransform(Display, Matrix, bool, bool);
178 virtual void ::SetBlitTint(Display, Surface, ColorAlpha);
181 public enum Alignment { left, right, center };
182 public enum ClearType { colorBuffer, depthBuffer, colorAndDepth };
184 define textCellW = 8;
185 define textCellH = 16;
187 public enum PixelFormat // : byte MESSES UP GuiApplication
189 pixelFormat4, pixelFormat8, pixelFormat444, pixelFormat555, pixelFormat565, pixelFormat888, pixelFormatAlpha, pixelFormatText, pixelFormatRGBA
191 public enum Resolution : int
193 resText80x25, res320x200, res320x240, res320x400, res360x480, res400x256, res400x300, res512x256, res512x384,
194 res640x200, res640x350, res640x400, res640x480, res720x348, res800x600, res856x480, res960x720, res1024x768,
195 res1152x864, res1280x1024, res1600x1200, res768x480
198 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
199 public class LightFlags
201 public bool off:1, spot:1, omni:1, attenuation:1;
211 Quaternion orientation;
224 define NumberOfLights = 8;
226 // Painter's algorithm
228 public class HitRecord : struct
231 HitRecord prev, next;
235 void * tags[1]; // More tags may follow
237 int Compare(HitRecord recordB, void * unused)
239 if(center.z > recordB.center.z)
241 else if(center.z < recordB.center.z)
243 else if(pos > recordB.pos)
245 else if(pos < recordB.pos)
252 #define EPSILON 0.00001
256 PrimitiveSingle * triangle;
263 int Compare(SortPrimitive primitive2)
266 if(ZOverlap(primitive2) && Sgn(plane.d) != Sgn(primitive2.plane.d))
267 value = plane.d - primitive2.plane.d;
269 value = middle.z - primitive2.middle.z;
273 else if(value<-EPSILON)
279 bool ZOverlap(SortPrimitive poly2)
281 if(min.z > poly2.max.z - EPSILON || poly2.min.z > max.z - EPSILON)
287 bool XYOverlap(SortPrimitive poly2)
289 if(min.x > poly2.max.x - EPSILON || poly2.min.x > max.x - EPSILON )
291 if(min.y > poly2.max.y - EPSILON || poly2.min.y > max.y - EPSILON )
296 bool SurfaceOutside(SortPrimitive poly2)
300 PrimitiveSingle * primitive = triangle;
301 Mesh mesh = object.mesh;
302 Matrix * matrix = &object.matrix;
304 double a = poly2.plane.a, b = poly2.plane.b, c = poly2.plane.c, d = poly2.plane.d;
310 d = - (a * poly2.middle.x + b * poly2.middle.y + c * poly2.middle.z);
313 for(v = 0; v < primitive->nIndices; v++)
316 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
319 vertex.MultMatrix(local, matrix);
321 surface = a * vertex.x + b * vertex.y + c * vertex.z + d;
323 if(surface < EPSILON)
336 bool SurfaceInside(SortPrimitive poly2)
340 PrimitiveSingle * primitive = poly2.triangle;
341 Mesh mesh = poly2.object.mesh;
342 Matrix * matrix = &poly2.object.matrix;
344 double a = plane.a, b = plane.b, c = plane.c, d = plane.d;
350 d = - (a * middle.x + b * middle.y + c * middle.z);
353 for(v = 0; v < primitive->nIndices; v++)
356 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
359 vertex.MultMatrix(local, matrix);
361 surface = a * vertex.x + b * vertex.y + c * vertex.z + d;
362 if(surface > -EPSILON)
375 bool ShouldBeSwapped(SortPrimitive poly2)
377 if (!XYOverlap(poly2)) return false;
378 if (SurfaceOutside(poly2)) return false;
379 if (SurfaceInside(poly2)) return false;
387 #define MAX_CLIP_POINTS 50
396 displaySystem.numDisplays--;
397 displaySystem.driver.DestroyDisplay(this);
399 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
404 bool Create(DisplaySystem displaySystem, void * window)
409 this.displaySystem = displaySystem;
410 this.window = window;
411 displaySystem.numDisplays++;
412 if(displaySystem.driver.CreateDisplay(this))
414 // if(!result) LogErrorCode(DisplayInitFailed, displaySystem.driver.name);
419 Surface GetSurface(int x, int y, Box clip)
421 Surface result = null;
425 Box box { -x, -y, -x + width - 1, -y + height - 1 };
428 surface.width = width - x;
429 surface.height = height - y;
430 surface.driver = displaySystem.driver;
431 surface.displaySystem = displaySystem;
432 surface.display = this;
434 if(displaySystem.driver.GetSurface(this, surface, x, y, box))
442 bool Resize(int width, int height)
444 return displaySystem.driver.DisplaySize(this, width, height);
447 void Position(int x, int y)
449 displaySystem.driver.DisplayPosition(this, x,y);
452 void StartUpdate(void)
454 displaySystem.driver.StartUpdate(this);
457 void Scroll(Box scroll, int x, int y, Extent dirty)
459 displaySystem.driver.Scroll(this, scroll, x, y, dirty);
462 void Update(Box updateBox)
464 displaySystem.driver.Update(this, updateBox);
469 displaySystem.driver.EndUpdate(this);
474 displaySystem.driver.NextPage(this);
477 bool Grab(Bitmap bitmap, int x, int y, int w, int h)
480 if(bitmap && w > 0 && h > 0 &&
481 displaySystem.driver.GrabScreen(this, bitmap, x, y, w, h))
488 void FontExtent(Font font, const char * text, int len, int * width, int * height)
490 // Fix for OnLoadGraphics time alpha blended window text extent on GDI
491 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
492 if(this && alphaBlend && pixelFormat == pixelFormat888 &&
493 displaySystem.driver == class(GDIDisplayDriver))
495 Surface s = GetSurface(0,0,null);
499 s.TextExtent(text, len, width, height);
505 // TODO: Should really pass display here...
506 DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height);
509 void SetPalette(ColorAlpha * palette, bool colorMatch)
511 displaySystem.driver.SetPalette(this, palette, colorMatch);
514 void RestorePalette(void)
516 displaySystem.driver.RestorePalette(this);
519 bool Lock(bool render)
524 for(c = 0; c<current; c++)
526 Logf("Locking (%d)\n", current+1);
529 // TOCHECK: Why is displaySystem null with GISDesigner?
530 result = displaySystem && displaySystem.Lock();
533 #if !defined(__EMSCRIPTEN__)
538 result = displaySystem.driver.Lock(this);
554 for(c = 0; c<current; c++)
556 Logf("Unlocking (%d)\n", current);
559 if(!current && displaySystem)
560 displaySystem.driver.Unlock(this);
561 #if !defined(__EMSCRIPTEN__)
566 displaySystem.Unlock();
569 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
570 // *** 3D GRAPHICS ***
571 void SetCamera(Surface surface, Camera camera)
575 display3D = Display3D { };
577 if(!display3D.selection)
582 if(!display3D.selection)
583 displaySystem.driver.SelectMesh(this, null);
585 display3D.material = null;
586 display3D.mesh = null;
588 if(!display3D.selection)
590 displaySystem.driver.SetCamera(this, surface, camera);
593 this.display3D.camera = camera;
598 camera.Setup(width, height, null);
600 // Always calling Update() here had broken interpolation in OrbitWithMouse!
604 if(display3D.selection)
606 // Compute Picking Planes
608 Vector3D point { 0,0,0 };
610 Angle fovLeft, fovRight, fovTop, fovBottom;
613 double l = camera.origin.x - (display3D.pickX - display3D.pickWidth/2.0f);
614 double r = camera.origin.x - (display3D.pickX + display3D.pickWidth/2.0f);
615 double t = (display3D.pickY - display3D.pickHeight/2.0f) - camera.origin.y;
616 double b = (display3D.pickY + display3D.pickHeight/2.0f) - camera.origin.y;
618 fovLeft = atan(l / camera.focalX);
619 fovRight = atan(r / camera.focalX);
620 fovTop = atan(t / camera.focalY);
621 fovBottom = atan(b / camera.focalY);
624 quat.Yaw(fovLeft - Pi/2);
625 quat.ToDirection(normal);
626 display3D.viewPickingPlanes[left].FromPointNormal(normal, point);
629 quat.Yaw(fovRight + Pi/2);
630 quat.ToDirection(normal);
631 display3D.viewPickingPlanes[right].FromPointNormal(normal, point);
634 quat.Pitch(fovTop + Pi/2);
635 quat.ToDirection(normal);
636 display3D.viewPickingPlanes[top].FromPointNormal(normal, point);
639 quat.Pitch(fovBottom - Pi/2);
640 quat.ToDirection(normal);
641 display3D.viewPickingPlanes[bottom].FromPointNormal(normal, point);
644 normal.x = 0; normal.y = 0; normal.z = 1;
645 point.z = camera.zMin;
646 display3D.viewPickingPlanes[near].FromPointNormal(normal, point);
649 normal.x = 0; normal.y = 0; normal.z = -1;
650 point.z = camera.zMax;
651 display3D.viewPickingPlanes[far].FromPointNormal(normal, point);
653 for(c = 0; c<ClippingPlane::enumSize; c++)
654 display3D.worldPickingPlanes[c].MultMatrix(display3D.viewPickingPlanes[c], camera.inverseTranspose);
656 // Compute picking ray
659 display3D.rayView.p0 = { 0, 0, 0 };
660 p.x = display3D.pickX;
661 p.y = display3D.pickY;
663 camera.Unproject(p, display3D.rayView.delta);
665 // Convert ray to world space
666 camera.Untransform(display3D.rayView.p0, display3D.rayWorld.p0);
667 camera.Untransform(display3D.rayView.delta, p);
668 display3D.rayWorld.delta.Subtract(p, display3D.rayWorld.p0);
675 void SetLight(int id, Light light)
677 displaySystem.driver.SetLight(this, id, light);
680 void SetLights(Object object)
683 display3D._SetLights(this, object, 0);
686 // --- Transformations ---
688 void SetTransform(Matrix matrix, bool viewSpace)
690 if(display3D.selection)
694 transpose.Transpose(matrix);
698 for(c = 0; c<ClippingPlane::enumSize; c++)
699 display3D.localPickingPlanes[c].MultMatrix(display3D.viewPickingPlanes[c], transpose);
703 for(c = 0; c<ClippingPlane::enumSize; c++)
704 display3D.localPickingPlanes[c].MultMatrix(display3D.worldPickingPlanes[c], transpose);
708 if(display3D.intersecting)
712 p2.Add(display3D.rayView.p0, display3D.rayView.delta);
714 p2.Add(display3D.rayWorld.p0, display3D.rayWorld.delta);
716 display3D.rayLocal.p0.DivideMatrix(display3D.rayWorld.p0, matrix);
717 tp2.DivideMatrix(p2, matrix);
718 display3D.rayLocal.delta.Subtract(tp2, display3D.rayLocal.p0);
722 displaySystem.driver.SetTransform(this, matrix, viewSpace, viewSpace ? false : true);
725 void PushMatrix(void)
727 displaySystem.driver.PushMatrix(this);
732 displaySystem.driver.PopMatrix(this, true);
736 void ApplyMaterial(Material material, Mesh mesh)
738 if(material != display3D.material)
740 display3D.material = material;
741 displaySystem.driver.ApplyMaterial(this, material, mesh);
745 void DrawPrimitives(PrimitiveSingle primitive, Mesh mesh)
747 displaySystem.driver.DrawPrimitives(this, primitive, mesh);
750 void SelectMesh(Mesh mesh)
752 displaySystem.driver.SelectMesh(this, mesh);
753 display3D.mesh = mesh;
756 bool DrawMesh(Object object)
759 if(display3D.selection)
760 result = display3D.PickMesh(object, null);
763 Mesh mesh = object.mesh;
764 Material objectMaterial = object.material;
766 if(mesh.groups.first)
768 PrimitiveGroup group;
769 displaySystem.driver.SelectMesh(this, mesh);
770 display3D.mesh = mesh;
772 for(group = mesh.groups.first; group; group = group.next)
774 Material material = group.material ? group.material : objectMaterial;
775 if(!material) material = defaultMaterial;
777 if(material != display3D.material)
779 display3D.material = material;
780 displaySystem.driver.ApplyMaterial(this, material, mesh);
783 // *** Render Vertex Arrays ***
784 displaySystem.driver.DrawPrimitives(this, (PrimitiveSingle *)&group.type, mesh);
788 if(object.flags.translucent)
791 Matrix inverse, inverseTranspose;
794 if(object.flags.viewSpace)
795 matrix = object.matrix;
798 Camera camera = display3D.camera;
799 Matrix temp = object.matrix;
800 temp.m[3][0] -= camera.cPosition.x;
801 temp.m[3][1] -= camera.cPosition.y;
802 temp.m[3][2] -= camera.cPosition.z;
803 matrix.Multiply(temp, camera.viewMatrix);
806 inverse.Inverse(matrix);
807 inverseTranspose.Transpose(inverse);
809 for(c = 0; c < mesh.nPrimitives; c++)
811 PrimitiveSingle * triangle = &mesh.primitives[c];
812 SortPrimitive * sort;
813 Plane * plane = &triangle->plane;
814 if(display3D.nTriangles >= display3D.maxTriangles)
816 display3D.maxTriangles = display3D.maxTriangles ? (display3D.maxTriangles * 3 / 2) : 32768;
817 display3D.triangles = renew display3D.triangles SortPrimitive[display3D.maxTriangles];
819 sort = &display3D.triangles[display3D.nTriangles++];
820 sort->object = object;
821 sort->triangle = triangle;
822 sort->middle.MultMatrix(triangle->middle, matrix);
823 sort->middle.z *= -1;
824 // sort->plane.MultMatrix(triangle->plane, inverseTranspose);
825 sort->plane.d = plane->a * inverseTranspose.m[0][3] +
826 plane->b * inverseTranspose.m[1][3] +
827 plane->c * inverseTranspose.m[2][3] +
828 plane->d * inverseTranspose.m[3][3];
834 displaySystem.driver.SelectMesh(this, mesh);
835 display3D.mesh = mesh;
837 for(c = 0; c<mesh.nPrimitives; c++)
839 PrimitiveSingle * primitive = &mesh.primitives[c];
841 Material material = primitive->material ? primitive->material : objectMaterial;
842 if(!material) material = defaultMaterial;
844 if(material != display3D.material)
846 display3D.material = material;
847 displaySystem.driver.ApplyMaterial(this, material, mesh);
850 displaySystem.driver.DrawPrimitives(this, primitive, display3D.mesh);
858 bool IsObjectVisible(Object object)
861 if(display3D.selection || !display3D.camera)
862 planes = object.flags.viewSpace ? display3D.viewPickingPlanes : display3D.worldPickingPlanes;
864 planes = object.flags.viewSpace ? display3D.camera.viewClippingPlanes : display3D.camera.worldClippingPlanes;
865 return object.InsideFrustum(planes) != outside;
868 bool DrawObject(Object object)
871 if(object && object.volume)
874 FrustumPlacement visible;
876 Camera camera = display3D.camera;
878 if(display3D.selection || !camera)
879 planes = object.flags.viewSpace ? display3D.viewPickingPlanes : display3D.worldPickingPlanes;
881 planes = object.flags.viewSpace ? camera.viewClippingPlanes : camera.worldClippingPlanes;
883 visible = object.InsideFrustum(planes);
885 if(visible || display3D.pickingPlanes)
887 if(display3D.collectingHits && object.tag)
889 /*if(object.flags.root)
890 this.tags[display3D.tagIndex] = object.tag;
892 this.tags[++display3D.tagIndex] = object.tag;
894 display3D.tags[display3D.tagIndex++] = object.tag;
897 if(object.flags.mesh && object.mesh)
899 if(!display3D.selection && displaySystem.driver.PushMatrix)
900 displaySystem.driver.PushMatrix(this);
902 SetTransform(object.matrix, object.flags.viewSpace);
903 if(display3D.selection)
905 if(visible == intersecting || display3D.intersecting)
907 Vector3D rayIntersect;
908 if(display3D.PickMesh(object, rayIntersect))
910 if(display3D.intersecting)
912 Vector3D wresult, vresult;
913 wresult.MultMatrix(rayIntersect, object.matrix);
914 if(!object.flags.viewSpace)
915 camera.TransformPoint(vresult, wresult);
919 if(vresult.z < display3D.rayIntersect.z)
920 display3D.rayIntersect = vresult;
921 display3D.intersected = true;
931 result |= DrawMesh(object);
932 if(displaySystem.driver.PopMatrix)
933 displaySystem.driver.PopMatrix(this, true);
935 if(display3D.collectingHits && result /*&& object.tag*/)
938 HitRecord hit = (HitRecord)new0 byte[sizeof(class HitRecord) + sizeof(void *) * (display3D.tagIndex/*+1*/)];
939 display3D.hitList.Add(hit);
940 hit.pos = display3D.hitList.count-1;
941 hit.numTags = display3D.tagIndex /*+ 1*/;
942 for(c = 0; c</*=*/display3D.tagIndex; c++)
944 hit.tags[c] = display3D.tags[c];
947 if(!object.flags.viewSpace)
948 camera.TransformPoint(hit.center, object.wcenter);
950 hit.center = object.wcenter;
954 for(child = object.children.first; child; child = child.next)
955 result |= DrawObject(child);
957 if(display3D.collectingHits && /*!object.flags.root && */object.tag)
958 display3D.tagIndex--;
964 void DrawTranslucency(void)
968 // *** Render translucent primitives ***
969 if(display3D.nTriangles)
971 Matrix * matrix = null;
976 display3D.SortTriangles();
980 displaySystem.driver.PushMatrix(this);
981 for(c=0; c<display3D.nTriangles; c++)
983 SortPrimitive * sort = &display3D.triangles[c];
984 Mesh mesh = sort->object.mesh;
985 PrimitiveSingle * primitive = sort->triangle;
988 if(&sort->object.matrix != matrix)
990 matrix = &sort->object.matrix;
992 displaySystem.driver.PopMatrix(this, false);
993 displaySystem.driver.PushMatrix(this);
994 SetTransform(matrix, sort->object.flags.viewSpace);
996 if(mesh != display3D.mesh)
998 displaySystem.driver.SelectMesh(this, mesh);
999 display3D.mesh = mesh;
1002 material = primitive->material ? primitive->material : sort->object.material;
1003 if(!material) material = defaultMaterial;
1005 if(material != display3D.material)
1007 displaySystem.driver.ApplyMaterial(this, material, display3D.mesh);
1008 display3D.material = material;
1013 Material testMaterial { };
1016 amount = (display3D.triangles[0].middle.z - display3D.triangles[c].middle.z) /
1017 (display3D.triangles[0].middle.z - display3D.triangles[display3D.nTriangles-1].middle.z);
1019 testMaterial.flags.doubleSided = { doubleSided = true, translucent = true };
1020 testMaterial.diffuse.a = 1;
1021 testMaterial.emissive.r = testMaterial.emissive.g = testMaterial.emissive.b = amount;
1022 testMaterial.baseMap = material->baseMap;
1024 displaySystem.driver.ApplyMaterial(this, testMaterial, display3D.mesh);
1028 // *** Render primitive ***
1029 // if(sort->plane.d > 0)
1030 displaySystem.driver.DrawPrimitives(this, primitive, display3D.mesh);
1032 displaySystem.driver.PopMatrix(this, true);
1034 display3D.nTriangles = 0;
1041 void StartSelection(int pickX, int pickY, int pickW, int pickH)
1045 display3D = Display3D { };
1047 display3D.pickX = (float)pickX;
1048 display3D.pickY = (float)pickY;
1049 display3D.pickWidth = (float)pickW;
1050 display3D.pickHeight = (float)pickH;
1051 display3D.selection = true;
1054 void CollectHits(void)
1056 display3D.collectingHits = true;
1059 int GetHits(OldList list)
1061 display3D.collectingHits = false;
1062 display3D.hitList.Sort(HitRecord::Compare, null);
1063 list = display3D.hitList;
1064 display3D.hitList.Clear();
1068 void IntersectPolygons(void)
1070 display3D.rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1071 display3D.intersected = false;
1072 display3D.intersecting = true;
1075 bool GetIntersect(Vector3D intersect)
1077 intersect = display3D.rayIntersect;
1078 display3D.intersecting = false;
1079 return display3D.intersected;
1082 void StopSelection(void)
1084 display3D.selection = false;
1087 // --- Rendering States ---
1088 property FillModeValue fillMode { set { displaySystem.driver.SetRenderState(this, fillMode, value); } };
1089 property bool depthTest { set { displaySystem.driver.SetRenderState(this, depthTest, value); } };
1090 property bool depthWrite { set { displaySystem.driver.SetRenderState(this, depthWrite, value); } };
1091 property float fogDensity { set { displaySystem.driver.SetRenderState(this, fogDensity, RenderStateFloat { value }.ui); } };
1092 property Color fogColor { set { displaySystem.driver.SetRenderState(this, fogColor, value); } };
1093 property bool blend { set { displaySystem.driver.SetRenderState(this, blend, value); } };
1094 property Color ambient { set { displaySystem.driver.SetRenderState(this, ambient, value); } };
1095 property bool alphaWrite { set { displaySystem.driver.SetRenderState(this, alphaWrite, value); } };
1096 property bool antiAlias { set { displaySystem.driver.SetRenderState(this, antiAlias, value); } };
1097 property bool vSync { set { displaySystem.driver.SetRenderState(this, vSync, value); } };
1099 property bool pickingPlanes { set { display3D.pickingPlanes = value; } };
1101 property DisplayFlags flags { get { return displaySystem.flags; } }
1102 property PixelFormat pixelFormat { get { return /*alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat; } }
1103 property bool alphaBlend { set { alphaBlend = value; } get { return alphaBlend; } };
1104 property bool useSharedMemory { set { useSharedMemory = value; } get { return useSharedMemory; } };
1105 property void * systemWindow { get { return window; } };
1106 property DisplaySystem displaySystem { get { return displaySystem; } };
1113 DisplaySystem displaySystem;
1116 #if !defined(__EMSCRIPTEN__)
1121 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1122 Display3D display3D;
1125 void * windowDriverData;
1126 bool useSharedMemory;
1129 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1130 private class Display3D
1134 SortPrimitive * triangles;
1136 Vector3D points[MAX_CLIP_POINTS];
1137 Vector3D newPoints[MAX_CLIP_POINTS];
1138 byte goodPoints[MAX_CLIP_POINTS];
1143 Plane viewPickingPlanes[ClippingPlane], worldPickingPlanes[ClippingPlane];
1144 Plane localPickingPlanes[ClippingPlane];
1146 bool collectingHits, selection, intersecting, intersected, pickingPlanes;
1147 float pickX, pickY, pickWidth, pickHeight;
1152 Line rayView, rayWorld, rayLocal;
1153 Vector3D rayIntersect;
1160 int _SetLights(Display display, Object object, int id)
1162 if(id < NumberOfLights)
1166 if(object.flags.light && !object.light.flags.off)
1167 display.SetLight(id++, object.light);
1169 for(child = object.children.first; child; child = child.next)
1171 id = _SetLights(display, child, id);
1177 //#define TRESHOLD -1
1178 //#define TRESHOLD -0.25
1179 #define TRESHOLD -0.0025
1181 bool PickPrimitives(Mesh mesh, PrimitiveSingle primitive, Vector3D rayDiff, Vector3D rayIntersect)
1183 Plane * planes = localPickingPlanes;
1185 int nIndex = 1, nPoints = 1;
1187 bool result = false;
1188 Vector3D * points = this.points;
1189 Vector3D * newPoints = this.newPoints;
1190 byte * goodPoints = this.goodPoints;
1191 int nVertices = primitive.type.vertexRange ? primitive.nVertices : primitive.nIndices;
1194 bool i32bit = primitive.type.indices32bit;
1195 uint32 * indices32 = primitive.indices32;
1196 uint16 * indices16 = primitive.indices;
1198 switch(primitive.type.primitiveType)
1200 case triangles: nIndex = 3; nPoints = 3; break;
1201 case quads: nIndex = 4; nPoints = 4; break;
1204 nIndex = 1; nPoints = 3;
1206 tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first] : mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
1207 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1208 tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first+1] : mesh.vertices[(i32bit ? indices32[1] : indices16[1])];
1209 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1213 for(c = offset; c<nVertices; c += nIndex)
1215 bool outside = false;
1222 if(primitive.type.vertexRange)
1224 if(primitive.type.primitiveType == triStrip)
1226 tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 1) : (c - 2)];
1227 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1228 tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 2) : (c - 1)];
1229 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1231 else if(primitive.type.primitiveType == triFan)
1233 tmp = mesh.vertices[primitive.first + 0];
1234 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1235 tmp = mesh.vertices[primitive.first + c - 1];
1236 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1238 for(i = 0; i<nIndex; i++)
1240 tmp = mesh.vertices[primitive.first + c+i];
1241 points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1246 if(primitive.type.primitiveType == triStrip)
1248 i = (c & 1) ? (c - 1) : (c - 2);
1249 tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
1250 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1252 i = (c & 1) ? (c - 2) : (c - 1);
1253 tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
1254 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1256 else if(primitive.type.primitiveType == triFan)
1258 tmp = mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
1259 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1260 tmp = mesh.vertices[(i32bit ? indices32[c-1] : indices16[c-1])];
1261 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1263 for(i = 0; i<nIndex; i++)
1265 tmp = mesh.vertices[(i32bit ? indices32[c+i] : indices16[c+i])];
1266 points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1270 for(p = 0; p < 6; p++)
1272 Plane * plane = &planes[p];
1274 int numGoodPoints = 0;
1276 memset(goodPoints, 0, n);
1277 for(i = 0; i < n; i++)
1279 double dot = plane->normal.DotProduct(points[i]);
1280 double distance = dot + plane->d;
1281 if(distance > TRESHOLD)
1292 if(numGoodPoints < n)
1303 newPoints[newN++] = points[j];
1312 for(lastGood = n-1; !goodPoints[lastGood]; lastGood--);
1314 edge.p0 = points[lastGood];
1315 edge.delta.Subtract(points[j], edge.p0);
1316 plane->IntersectLine(edge, newPoints[newN++]);
1318 for(next = j+1; next != j; next++)
1320 if(next == n) next = 0;
1321 if(goodPoints[next])
1323 int prev = next - 1;
1324 if(prev < 0) prev = n-1;
1326 edge.p0 = points[prev];
1327 edge.delta.Subtract(points[next], edge.p0);
1328 plane->IntersectLine(edge, newPoints[newN++]);
1338 // Use the new points
1339 memcpy(points, newPoints, newN * sizeof(Vector3D));
1348 // TODO: Implement intersection with TriStrip, TriFan...
1351 // Intersect primitives
1353 Vector3D intersect, diff;
1354 int i0 = c, i1 = c+1, i2 = c+2;
1356 if(primitive.type.primitiveType == triStrip)
1358 i0 = (c & 1) ? (c - 1) : (c - 2);
1359 i1 = (c & 1) ? (c - 2) : (c - 1);
1362 else if(primitive.type.primitiveType == triFan)
1369 if(primitive.type.vertexRange)
1371 mesh.vertices[primitive.first + i0],
1372 mesh.vertices[primitive.first + i1],
1373 mesh.vertices[primitive.first + i2]);
1376 mesh.vertices[(i32bit ? indices32[i0] : indices16[i0])],
1377 mesh.vertices[(i32bit ? indices32[i1] : indices16[i1])],
1378 mesh.vertices[(i32bit ? indices32[i2] : indices16[i2])]);
1380 plane.IntersectLine(rayLocal, intersect);
1381 diff.Subtract(intersect, rayLocal.p0);
1382 diff.x /= rayLocal.delta.x;
1383 diff.y /= rayLocal.delta.y;
1384 diff.z /= rayLocal.delta.z;
1385 if(diff.x < rayDiff.x || diff.y < rayDiff.y || diff.z < rayDiff.z)
1388 rayIntersect = intersect;
1395 switch(primitive.type)
1398 points[strip] = points[2];
1402 points[1] = points[2];
1409 bool PickMesh(Object object, Vector3D rayIntersect)
1411 Mesh mesh = object.mesh;
1412 bool result = false;
1413 Vector3D rayDiff { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1414 if(rayIntersect != null)
1415 rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1417 if(mesh.groups.first)
1419 PrimitiveGroup group;
1421 for(group = mesh.groups.first; group; group = group.next)
1423 if(PickPrimitives(mesh, (PrimitiveSingle *)&group.type, rayDiff, rayIntersect))
1434 for(c = 0; c < mesh.nPrimitives; c++)
1436 if(PickPrimitives(mesh, mesh.primitives[c], rayDiff, rayIntersect))
1447 void SortTriangles(void)
1450 Object object = null;
1452 for(c=0; c<nTriangles; c++)
1454 SortPrimitive * sort = &triangles[c];
1455 Mesh mesh = sort->object.mesh;
1456 PrimitiveSingle * primitive = sort->triangle;
1457 Vector3Df min { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1458 Vector3Df max { -MAXFLOAT, -MAXFLOAT, -MAXFLOAT };
1460 bool ix32 = primitive->type.indices32bit;
1461 if(object != sort->object)
1463 object = sort->object;
1464 if(object.flags.viewSpace)
1465 matrix = object.matrix;
1468 Camera camera = this.camera;
1469 Matrix temp = object.matrix;
1470 temp.m[3][0] -= camera.cPosition.x;
1471 temp.m[3][1] -= camera.cPosition.y;
1472 temp.m[3][2] -= camera.cPosition.z;
1473 matrix.Multiply(temp, camera.viewMatrix);
1477 for(v = 0; v<primitive->nIndices; v++)
1479 Vector3Df * local = &mesh.vertices[ix32 ? primitive->indices32[v] : primitive->indices[v]];
1482 vertex.MultMatrix(local, &matrix);
1484 if(vertex.x > max.x) max.x = vertex.x;
1485 if(vertex.y > max.y) max.y = vertex.y;
1486 if(vertex.z > max.z) max.z = vertex.z;
1487 if(vertex.x < min.x) min.x = vertex.x;
1488 if(vertex.y < min.y) min.y = vertex.y;
1489 if(vertex.z < min.z) min.z = vertex.z;
1495 sort->marked = false;
1499 Logf("========= Before Sort ==========\n");
1500 for(c=0; c<nTriangles; c++)
1502 SortPrimitive * sort = &triangles[c];
1504 Mesh mesh = sort->mesh;
1505 PrimitiveSingle * primitive = sort->triangle;
1507 Logf("Triangle %d (%s):\n", c, primitive->material->name);
1509 for(v = 0; v<primitive->nIndices; v++)
1511 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1515 vertex.<MultMatrix(local, sort->matrix);
1517 Logf("Vertex %d:", v);
1519 // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
1520 Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
1524 Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
1525 Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
1529 // *** Sort translucent primitives ***
1530 qsort((void*) triangles, nTriangles, sizeof(SortPrimitive), SortPrimitive::Compare);
1532 Logf("\n\n========= After Sort ==========\n");
1533 for(c=0; c<nTriangles; c++)
1535 SortPrimitive * sort = &triangles[c];
1537 Mesh mesh = sort->mesh;
1538 PrimitiveSingle * primitive = sort->triangle;
1540 Logf("Triangle %d (%s):\n", c, primitive->material->name);
1542 for(v = 0; v<primitive->nIndices; v++)
1544 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1548 vertex.MultMatrix(local, sort->matrix);
1550 Logf("Vertex %d:", v);
1552 // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
1553 Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
1557 Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
1558 Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
1565 If all five tests fail for a particular Q,
1566 then P might obscure Q. Now Q must be tested.
1567 First, the algorithm checks if Q has been "marked."
1568 If Q is marked, then Q was "moved around" in the list
1569 during a previous iteration of the loop. The algorithm
1570 only allows a polygon to be moved once, to avoid the possibility
1571 of infinite loops. If Q is not marked, it is tested to see
1572 if it might obscure P. If Q cannot obscure P, then Q is possibly
1573 behind P and so it is good candidate to be drawn next.
1574 Therefore, the algorithm "abandons" the current P (that is, it
1575 stops testing Q's against the current P) and moves the current
1576 Q to the end of the list to become the next P.
1581 for(p = 0; p<nTriangles; p++)
1583 SortPrimitive * poly1 = &triangles[p];
1586 for(q = p+1; q<nTriangles; q++)
1590 SortPrimitive * poly2 = &triangles[q];
1591 if(poly1->ZOverlap(poly2) && !poly2->marked)
1593 if(poly1->ShouldBeSwapped(poly2))
1595 if(!poly2->ShouldBeSwapped(poly1))
1597 SortPrimitive temp = *poly2;
1598 memmove(triangles+1, triangles, sizeof(SortPrimitive)*q);
1599 triangles[0] = temp;
1600 triangles[0].marked = true;
1613 for(p = 0; p<nTriangles; p++)
1615 SortPrimitive * poly1 = &triangles[p];
1618 // for(q = p+1; q<nTriangles; q++)
1619 for(q = 0; q<nTriangles; q++)
1623 SortPrimitive * poly2 = &triangles[q];
1624 if(poly1->ZOverlap(poly2) && !poly2->marked)
1626 if(poly1->ShouldBeSwapped(poly2))
1628 if(!poly2->ShouldBeSwapped(poly1))
1630 SortPrimitive temp = *poly2;
1631 memmove(triangles+1, triangles, sizeof(SortPrimitive)*q);
1632 triangles[0] = temp;
1633 triangles[0].marked = true;
1646 for(p = nTriangles-1; p>=0; p--)
1648 SortPrimitive * poly1 = &triangles[p];
1651 for(q = nTriangles-1; q>=0; q--)
1655 SortPrimitive * poly2 = &triangles[q];
1656 if(poly1->ZOverlap(poly2) && !poly2->marked)
1658 if(poly1->ShouldBeSwapped(poly2))
1660 if(!poly2->ShouldBeSwapped(poly1))
1662 SortPrimitive temp = *poly2;
1663 memmove(triangles + q, triangles + q + 1, sizeof(SortPrimitive)*q);
1665 triangles[nTriangles-1] = temp;
1678 for(c=0; c<nTriangles; c++)
1681 SortPrimitive * poly1 = &triangles[c];
1683 // for(b=0; b<nTriangles; b++)
1684 //for(b=c+1; b<nTriangles; b++)
1686 if(b<this.nTriangles)
1688 SortPrimitive * poly2 = &this.triangles[b];
1690 if(poly1->ZOverlap(poly2) && poly1->ShouldBeSwapped(poly2))
1692 SortPrimitive temp = *poly1;
1705 bool IsDriverTextMode(const char * driverName)
1707 subclass(DisplayDriver) driver = GetDisplayDriver(driverName);
1708 return driver ? driver.textMode : false;
1711 bool IsDriverPrinter(const char * driverName)
1713 subclass(DisplayDriver) driver = GetDisplayDriver(driverName);
1714 return driver ? driver.printer : false;
1717 static ColorAlpha defaultPalette[256] =
1721 0xFF000000,0xFF000080,0xFF008000,0xFF008080,0xFF800000,0xFF800080,0xFF808000,0xFFC0C0C0,
1722 0xFF808080,0xFF0000FF,0xFF00FF00,0xFF00FFFF,0xFFFF0000,0xFFFF00FF,0xFFFFFF00,0xFFFFFFFF,
1724 0xFF000000,0xFF0000AA,0xFF00AA00,0xFF00AAAA,0xFFAA0000,0xFFAA00AA,0xFFAAAA00,0xFFABABAB,
1725 0xFF555555,0xFF5555FF,0xFF55FF55,0xFF55FFFF,0xFFFF5555,0xFFFF55FF,0xFFFFFF55,0xFFFFFFFF,
1727 // 6 x 6 x 6 Color Cube
1728 0xFF000000, 0xFF000033, 0xFF000066, 0xFF000099, 0xFF0000CC, 0xFF0000FF,
1729 0xFF003300, 0xFF003333, 0xFF003366, 0xFF003399, 0xFF0033CC, 0xFF0033FF,
1730 0xFF006600, 0xFF006633, 0xFF006666, 0xFF006699, 0xFF0066CC, 0xFF0066FF,
1731 0xFF009900, 0xFF009933, 0xFF009966, 0xFF009999, 0xFF0099CC, 0xFF0099FF,
1732 0xFF00CC00, 0xFF00CC33, 0xFF00CC66, 0xFF00CC99, 0xFF00CCCC, 0xFF00CCFF,
1733 0xFF00FF00, 0xFF00FF33, 0xFF00FF66, 0xFF00FF99, 0xFF00FFCC, 0xFF00FFFF,
1735 0xFF330000, 0xFF330033, 0xFF330066, 0xFF330099, 0xFF3300CC, 0xFF3300FF,
1736 0xFF333300, 0xFF333333, 0xFF333366, 0xFF333399, 0xFF3333CC, 0xFF3333FF,
1737 0xFF336600, 0xFF336633, 0xFF336666, 0xFF336699, 0xFF3366CC, 0xFF3366FF,
1738 0xFF339900, 0xFF339933, 0xFF339966, 0xFF339999, 0xFF3399CC, 0xFF3399FF,
1739 0xFF33CC00, 0xFF33CC33, 0xFF33CC66, 0xFF33CC99, 0xFF33CCCC, 0xFF33CCFF,
1740 0xFF33FF00, 0xFF33FF33, 0xFF33FF66, 0xFF33FF99, 0xFF33FFCC, 0xFF33FFFF,
1742 0xFF660000, 0xFF660033, 0xFF660066, 0xFF660099, 0xFF6600CC, 0xFF6600FF,
1743 0xFF663300, 0xFF663333, 0xFF663366, 0xFF663399, 0xFF6633CC, 0xFF6633FF,
1744 0xFF666600, 0xFF666633, 0xFF666666, 0xFF666699, 0xFF6666CC, 0xFF6666FF,
1745 0xFF669900, 0xFF669933, 0xFF669966, 0xFF669999, 0xFF6699CC, 0xFF6699FF,
1746 0xFF66CC00, 0xFF66CC33, 0xFF66CC66, 0xFF66CC99, 0xFF66CCCC, 0xFF66CCFF,
1747 0xFF66FF00, 0xFF66FF33, 0xFF66FF66, 0xFF66FF99, 0xFF66FFCC, 0xFF66FFFF,
1749 0xFF990000, 0xFF990033, 0xFF990066, 0xFF990099, 0xFF9900CC, 0xFF9900FF,
1750 0xFF993300, 0xFF993333, 0xFF993366, 0xFF993399, 0xFF9933CC, 0xFF9933FF,
1751 0xFF996600, 0xFF996633, 0xFF996666, 0xFF996699, 0xFF9966CC, 0xFF9966FF,
1752 0xFF999900, 0xFF999933, 0xFF999966, 0xFF999999, 0xFF9999CC, 0xFF9999FF,
1753 0xFF99CC00, 0xFF99CC33, 0xFF99CC66, 0xFF99CC99, 0xFF99CCCC, 0xFF99CCFF,
1754 0xFF99FF00, 0xFF99FF33, 0xFF99FF66, 0xFF99FF99, 0xFF99FFCC, 0xFF99FFFF,
1756 0xFFCC0000, 0xFFCC0033, 0xFFCC0066, 0xFFCC0099, 0xFFCC00CC, 0xFFCC00FF,
1757 0xFFCC3300, 0xFFCC3333, 0xFFCC3366, 0xFFCC3399, 0xFFCC33CC, 0xFFCC33FF,
1758 0xFFCC6600, 0xFFCC6633, 0xFFCC6666, 0xFFCC6699, 0xFFCC66CC, 0xFFCC66FF,
1759 0xFFCC9900, 0xFFCC9933, 0xFFCC9966, 0xFFCC9999, 0xFFCC99CC, 0xFFCC99FF,
1760 0xFFCCCC00, 0xFFCCCC33, 0xFFCCCC66, 0xFFCCCC99, 0xFFCCCCCC, 0xFFCCCCFF,
1761 0xFFCCFF00, 0xFFCCFF33, 0xFFCCFF66, 0xFFCCFF99, 0xFFCCFFCC, 0xFFCCFFFF,
1763 0xFFFF0000, 0xFFFF0033, 0xFFFF0066, 0xFFFF0099, 0xFFFF00CC, 0xFFFF00FF,
1764 0xFFFF3300, 0xFFFF3333, 0xFFFF3366, 0xFFFF3399, 0xFFFF33CC, 0xFFFF33FF,
1765 0xFFFF6600, 0xFFFF6633, 0xFFFF6666, 0xFFFF6699, 0xFFFF66CC, 0xFFFF66FF,
1766 0xFFFF9900, 0xFFFF9933, 0xFFFF9966, 0xFFFF9999, 0xFFFF99CC, 0xFFFF99FF,
1767 0xFFFFCC00, 0xFFFFCC33, 0xFFFFCC66, 0xFFFFCC99, 0xFFFFCCCC, 0xFFFFCCFF,
1768 0xFFFFFF00, 0xFFFFFF33, 0xFFFFFF66, 0xFFFFFF99, 0xFFFFFFCC, 0xFFFFFFFF,
1770 // 16 Shades of gray
1771 0xFF000000,0xFF101010,0xFF202020,0xFF303030,0xFF404040,0xFF505050,0xFF606060,0xFF707070,
1772 0xFF808080,0xFF909090,0xFFA0A0A0,0xFFB0B0B0,0xFFC0C0C0,0xFFD0D0D0,0xFFE0E0E0,0xFFF0F0F0,
1775 0xFF080808,0xFF101010,0xFF585858,0xFF606060,0xFFA8A8A8,0xFFB0B0B0,0xFFF8F8F8,0xFFFFFFFF
1779 0xFF080000,0xFF100000,0xFF180000,0xFF200000,0xFF280000,0xFF300000,0xFF380000,0xFF400000,
1780 0xFF480000,0xFF500000,0xFF580000,0xFF600000,0xFF680000,0xFF700000,0xFF780000,0xFF800000,
1781 0xFF880000,0xFF900000,0xFF980000,0xFFA00000,0xFFA80000,0xFFB00000,0xFFB80000,0xFFC00000,
1782 0xFFC80000,0xFFD00000,0xFFD80000,0xFFE00000,0xFFE80000,0xFFF00000,0xFFF80000,0xFFFF0000,
1784 0xFF000800,0xFF001000,0xFF001800,0xFF002000,0xFF002800,0xFF003000,0xFF003800,0xFF004000,
1785 0xFF004800,0xFF005000,0xFF005800,0xFF006000,0xFF006800,0xFF007000,0xFF007800,0xFF008000,
1786 0xFF008800,0xFF009000,0xFF009800,0xFF00A000,0xFF00A800,0xFF00B000,0xFF00B800,0xFF00C000,
1787 0xFF00C800,0xFF00D000,0xFF00D800,0xFF00E000,0xFF00E800,0xFF00F000,0xFF00F800,0xFF00FF00,
1789 0xFF000808,0xFF001010,0xFF001818,0xFF002020,0xFF002828,0xFF003030,0xFF003838,0xFF004040,
1790 0xFF004848,0xFF005050,0xFF005858,0xFF006060,0xFF006868,0xFF007070,0xFF007878,0xFF008080,
1791 0xFF008888,0xFF009090,0xFF009898,0xFF00A0A0,0xFF00A8A8,0xFF00B0B0,0xFF00B8B8,0xFF00C0C0,
1792 0xFF00C8C8,0xFF00D0D0,0xFF00D8D8,0xFF00E0E0,0xFF00E8E8,0xFF00F0F0,0xFF00F8F8,0xFF00FFFF,
1794 0xFF000008,0xFF000010,0xFF000018,0xFF000020,0xFF000028,0xFF000030,0xFF000038,0xFF000040,
1795 0xFF000048,0xFF000050,0xFF000058,0xFF000060,0xFF000068,0xFF000070,0xFF000078,0xFF000080,
1796 0xFF000088,0xFF000090,0xFF000098,0xFF0000A0,0xFF0000A8,0xFF0000B0,0xFF0000B8,0xFF0000C0,
1797 0xFF0000C8,0xFF0000D0,0xFF0000D8,0xFF0000E0,0xFF0000E8,0xFF0000F0,0xFF0000F8,0xFF0000FF,
1799 0xFF080008,0xFF100010,0xFF180018,0xFF200020,0xFF280028,0xFF300030,0xFF380038,0xFF400040,
1800 0xFF480048,0xFF500050,0xFF580058,0xFF600060,0xFF680068,0xFF700070,0xFF780078,0xFF800080,
1801 0xFF880088,0xFF900090,0xFF980098,0xFFA000A0,0xFFA800A8,0xFFB000B0,0xFFB800B8,0xFFC000C0,
1802 0xFFC800C8,0xFFD000D0,0xFFD800D8,0xFFE000E0,0xFFE800E8,0xFFF000F0,0xFFF800F8,0xFFFF00FF,
1804 0xFF080800,0xFF101000,0xFF181800,0xFF202000,0xFF282800,0xFF303000,0xFF383800,0xFF404000,
1805 0xFF484800,0xFF505000,0xFF585800,0xFF606000,0xFF686800,0xFF707000,0xFF787800,0xFF808000,
1806 0xFF888800,0xFF909000,0xFF989800,0xFFA0A000,0xFFA8A800,0xFFB0B000,0xFFB8B800,0xFFC0C000,
1807 0xFFC8C800,0xFFD0D000,0xFFD8D800,0xFFE0E000,0xFFE8E800,0xFFF0F000,0xFFF8F800,0xFFFFFF00,
1809 0xFF080808,0xFF101010,0xFF181818,0xFF202020,0xFF282828,0xFF303030,0xFF383838,0xFF404040,
1810 0xFF484848,0xFF505050,0xFF585858,0xFF606060,0xFF686868,0xFF707070,0xFF787878,0xFF808080,
1811 0xFF888888,0xFF909090,0xFF989898,0xFFA0A0A0,0xFFA8A8A8,0xFFB0B0B0,0xFFB8B8B8,0xFFC0C0C0,
1812 0xFFC8C8C8,0xFFD0D0D0,0xFFD8D8D8,0xFFE0E0E0,0xFFE8E8E8,0xFFF0F0F0,0xFFF8F8F8,0xFFFFFFFF
1816 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1817 static Material defaultMaterial
1820 diffuse = { 1.0f, 1.0f, 1.0f },
1821 ambient = { 1.0f, 1.0f, 1.0f },
1822 flags = { doubleSided = true, noFog = true };
1826 static byte colorDepthShifts[PixelFormat] = { 0,0,1,1,1,2,0,1,2 };
1827 static Size resolutions[Resolution] =
1830 {320,200},{320,240},{320,400},{360,480},
1831 {400,256},{400,300},{512,256},{512,384},
1832 {640,200},{640,350},{640,400},{640,480},
1833 {720,348},{800,600},{856,480},{960,720},
1834 {1024,768},{1152,864},{1280,1024},{1600,1200},
1837 static int colorDepths[PixelFormat] = {4,8,12,15,16,32,8,16,32};
1839 // --- Query utilities ---
1841 public int GetResolutionWidth(Resolution resolution)
1843 return resolutions[resolution].w;
1846 public int GetResolutionHeight(Resolution resolution)
1848 return resolutions[resolution].h;
1851 public int GetDepthBits(PixelFormat colorDepth)
1853 return colorDepths[colorDepth];
1856 public byte GetColorDepthShifts(PixelFormat format)
1858 return colorDepthShifts[format];
1861 public ColorAlpha * GetDefaultPalette()
1863 return (ColorAlpha *)defaultPalette;
1865 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1866 public Material GetDefaultMaterial()
1868 return defaultMaterial;
1871 public int BestColorMatch(ColorAlpha * palette, int start, int end, Color rgb)
1877 int bestscore = MAXINT,score;
1878 byte r = rgb.r, g = rgb.g, b = rgb.b;
1881 for(c = start; c <= end; c++)
1884 current = palette[c];
1885 if(rgb && !c) continue;
1889 score = Abs(dr) + Abs(dg) + Abs(db);
1890 if(score <= bestscore)
1900 // had to move this here due to compiler ordering issue for "get property" symbol
1901 subclass(DisplayDriver) GetDisplayDriver(const char * driverName)
1906 for(link = class(DisplayDriver).derivatives.first; link; link = link.next)
1908 subclass(DisplayDriver) displayDriver = link.data;
1909 if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName))
1910 return displayDriver;
1916 DisplaySystem GetDisplaySystem(const char * driverName)
1918 subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName);
1919 return displayDriver ? displayDriver.displaySystem : null;