Front most window using CGWindowListCopyWindowInfo - objective-c
In the documentation, it says that list of windows returned by this method:
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
will return windows in order from front to back. But it doesn't...The front most window should be test, but here's the out of this array:
2011-03-12 18:18:14.221 test[982:a0f] (
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 22;
Width = 212;
X = 1662;
Y = 0;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 25;
kCGWindowMemoryUsage = 30104;
kCGWindowName = "";
kCGWindowNumber = 14;
kCGWindowOwnerName = SystemUIServer;
kCGWindowOwnerPID = 99;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
},
{
kCGWindowAlpha = 0;
kCGWindowBounds = {
Height = 22;
Width = 1920;
X = 0;
Y = 0;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 25;
kCGWindowMemoryUsage = 5528;
kCGWindowNumber = 15;
kCGWindowOwnerName = SystemUIServer;
kCGWindowOwnerPID = 99;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 22;
Width = 46;
X = 1874;
Y = 0;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 25;
kCGWindowMemoryUsage = 5528;
kCGWindowName = "";
kCGWindowNumber = 12;
kCGWindowOwnerName = SystemUIServer;
kCGWindowOwnerPID = 99;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 22;
Width = 1920;
X = 0;
Y = 0;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 24;
kCGWindowMemoryUsage = 218520;
kCGWindowName = "Shared Menubar";
kCGWindowNumber = 6;
kCGWindowOwnerName = "Window Server";
kCGWindowOwnerPID = 73;
kCGWindowSharingState = 2;
kCGWindowStoreType = 2;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 1058;
Width = 1920;
X = 0;
Y = 22;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 20;
kCGWindowMemoryUsage = 1200;
kCGWindowNumber = 13;
kCGWindowOwnerName = Dock;
kCGWindowOwnerPID = 98;
kCGWindowSharingState = 1;
kCGWindowStoreType = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 52;
Width = 676;
X = 622;
Y = 1028;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 19;
kCGWindowMemoryUsage = 157080;
kCGWindowName = "Magic Mirror";
kCGWindowNumber = 16;
kCGWindowOwnerName = Dock;
kCGWindowOwnerPID = 98;
kCGWindowSharingState = 2;
kCGWindowStoreType = 2;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 382;
Width = 480;
X = 335;
Y = 367;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 792496;
kCGWindowName = test;
kCGWindowNumber = 252;
kCGWindowOwnerName = test;
kCGWindowOwnerPID = 982;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 807;
Width = 1206;
X = 321;
Y = 157;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 4055280;
kCGWindowName = "AppDelegate.m - test";
kCGWindowNumber = 24;
kCGWindowOwnerName = Xcode;
kCGWindowOwnerPID = 132;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 967;
Width = 960;
X = 175;
Y = 22;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 3817968;
kCGWindowName = "test - Debugger Console";
kCGWindowNumber = 31;
kCGWindowOwnerName = Xcode;
kCGWindowOwnerPID = 132;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 967;
Width = 1845;
X = 121;
Y = 22;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 882288;
kCGWindowName = "CocoaDev Forums - get focused window id";
kCGWindowNumber = 80;
kCGWindowOwnerName = "Google Chrome";
kCGWindowOwnerPID = 244;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 784;
Width = 885;
X = 560;
Y = 157;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 318768;
kCGWindowName = "Console Messages";
kCGWindowNumber = 125;
kCGWindowOwnerName = Console;
kCGWindowOwnerPID = 482;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 494;
Width = 1167;
X = 519;
Y = 417;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 2441264;
kCGWindowName = Debug;
kCGWindowNumber = 54;
kCGWindowOwnerName = Finder;
kCGWindowOwnerPID = 100;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 382;
Width = 480;
X = 335;
Y = 367;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 55216;
kCGWindowName = test;
kCGWindowNumber = 223;
kCGWindowOwnerName = test;
kCGWindowOwnerPID = 849;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 437;
Width = 770;
X = 396;
Y = 308;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 238512;
kCGWindowName = Applications;
kCGWindowNumber = 19;
kCGWindowOwnerName = Finder;
kCGWindowOwnerPID = 100;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 437;
Width = 770;
X = 450;
Y = 429;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 332720;
kCGWindowName = Applications;
kCGWindowNumber = 17;
kCGWindowOwnerName = Finder;
kCGWindowOwnerPID = 100;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 14;
Width = 1920;
X = 0;
Y = 22;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = "-20";
kCGWindowMemoryUsage = 5528;
kCGWindowName = "Backstop Menubar";
kCGWindowNumber = 11;
kCGWindowOwnerName = "Window Server";
kCGWindowOwnerPID = 73;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 1080;
Width = 1920;
X = 0;
Y = 0;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = "-2147483627";
kCGWindowMemoryUsage = 1200;
kCGWindowName = "";
kCGWindowNumber = 10;
kCGWindowOwnerName = Finder;
kCGWindowOwnerPID = 100;
kCGWindowSharingState = 1;
kCGWindowStoreType = 1;
},
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 1080;
Width = 1920;
X = 0;
Y = 0;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = "-2147483628";
kCGWindowMemoryUsage = 8328600;
kCGWindowName = Desktop;
kCGWindowNumber = 2;
kCGWindowOwnerName = "Window Server";
kCGWindowOwnerPID = 73;
kCGWindowSharingState = 2;
kCGWindowStoreType = 2;
}
)
What's SystemUIServer, dock and magic mirror? These aren't my front most apps. Thanks!
Grab a copy of Apple's sample app: Son Of Grab. Then build and run it, and you'll have a very handy interactive app for investigating all the windows known to the window server.
The answer to your question is that windows are ordered front to back, but there are far more user interface elements defined as windows than you are expecting. This includes the menubar, the dock, the services menu, the Desktop, etc. These are defined at different levels, corresponding to kCGWindowLayer in your output.
You want the first window defined at the standard window level (zero). And if you look at your output, the first window with kCGWindowLayer == 0 is in fact the 7th.
SystemUIServer is the top menu bar. Dock is the Dock (usually at the bottom of the screen). I'm not familiar with "Magic Mirror." You can look for it on your system with lsregister:
`locate lsregister` -dump
Search the output for "Magic Mirror".
Related
Algorithm for computing inverse polynomials in NTRUEncrypt
I'm implementing in code an algorithm for computing inverse polynomials in the NTRU cryptosystem, and I'm using the paper "Almost Inverses and Fast NTRU Key Creation" by Joseph H. Silverman. I implemented the second pseudo-code as: int inverse_mod_p(polynomial *r, polynomial *a) { int k; int16_t b[NTRU_N + 1], c[NTRU_N + 1], f[NTRU_N + 1], g[NTRU_N + 1]; int i; int16_t aux; int zero_f; int constant_f; int deg_fg; memset(b, 0, (NTRU_N + 1) * sizeof(int16_t)); b[0] = 1; memset(c, 0, (NTRU_N + 1) * sizeof(int16_t)); memcpy(f, a->coeffs, NTRU_N * sizeof(int16_t)); f[NTRU_N] = 0; memset(g, 0, (NTRU_N + 1) * sizeof(int16_t)); g[0] = -1; g[NTRU_N] = 1; while (1) { zero_f = 1; for (i = 0; i < NTRU_N + 1; i++) { if (f[i] != 0) { zero_f = 0; break; } } if (zero_f) return 1; while (f[0] == 0) { for (i = 0; i < NTRU_N; i++) { f[i] = f[i + 1]; c[NTRU_N - i] = c[NTRU_N - i - 1]; } f[NTRU_N] = 0; c[0] = 0; k++; } constant_f = 1; for (i = 1; i < NTRU_N + 1; i++) { if (f[i] != 0) { constant_f = 0; break; } } if (constant_f) break; deg_fg = 0; for (i = NTRU_N; i >= 0; i--) { if (f[i] == 0 && g[i] != 0) { deg_fg = 1; break; } else if (f[i] != 0 && g[i] == 0) { break; } } if (deg_fg) { for (i = 0; i < NTRU_N + 1; i++) { aux = f[i]; f[i] = g[i]; g[i] = aux; aux = b[i]; b[i] = c[i]; c[i] = aux; } } if (f[0] == g[0]) { for (i = 0; i < NTRU_N + 1; i++) { f[i] = (f[i] - g[i] + 3) % 3; b[i] = (b[i] - c[i] + 3) % 3; } } else { for (i = 0; i < NTRU_N + 1; i++) { f[i] = (f[i] + g[i] + 3) % 3; b[i] = (b[i] + c[i] + 3) % 3; } } } k = k % NTRU_N; for (i = NTRU_N - 1; i >= 0; i--) { if (i - k < 0) r->coeffs[i - k + NTRU_N] = b[i] * f[0]; else r->coeffs[i - k] = b[i] * f[0]; } for (i = 0; i < NTRU_N; i++) r->coeffs[i] = (r->coeffs[i] + 3) % 3; return 0; } But this seems to be wrong. I tested it using the example giveng in Wikipedia: https://en.wikipedia.org/wiki/NTRUEncrypt . The polynomial -1 + x + x^2 - x^4 + x^6 + x^9 - x^10 should have as inverse the polynomial 1 + 2x + 2x^3 + 2x^4 + x^5 + 2x^7 + x^8 - x^10 , but I got the following result: Polinomial: -1 1 1 0 -1 0 1 0 0 1 -1 Inverse polinomial: 0 2 2 1 0 2 1 2 0 1 2 Where is the error in the implementation?
THREE.JS + Delaunator.JS Keeping faces indexing
Probably this question is for Mapbox team and Delaunator.JS developers, but I hope that somebody could help me here. I have a pseudo quadtree geometry (THREE.BufferGeometry) set by series of points having seven partitions with their individual draw call (geometry.addGroup() method) and material. //pseudo quadtree var points = [], indices = [], quad_uvs = [], groups = [], materials = []; getSegmentSubpoints(0, new THREE.Vector3(-1024, 0, -1024), 1024, 1024, 4); getSegmentSubpoints(1, new THREE.Vector3(0, 0, -1024), 1024, 1024, 4); getSegmentSubpoints(2, new THREE.Vector3(-1024, 0, 0), 1024, 1024, 4); getSegmentSubpoints(3, new THREE.Vector3(0, 0, 0), 512, 512, 8); getSegmentSubpoints(4, new THREE.Vector3(512, 0, 0), 512, 512, 8); getSegmentSubpoints(5, new THREE.Vector3(0, 0, 512), 512, 512, 8); getSegmentSubpoints(6, new THREE.Vector3(512, 0, 512), 512, 512, 8); var geometry = new THREE.BufferGeometry().setFromPoints(points); geometry.setIndex(indices); geometry.setAttribute( 'uv', new THREE.BufferAttribute(new Float32Array(quad_uvs), 2 ) ); geometry.computeVertexNormals(); var colors = [new THREE.Color(0xe6194b), new THREE.Color(0x3cb44b), new THREE.Color(0xffe119), new THREE.Color(0x4363d8), new THREE.Color(0xf58231), new THREE.Color(0x911eb4), new THREE.Color(0x46f0f0) ] groups.forEach(function(g_, i_){ geometry.addGroup(g_.start, g_.end, g_.id); }); var plane = new THREE.Mesh(geometry, materials); plane.rotation.set(Math.PI, 0, 0); plane.position.set(-1152, 0, 0); scene.add(plane); function getSegmentSubpoints(id_, lt_, w_, h_, level_){ var subpoints = []; var subindices = []; var subquad = []; var lastIndex = points.length; var lastIndex2 = indices.length; var step = {x: w_ / level_, z: h_ / level_ }; var stepT = {x: 1.0 / level_, z: 1.0 / level_ }; for(var z = 0; z <= level_; z++){ for(var x = 0; x <= level_; x++){ var dx = lt_.x + step.x * x; var dz = lt_.z + step.z * z; var dy = noise.simplex2(dx / 512.0, dz / 512.0) * 32.0; subquad.push(...[stepT.x * x, stepT.z * z]); subpoints.push(new THREE.Vector3(dx, dy, dz)); } } for(var i = 0; i < subpoints.length - level_ - 2; i++) { if(i % (level_ + 1) != (level_)){ subindices.push(lastIndex + i, lastIndex + i + 1, lastIndex + i + level_ + 2, lastIndex + i + level_ + 2, lastIndex + i + level_ + 1, lastIndex + i); } } points.push(...subpoints); indices.push(...subindices); quad_uvs.push(...subquad); groups.push({id: id_, start: lastIndex2, end: subindices.length}); materials.push(new THREE.MeshBasicMaterial({ wireframe: true, map: new THREE.TextureLoader().load("textures/" + id_ + ".jpg")})); } Everything is fine, but for my project I have to process the current geometry through Delaunator.JS and it seems that the output has different triangles/faces indexing starting from the center. There is dynamic colors for each segment to visualize indexing. Eventually, it has to be the same as previous one with seven materials and individual draw calls. //delaunay var geometry = new THREE.BufferGeometry().setFromPoints(points); var indexDelaunay = Delaunator.from(points.map(v => { return [v.x, v.z]; }) ); var meshIndex = []; for (let i = 0; i < indexDelaunay.triangles.length; i++){ meshIndex.push(indexDelaunay.triangles[i]); } geometry.setIndex(meshIndex); geometry.computeVertexNormals(); count = 0; for(var i = 0; i < meshIndex.length; i += 6){ geometry.addGroup(i, 6, i / 6); materials.push(new THREE.MeshBasicMaterial({ wireframe: true, color: new THREE.Color("hsl(" + (360 / 316 * count) + ",80%, 80%)")})) count++; } var plane = new THREE.Mesh(geometry, materials); plane.rotation.set(Math.PI, 0, 0) plane.position.set(1152, 0, 0); scene.add(plane); So is there a way to re-index faces back so I could get the same result? Yes, I could go through each Delaunator.triangles check its position/area for if it fits the certain partition, but it's not an elegant and fast solution. I bet it's possible to tweak Delaunator.JS code for right indexing on the fly. The snippet is attached as well. //https://hofk.de/main/discourse.threejs/2018/Triangulation/Triangulation.html ////by Mapbox https://github.com/mapbox/delaunator (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.Delaunator = factory()); }(this, (function () { 'use strict'; var EPSILON = Math.pow(2, -52); var Delaunator = function Delaunator(coords) { var this$1 = this; var n = coords.length >> 1; if (n > 0 && typeof coords[0] !== 'number') { throw new Error('Expected coords to contain numbers.'); } this.coords = coords; var maxTriangles = 2 * n - 5; var triangles = this.triangles = new Uint32Array(maxTriangles * 3); var halfedges = this.halfedges = new Int32Array(maxTriangles * 3); this._hashSize = Math.ceil(Math.sqrt(n)); var hullPrev = this.hullPrev = new Uint32Array(n); var hullNext = this.hullNext = new Uint32Array(n); var hullTri = this.hullTri = new Uint32Array(n); var hullHash = new Int32Array(this._hashSize).fill(-1); var ids = new Uint32Array(n); var minX = Infinity; var minY = Infinity; var maxX = -Infinity; var maxY = -Infinity; for (var i = 0; i < n; i++) { var x = coords[2 * i]; var y = coords[2 * i + 1]; if (x < minX) { minX = x; } if (y < minY) { minY = y; } if (x > maxX) { maxX = x; } if (y > maxY) { maxY = y; } ids[i] = i; } var cx = (minX + maxX) / 2; var cy = (minY + maxY) / 2; var minDist = Infinity; var i0, i1, i2; for (var i$1 = 0; i$1 < n; i$1++) { var d = dist(cx, cy, coords[2 * i$1], coords[2 * i$1 + 1]); if (d < minDist) { i0 = i$1; minDist = d; } } var i0x = coords[2 * i0]; var i0y = coords[2 * i0 + 1]; minDist = Infinity; for (var i$2 = 0; i$2 < n; i$2++) { if (i$2 === i0) { continue; } var d$1 = dist(i0x, i0y, coords[2 * i$2], coords[2 * i$2 + 1]); if (d$1 < minDist && d$1 > 0) { i1 = i$2; minDist = d$1; } } var i1x = coords[2 * i1]; var i1y = coords[2 * i1 + 1]; var minRadius = Infinity; for (var i$3 = 0; i$3 < n; i$3++) { if (i$3 === i0 || i$3 === i1) { continue; } var r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i$3], coords[2 * i$3 + 1]); if (r < minRadius) { i2 = i$3; minRadius = r; } } var i2x = coords[2 * i2]; var i2y = coords[2 * i2 + 1]; if (minRadius === Infinity) { throw new Error('No Delaunay triangulation exists for this input.'); } if (orient(i0x, i0y, i1x, i1y, i2x, i2y)) { var i$4 = i1; var x$1 = i1x; var y$1 = i1y; i1 = i2; i1x = i2x; i1y = i2y; i2 = i$4; i2x = x$1; i2y = y$1; } var center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y); this._cx = center.x; this._cy = center.y; var dists = new Float64Array(n); for (var i$5 = 0; i$5 < n; i$5++) { dists[i$5] = dist(coords[2 * i$5], coords[2 * i$5 + 1], center.x, center.y); } quicksort(ids, dists, 0, n - 1); this.hullStart = i0; var hullSize = 3; hullNext[i0] = hullPrev[i2] = i1; hullNext[i1] = hullPrev[i0] = i2; hullNext[i2] = hullPrev[i1] = i0; hullTri[i0] = 0; hullTri[i1] = 1; hullTri[i2] = 2; hullHash[this._hashKey(i0x, i0y)] = i0; hullHash[this._hashKey(i1x, i1y)] = i1; hullHash[this._hashKey(i2x, i2y)] = i2; this.trianglesLen = 0; this._addTriangle(i0, i1, i2, -1, -1, -1); for (var k = 0, xp = (void 0), yp = (void 0); k < ids.length; k++) { var i$6 = ids[k]; var x$2 = coords[2 * i$6]; var y$2 = coords[2 * i$6 + 1]; if (k > 0 && Math.abs(x$2 - xp) <= EPSILON && Math.abs(y$2 - yp) <= EPSILON) { continue; } xp = x$2; yp = y$2; if (i$6 === i0 || i$6 === i1 || i$6 === i2) { continue; } var start = 0; for (var j = 0, key = this._hashKey(x$2, y$2); j < this._hashSize; j++) { start = hullHash[(key + j) % this$1._hashSize]; if (start !== -1 && start !== hullNext[start]) { break; } } start = hullPrev[start]; var e = start, q = (void 0); while (q = hullNext[e], !orient(x$2, y$2, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1])) { e = q; if (e === start) { e = -1; break; } } if (e === -1) { continue; } var t = this$1._addTriangle(e, i$6, hullNext[e], -1, -1, hullTri[e]); hullTri[i$6] = this$1._legalize(t + 2); hullTri[e] = t; hullSize++; var n$1 = hullNext[e]; while (q = hullNext[n$1], orient(x$2, y$2, coords[2 * n$1], coords[2 * n$1 + 1], coords[2 * q], coords[2 * q + 1])) { t = this$1._addTriangle(n$1, i$6, q, hullTri[i$6], -1, hullTri[n$1]); hullTri[i$6] = this$1._legalize(t + 2); hullNext[n$1] = n$1; hullSize--; n$1 = q; } if (e === start) { while (q = hullPrev[e], orient(x$2, y$2, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1])) { t = this$1._addTriangle(q, i$6, e, -1, hullTri[e], hullTri[q]); this$1._legalize(t + 2); hullTri[q] = t; hullNext[e] = e; hullSize--; e = q; } } this$1.hullStart = hullPrev[i$6] = e; hullNext[e] = hullPrev[n$1] = i$6; hullNext[i$6] = n$1; hullHash[this$1._hashKey(x$2, y$2)] = i$6; hullHash[this$1._hashKey(coords[2 * e], coords[2 * e + 1])] = e; } this.hull = new Uint32Array(hullSize); for (var i$7 = 0, e$1 = this.hullStart; i$7 < hullSize; i$7++) { this$1.hull[i$7] = e$1; e$1 = hullNext[e$1]; } this.hullPrev = this.hullNext = this.hullTri = null; this.triangles = triangles.subarray(0, this.trianglesLen); this.halfedges = halfedges.subarray(0, this.trianglesLen); }; Delaunator.from = function from (points, getX, getY) { if ( getX === void 0 ) getX = defaultGetX; if ( getY === void 0 ) getY = defaultGetY; var n = points.length; var coords = new Float64Array(n * 2); for (var i = 0; i < n; i++) { var p = points[i]; coords[2 * i] = getX(p); coords[2 * i + 1] = getY(p); } return new Delaunator(coords); }; Delaunator.prototype._hashKey = function _hashKey (x, y) { return Math.floor(pseudoAngle(x - this._cx, y - this._cy) * this._hashSize) % this._hashSize; }; Delaunator.prototype._legalize = function _legalize (a) { var this$1 = this; var ref = this; var triangles = ref.triangles; var coords = ref.coords; var halfedges = ref.halfedges; var b = halfedges[a]; var a0 = a - a % 3; var b0 = b - b % 3; var al = a0 + (a + 1) % 3; var ar = a0 + (a + 2) % 3; var bl = b0 + (b + 2) % 3; if (b === -1) { return ar; } var p0 = triangles[ar]; var pr = triangles[a]; var pl = triangles[al]; var p1 = triangles[bl]; var illegal = inCircle( coords[2 * p0], coords[2 * p0 + 1], coords[2 * pr], coords[2 * pr + 1], coords[2 * pl], coords[2 * pl + 1], coords[2 * p1], coords[2 * p1 + 1]); if (illegal) { triangles[a] = p1; triangles[b] = p0; var hbl = halfedges[bl]; if (hbl === -1) { var e = this.hullStart; do { if (this$1.hullTri[e] === bl) { this$1.hullTri[e] = a; break; } e = this$1.hullNext[e]; } while (e !== this.hullStart); } this._link(a, hbl); this._link(b, halfedges[ar]); this._link(ar, bl); var br = b0 + (b + 1) % 3; this._legalize(a); return this._legalize(br); } return ar; }; Delaunator.prototype._link = function _link (a, b) { this.halfedges[a] = b; if (b !== -1) { this.halfedges[b] = a; } }; Delaunator.prototype._addTriangle = function _addTriangle (i0, i1, i2, a, b, c) { var t = this.trianglesLen; this.triangles[t] = i0; this.triangles[t + 1] = i1; this.triangles[t + 2] = i2; this._link(t, a); this._link(t + 1, b); this._link(t + 2, c); this.trianglesLen += 3; return t; }; function pseudoAngle(dx, dy) { var p = dx / (Math.abs(dx) + Math.abs(dy)); return (dy > 0 ? 3 - p : 1 + p) / 4; } function dist(ax, ay, bx, by) { var dx = ax - bx; var dy = ay - by; return dx * dx + dy * dy; } function orient(px, py, qx, qy, rx, ry) { return (qy - py) * (rx - qx) - (qx - px) * (ry - qy) < 0; } function inCircle(ax, ay, bx, by, cx, cy, px, py) { var dx = ax - px; var dy = ay - py; var ex = bx - px; var ey = by - py; var fx = cx - px; var fy = cy - py; var ap = dx * dx + dy * dy; var bp = ex * ex + ey * ey; var cp = fx * fx + fy * fy; return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0; } function circumradius(ax, ay, bx, by, cx, cy) { var dx = bx - ax; var dy = by - ay; var ex = cx - ax; var ey = cy - ay; var bl = dx * dx + dy * dy; var cl = ex * ex + ey * ey; var d = 0.5 / (dx * ey - dy * ex); var x = (ey * bl - dy * cl) * d; var y = (dx * cl - ex * bl) * d; return x * x + y * y; } function circumcenter(ax, ay, bx, by, cx, cy) { var dx = bx - ax; var dy = by - ay; var ex = cx - ax; var ey = cy - ay; var bl = dx * dx + dy * dy; var cl = ex * ex + ey * ey; var d = 0.5 / (dx * ey - dy * ex); var x = ax + (ey * bl - dy * cl) * d; var y = ay + (dx * cl - ex * bl) * d; return {x: x, y: y}; } function quicksort(ids, dists, left, right) { if (right - left <= 20) { for (var i = left + 1; i <= right; i++) { var temp = ids[i]; var tempDist = dists[temp]; var j = i - 1; while (j >= left && dists[ids[j]] > tempDist) { ids[j + 1] = ids[j--]; } ids[j + 1] = temp; } } else { var median = (left + right) >> 1; var i$1 = left + 1; var j$1 = right; swap(ids, median, i$1); if (dists[ids[left]] > dists[ids[right]]) { swap(ids, left, right); } if (dists[ids[i$1]] > dists[ids[right]]) { swap(ids, i$1, right); } if (dists[ids[left]] > dists[ids[i$1]]) { swap(ids, left, i$1); } var temp$1 = ids[i$1]; var tempDist$1 = dists[temp$1]; while (true) { do { i$1++; } while (dists[ids[i$1]] < tempDist$1); do { j$1--; } while (dists[ids[j$1]] > tempDist$1); if (j$1 < i$1) { break; } swap(ids, i$1, j$1); } ids[left + 1] = ids[j$1]; ids[j$1] = temp$1; if (right - i$1 + 1 >= j$1 - left) { quicksort(ids, dists, i$1, right); quicksort(ids, dists, left, j$1 - 1); } else { quicksort(ids, dists, left, j$1 - 1); quicksort(ids, dists, i$1, right); } } } function swap(arr, i, j) { var tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } function defaultGetX(p) { return p[0]; } function defaultGetY(p) { return p[1]; } return Delaunator; }))); var renderer, scene, camera, controls, loader, terrain, glsl, uniforms, root, tree; renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(0x000000); document.body.appendChild(renderer.domElement); scene = new THREE.Scene(); loader = new THREE.TextureLoader(); loader.crossOrigin = ""; camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 51200); camera.position.set(-3072, 2048, -3072); controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; controls.screenSpacePanning = false; controls.minDistance = 8; controls.maxDistance = 10240; controls.maxPolarAngle = Math.PI / 2; //simple pseudo quadtree var points = [], indices = [], quad_uvs = [], groups = [], materials = []; getSegmentSubpoints(0, new THREE.Vector3(-1024, 0, -1024), 1024, 1024, 4); getSegmentSubpoints(1, new THREE.Vector3(0, 0, -1024), 1024, 1024, 4); getSegmentSubpoints(2, new THREE.Vector3(-1024, 0, 0), 1024, 1024, 4); getSegmentSubpoints(3, new THREE.Vector3(0, 0, 0), 512, 512, 8); getSegmentSubpoints(4, new THREE.Vector3(512, 0, 0), 512, 512, 8); getSegmentSubpoints(5, new THREE.Vector3(0, 0, 512), 512, 512, 8); getSegmentSubpoints(6, new THREE.Vector3(512, 0, 512), 512, 512, 8); var geometry = new THREE.BufferGeometry().setFromPoints(points); geometry.setIndex(indices); geometry.setAttribute( 'uv', new THREE.BufferAttribute(new Float32Array(quad_uvs), 2 ) ); geometry.computeVertexNormals(); var materials = []; var colors = [new THREE.Color(0xe6194b), new THREE.Color(0x3cb44b), new THREE.Color(0xffe119), new THREE.Color(0x4363d8), new THREE.Color(0xf58231), new THREE.Color(0x911eb4), new THREE.Color(0x46f0f0) ] groups.forEach(function(g_, i_){ geometry.addGroup(g_.start, g_.end, g_.id); materials.push(new THREE.MeshBasicMaterial({wireframe: true, color: colors[i_]})) }); var plane = new THREE.Mesh(geometry, materials); plane.rotation.set(Math.PI, 0, 0); plane.position.set(-1152, 0, 0); scene.add(plane); //delaunay materials = []; var geometry = new THREE.BufferGeometry().setFromPoints(points); var indexDelaunay = Delaunator.from(points.map(v => { return [v.x, v.z]; }) ); var meshIndex = []; for (let i = 0; i < indexDelaunay.triangles.length; i++){ meshIndex.push(indexDelaunay.triangles[i]); } geometry.setIndex(meshIndex); geometry.computeVertexNormals(); count = 0; for(var i = 0; i < meshIndex.length; i += 6){ geometry.addGroup(i, 6, i / 6); materials.push(new THREE.MeshBasicMaterial({ wireframe: true, color: new THREE.Color("hsl(" + (360 / 316 * count) + ",80%, 80%)")})) count++; } var plane = new THREE.Mesh(geometry, materials); //new THREE.MeshBasicMaterial({color: 0xFF00FF, side: THREE.DoubleSide, wireframe: true}) ); plane.rotation.set(Math.PI, 0, 0) plane.position.set(1152, 0, 0); scene.add(plane); animate(); function getSegmentSubpoints(id_, lt_, w_, h_, level_){ var subpoints = []; var subindices = []; var subquad = []; var lastIndex = points.length; var lastIndex2 = indices.length; var step = {x: w_ / level_, z: h_ / level_ }; var stepT = {x: 1.0 / level_, z: 1.0 / level_ }; for(var z = 0; z <= level_; z++){ for(var x = 0; x <= level_; x++){ var dx = lt_.x + step.x * x; var dz = lt_.z + step.z * z; var dy = 0; subquad.push(...[stepT.x * x, stepT.z * z]); subpoints.push(new THREE.Vector3(dx, dy, dz)); } } for(var i = 0; i < subpoints.length - level_ - 2; i++) { if(i % (level_ + 1) != (level_)){ subindices.push(lastIndex + i, lastIndex + i + 1, lastIndex + i + level_ + 2, lastIndex + i + level_ + 2, lastIndex + i + level_ + 1, lastIndex + i); } } points.push(...subpoints); indices.push(...subindices); quad_uvs.push(...subquad); groups.push({id: id_, start: lastIndex2, end: subindices.length}); materials.push(new THREE.MeshBasicMaterial({ wireframe: true, map: new THREE.TextureLoader().load("textures/" + id_ + ".jpg")})); } function animate(){ controls.update(); renderer.render(scene, camera); requestAnimationFrame(animate); } body { margin: 0; } <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>GLSL Intersection</title> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://unpkg.com/three#0.116.0/build/three.min.js"></script> <script src="https://unpkg.com/three#0.116.0/examples/js/controls/OrbitControls.js"></script> </head> <body> </body> </html>
Objective C - Get DisplayProductID and DisplayVendorID in MacOS programmatically
Regarding DisplayProductID and DisplayVendorID of Screen (Display), I can get the info from System Information and several commands in Terminal like this; Display Product Name is different with DisplayProductID, It is just String. $ defaults read /Library/Preferences/com.apple.windowserver.plist { DisplayResolutionEnabled = 1; DisplaySets = ( ( { Active = 1; Depth = 4; DisplayID = 69731456; DisplayProductID = 40978; DisplaySerialNumber = 0; DisplayVendorID = 1552; Height = 1080; IODisplayLocation = "IOService:/AppleACPIPlatformExpert/PCI0#0/AppleACPIPCI/P0P2#1/IOPCI2PCIBridge/GFX0#0/NVDA,Display-A#0/NVDA"; IOFlags = 7; LimitsHeight = 1080; LimitsOriginX = 0; LimitsOriginY = 0; LimitsWidth = 1920; MirrorID = 0; Mirrored = 0; Mode = { BitsPerPixel = 32; BitsPerSample = 8; DepthFormat = 4; Height = 1080; IODisplayModeID = "-2147479552"; IOFlags = 7; Mode = 1; PixelEncoding = "--------RRRRRRRRGGGGGGGGBBBBBBBB"; RefreshRate = 0; SamplesPerPixel = 3; UsableForDesktopGUI = 1; Width = 1920; kCGDisplayBytesPerRow = 7680; kCGDisplayHorizontalResolution = 103; kCGDisplayModeIsInterlaced = 0; kCGDisplayModeIsSafeForHardware = 1; kCGDisplayModeIsStretched = 0; kCGDisplayModeIsTelevisionOutput = 0; kCGDisplayModeIsUnavailable = 0; kCGDisplayModeSuitableForUI = 1; kCGDisplayPixelsHigh = 1080; kCGDisplayPixelsWide = 1920; kCGDisplayResolution = 1; kCGDisplayVerticalResolution = 103; }; OriginX = 0; OriginY = 0; PixelEncoding = "--------RRRRRRRRGGGGGGGGBBBBBBBB"; Resolution = 1; Unit = 0; UnmirroredHeight = 1080; UnmirroredLimitsHeight = 1080; UnmirroredLimitsOriginX = 0; UnmirroredLimitsOriginY = 0; UnmirroredLimitsWidth = 1920; UnmirroredMode = { BitsPerPixel = 32; BitsPerSample = 8; DepthFormat = 4; Height = 1080; IODisplayModeID = "-2147479552"; IOFlags = 7; Mode = 1; PixelEncoding = "--------RRRRRRRRGGGGGGGGBBBBBBBB"; RefreshRate = 0; SamplesPerPixel = 3; UsableForDesktopGUI = 1; Width = 1920; kCGDisplayBytesPerRow = 7680; kCGDisplayHorizontalResolution = 103; kCGDisplayModeIsInterlaced = 0; kCGDisplayModeIsSafeForHardware = 1; kCGDisplayModeIsStretched = 0; kCGDisplayModeIsTelevisionOutput = 0; kCGDisplayModeIsUnavailable = 0; kCGDisplayModeSuitableForUI = 1; kCGDisplayPixelsHigh = 1080; kCGDisplayPixelsWide = 1920; kCGDisplayResolution = 1; kCGDisplayVerticalResolution = 103; }; UnmirroredOriginX = 0; UnmirroredOriginY = 0; UnmirroredResolution = 1; UnmirroredWidth = 1920; Width = 1920; } ) ); ForceOldStyleMemoryManagement = 0; } But I want to get this DisplayProductID and DisplayVendorID in MacOS app programmatically (Objective C). How can I read this plist file in Objective-C? This file is encrypted, can't get data. Please let me know the way to get DisplayProductID and VendorID programmatically.
CGDisplayVendorNumber() and CGDisplayModelNumber() should return those values. Use CGMainDisplayID() to get the ID for the main display, or there are other functions to get a list of displays you can filter/iterate over if needed.
encoder/decoder ripping from autoencoder in encog
I have created and learned autoencoder in Encog and I try to rip it into parts: encoder and decoder part. Unfortunately I cannot get it and I keep getting strange improper data (comparing result from applying once net to data and twice data -> enc -> dec). I have tried to make it with simply GetWeight and SetWeight but there result is incorrect. The solution found in encog documentation - initialization flat network is for me not clear (I cannot get it working). public static BasicNetwork getEncoder(BasicNetwork net) { var enc = new BasicNetwork(); enc.AddLayer(new BasicLayer(null, true, net.GetLayerNeuronCount(0))); enc.AddLayer(new BasicLayer(new ActivationSigmoid(), true, net.GetLayerNeuronCount(1))); enc.AddLayer(new BasicLayer(new ActivationSigmoid(), false, net.GetLayerNeuronCount(2))); enc.Structure.FinalizeStructure (); var weights1 = net.Structure.Flat.Weights; var weights2 = enc.Structure.Flat.Weights; var idx1 = net.Structure.Flat.WeightIndex; var idx2 = enc.Structure.Flat.WeightIndex; for(var i = 0; i < 1; i++) { int n = net.GetLayerNeuronCount(i); int m = net.GetLayerNeuronCount(i + 1); Console.WriteLine("Decoder: {0} - {1}", n, m); for(var j = 0; j < n; j++) { for(var k = 0; k < m; k++) { weights1 [idx1[i] + j * m + k] = weights2 [idx2[i] + j * m * k]; } } } return enc; } Full old-like (set/get weight) code of AutoEncoder: using System; using Encog.Engine.Network.Activation; using Encog.ML.Data; using Encog.ML.Data.Basic; using Encog.ML.Train; using Encog.Neural.Networks; using Encog.Neural.Networks.Layers; using Encog.Neural.Networks.Training.Propagation.Resilient; namespace engine { public class AutoEncoder { private int k = 0; public IMLDataSet trainingSet { get; set; } public AutoEncoder(int k) { this.k = k; } public static BasicNetwork getDecoder(BasicNetwork net) { var dec = new BasicNetwork(); dec.AddLayer(new BasicLayer(null, true, net.GetLayerNeuronCount(1))); dec.AddLayer(new BasicLayer(new ActivationSigmoid(), true, net.GetLayerNeuronCount(2))); dec.Structure.FinalizeStructure(); for(var i = 1; i < 2; i++) { int n = net.GetLayerNeuronCount(i); int m = net.GetLayerNeuronCount(i + 1); Console.WriteLine("Decoder: {0} - {1}", n, m); for(var j = 0; j < n; j++) { for(var k = 0; k < m; k++) { dec.SetWeight(i - 1, j, k, net.GetWeight(i, j, k)); } } } return dec; } public static BasicNetwork getEncoder(BasicNetwork net) { var enc = new BasicNetwork(); enc.AddLayer(new BasicLayer(null, true, net.GetLayerNeuronCount(0))); enc.AddLayer(new BasicLayer(new ActivationSigmoid(), true, net.GetLayerNeuronCount(1))); enc.Structure.FinalizeStructure(); for(var i = 0; i < 1; i++) { int n = net.GetLayerNeuronCount(i); int m = net.GetLayerNeuronCount(i + 1); Console.WriteLine("Encoder: {0} - {1}", n, m); for(var j = 0; j < n; j++) { for(var k = 0; k < m; k++) { enc.SetWeight(i, j, k, net.GetWeight(i, j, k)); } } } return enc; } public BasicNetwork learn(double[][] data, double eps = 1e-6, long trainMaxIter = 10000) { int n = data.Length; int m = data[0].Length; double[][] output = new double[n][]; for(var i = 0; i < n; i++) { output[i] = new double[m]; data[i].CopyTo(output[i], 0); } var network = new BasicNetwork(); network.AddLayer(new BasicLayer(null, true, m)); network.AddLayer(new BasicLayer(new ActivationSigmoid(), true, k)); network.AddLayer(new BasicLayer(new ActivationSigmoid(), true, m)); network.Structure.FinalizeStructure(); network.Reset(); trainingSet = new BasicMLDataSet(data, output); IMLTrain train = new ResilientPropagation(network, trainingSet); int epoch = 1; do { train.Iteration(); Console.WriteLine(#"Epoch #" + epoch + #" Error:" + train.Error); epoch++; } while(train.Error > eps && epoch < trainMaxIter); train.FinishTraining(); return network; } } } How can I correctly rip only two first layers from autoencoder for encoder and two last layers from one for decoder?
If you need direct access to the weights, the best method is to use BasicNetwork.GetWeight(). Here is an example that shows how to use GetWeight to obtain all of the weights in the neural network. It is from a unit test, to prove that GetWeight does work, it calculates the output of a simple neural network using BasicNetwork.Compute and also manually just by summing the weighted inputs and applying the TanH. Both result in the same output. More info here too, if you want to access the weight array directly: http://www.heatonresearch.com/wiki/Weight var network = new BasicNetwork(); network.AddLayer(new BasicLayer(null, true, 2)); network.AddLayer(new BasicLayer(new ActivationTANH(), true, 2)); network.AddLayer(new BasicLayer(new ActivationTANH(), false, 1)); network.Structure.FinalizeStructure(); network.Reset(100); BasicMLData input = new BasicMLData(2); input[0] = 0.1; input[1] = 0.2; Console.WriteLine("Using network: " + network.Compute(input)); // now manually double sum1 = (input[0]*network.GetWeight(0, 0, 0)) + (input[1]*network.GetWeight(0, 1, 0)) + (1.0*network.GetWeight(0,2,0)); double sum2 = (input[0]*network.GetWeight(0, 0, 1)) + (input[1]*network.GetWeight(0, 1, 1)) + (1.0*network.GetWeight(0,2,1)); double hidden1 = Math.Tanh(sum1); double hidden2 = Math.Tanh(sum2); double sum3 = (hidden1 * network.GetWeight(1, 0, 0)) + (hidden2 * network.GetWeight(1, 1, 0)) + (1.0 * network.GetWeight(1, 2, 0)); double output = Math.Tanh(sum3); Console.WriteLine("Using manual: " + network.Compute(input));
how to convert modelview matrix to gluLookAt parameters?
I had a requirement in Bullet physics with Opengl where I have modelview matrix but need to get the same matrix by calling gluLookAt. Thanks in advance.
From any 4x4 matrix we can get gluLookAt parameters which are CameraPos, CameraTarget, UpVector. Here is the code to get CameraPos, CameraTarget, UpVector from ModelView matrix. float modelViewMat[16]; glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMat); // Here instead of model view matrix we can pass any 4x4 matrix. float params[9]; GetGluLookAtParameters(modelViewMat, params); CameraPos.x = params[0]; CameraPos.y = params[1]; CameraPos.z = params[2]; CameraTarget.x = params[3]; CameraTarget.y = params[4]; CameraTarget.z = params[5]; UpVector.x = params[6]; UpVector.y = params[7]; UpVector.z = params[8]; void GetGluLookAtParameters(float* m, float* gluLookAtParams) { VECTOR3D sideVector(m[0], m[4], m[8]); VECTOR3D upVector(m[1], m[5], m[9]); VECTOR3D forwardVector(-m[2], -m[6], -m[10]); sideVector.Normalize(); upVector.Normalize(); forwardVector.Normalize(); float rotMat[16]; memcpy(rotMat, m, 16*sizeof(float)); rotMat[12] = rotMat[13] = rotMat[14] = rotMat[3] = rotMat[7] = rotMat[11] = 0.0f; rotMat[15] = 1.0f; float rotInvert[16]; __gluInvertMatrixd(rotMat, rotInvert); float transMat[16]; memset(transMat, 0, 16*sizeof(float)); transMat[0] = transMat[5] = transMat[10] = transMat[15] = 1.0f; MultMat(rotInvert, m, transMat); gluLookAtParams[0] = -transMat[12]; gluLookAtParams[1] = -transMat[13]; gluLookAtParams[2] = -transMat[14]; gluLookAtParams[3] = -transMat[12] + forwardVector.x; gluLookAtParams[4] = -transMat[13] + forwardVector.y; gluLookAtParams[5] = -transMat[14] + forwardVector.z; gluLookAtParams[6] = upVector.x; gluLookAtParams[7] = upVector.y; gluLookAtParams[8] = upVector.z; } void MultMat(float* a, float* b, float* result) { result[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; result[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; result[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3]; result[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3]; result[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7]; result[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7]; result[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7]; result[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7]; result[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11]; result[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11]; result[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11]; result[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11]; result[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15]; result[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15]; result[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15]; result[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; } int __gluInvertMatrixd(const float src[16], float inverse[16]) { int i, j, k, swap; float t; GLfloat temp[4][4]; for (i=0; i<4; i++) for (j=0; j<4; j++) temp[i][j] = src[i*4+j]; for(int i=0;i<16;i++) inverse[i] = 0; inverse[0] = inverse[5] = inverse[10] = inverse[15] = 1.0f; for(i=0; i<4; i++) { swap = i; for (j = i + 1; j < 4; j++) if (fabs(temp[j][i]) > fabs(temp[i][i])) swap = j; if (swap != i) { //Swap rows. for (k = 0; k < 4; k++) { t = temp[i][k]; temp[i][k] = temp[swap][k]; temp[swap][k] = t; t = inverse[i*4+k]; inverse[i*4+k] = inverse[swap*4+k]; inverse[swap*4+k] = t; } } if (temp[i][i] == 0) return 0; t = temp[i][i]; for (k = 0; k < 4; k++) { temp[i][k] /= t; inverse[i*4+k] /= t; } for (j = 0; j < 4; j++) { if (j != i) { t = temp[j][i]; for (k = 0; k < 4; k++) { temp[j][k] -= temp[i][k]*t; inverse[j*4+k] -= inverse[i*4+k]*t; } } } } return 1; }