light position debug pipeline, keyboard camera movement

This commit is contained in:
Zack Buhman 2026-07-26 19:15:25 -05:00
parent ed2160a935
commit 4526aaa2c5
19 changed files with 7695 additions and 1189 deletions

View File

@ -79,7 +79,7 @@ fn lighting(position: vec3f, normal: vec3f) -> vec3f
{ {
let d = 0.9; let d = 0.9;
let eyePosition = vec3f(d, d / 2, d); let eyePosition = vec3f(d, d / 2, d);
let lightPosition = vec3f(1, 1, 1); let lightPosition = vec3f(100, 100, 100);
let lightVector = normalize(lightPosition - position); let lightVector = normalize(lightPosition - position);
let ndotl = max(dot(lightVector, normal), 0.0); let ndotl = max(dot(lightVector, normal), 0.0);
let intensity = (ndotl + 0.3) / 1.3; let intensity = (ndotl + 0.3) / 1.3;
@ -95,5 +95,5 @@ fn fragmentMain(input: FragmentInput) -> @location(0) vec4f
let intensity = lighting(input.positionWorld, normalize(input.normal)); let intensity = lighting(input.positionWorld, normalize(input.normal));
let color = textureSample(colorTexture, linearSampler, input.texture); let color = textureSample(colorTexture, linearSampler, input.texture);
return vec4(color.xyz, 1.0); return vec4(color.xyz * intensity, 1.0);
} }

143
index.js
View File

@ -1,5 +1,6 @@
import { getPath } from "./common.js"; import { getPath } from "./common.js";
import { loadGltf } from "./index2.js"; import { loadGltf } from "./index2.js";
import { loadLight } from "./light.js";
if (!navigator.gpu) { if (!navigator.gpu) {
throw new Error("WebGPU not supported on this browser."); throw new Error("WebGPU not supported on this browser.");
@ -441,18 +442,150 @@ function render()
} }
//requestAnimationFrame(render); //requestAnimationFrame(render);
const gltfRenderer = await loadGltf(device, canvasFormat, memory2, module); const matrixSize = 4 * 4 * 4;
const float4Size = 4 * 4;
const float3Size = 4 * 3;
const viewUniformBufferSize = (matrixSize * 2) + (float4Size * 1);
const viewUniformBuffer = device.createBuffer({
label: "view uniform buffer",
size: viewUniformBufferSize,
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
});
const cameraStateSize = (float3Size * 3) + (4 * 3) + (float3Size * 1);
const viewStateAddress = module.instance.exports.mem_alloc(viewUniformBufferSize);
const cameraStateAddress = module.instance.exports.mem_alloc(cameraStateSize);
module.instance.exports.camera_init(cameraStateAddress);
const gltfRenderer = await loadGltf(device, canvasFormat, viewUniformBuffer, memory2, module);
const lightRenderer = await loadLight(device, canvasFormat, viewUniformBuffer);
const KEY = {
A: 65,
B: 66,
C: 67,
D: 68,
E: 69,
F: 70,
G: 71,
H: 72,
I: 73,
J: 74,
K: 75,
L: 76,
M: 77,
N: 78,
O: 79,
P: 80,
Q: 81,
R: 82,
S: 83,
T: 84,
U: 85,
V: 86,
W: 87,
X: 88,
Y: 89,
Z: 90,
Left: 37,
Up: 38,
Right: 39,
Down: 40,
};
const keyCodes = new Set(Object.values(KEY));
const keyState = {};
for (const code of Object.values(KEY)) {
keyState[code] = false;
}
function handleKeydown(e)
{
//console.log(e.keyCode);
if (keyCodes.has(e.keyCode)) {
keyState[e.keyCode] = true;
}
}
function handleKeyup(e)
{
if (keyCodes.has(e.keyCode)) {
keyState[e.keyCode] = false;
}
}
window.addEventListener('keydown', handleKeydown, false);
window.addEventListener('keyup', handleKeyup, false);
function updateView()
{
const lu = keyState[KEY.W] === true;
const ll = keyState[KEY.A] === true;
const ld = keyState[KEY.S] === true;
const lr = keyState[KEY.D] === true;
const lal = keyState[KEY.Q] === true;
const lar = keyState[KEY.E] === true;
const ru = keyState[KEY.Up] === true;
const rl = keyState[KEY.Left] === true;
const rd = keyState[KEY.Down] === true;
const rr = keyState[KEY.Right] === true;
module.instance.exports.camera_move(cameraStateAddress,
lu, ll, ld, lr,
lal, lar,
ru, rl, rd, rr);
const aspect = canvas.width / canvas.height;
module.instance.exports.camera_view_projection(cameraStateAddress,
viewStateAddress,
aspect);
device.queue.writeBuffer(viewUniformBuffer, 0,
memory2.buffer, viewStateAddress,
viewUniformBufferSize);
}
function render2() function render2()
{ {
recreateDepth(); recreateDepth();
const colorView = context.getCurrentTexture().createView(); const colorView = context.getCurrentTexture().createView();
const aspect = canvas.width / canvas.height; updateView();
rotate.instance.exports.rotate(tick * 0.01, aspect, 0);
device.queue.writeBuffer(gltfRenderer.uniformBuffer, 0, uniformArray, 0, gltfRenderer.uniformBufferSize / 4); {
const encoder = device.createCommandEncoder();
const renderPass = encoder.beginRenderPass({
colorAttachments: [{
view: colorView,
loadOp: "clear",
clearValue: { r: 0.2, g: 0.2, b: 0.4, a: 1 },
storeOp: "store",
}],
depthStencilAttachment: {
view: depthTexture.createView(),
depthClearValue: 1.0,
depthLoadOp: 'clear',
depthStoreOp: 'store',
},
});
gltfRenderer.render(renderPass);
lightRenderer.render(renderPass);
renderPass.end();
const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);
}
gltfRenderer.render(device, colorView, depthTexture);
requestAnimationFrame(render2); requestAnimationFrame(render2);
} }
requestAnimationFrame(render2); requestAnimationFrame(render2);

View File

@ -1,7 +1,6 @@
import { getPath } from "./common.js"; import { getPath } from "./common.js";
import { parseGltfChunks, vertexBufferLayouts, primitiveAccessors, splitGltf } from "./gltf.js"; import { parseGltfChunks, vertexBufferLayouts, primitiveAccessors, splitGltf } from "./gltf.js";
function loadGltfNode(module, handle, gltf, nodeIndex) function loadGltfNode(module, handle, gltf, nodeIndex)
{ {
const node = gltf.json.nodes[nodeIndex]; const node = gltf.json.nodes[nodeIndex];
@ -37,7 +36,7 @@ function printMatrix(m, o)
} }
class GltfRenderer { class GltfRenderer {
constructor(device, canvasFormat, shaderModule, gltf, texture) constructor(device, canvasFormat, viewUniformBuffer, shaderModule, gltf, texture)
{ {
this.gltf = gltf; this.gltf = gltf;
@ -153,13 +152,6 @@ class GltfRenderer {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
const matrixSize = 4 * 4 * 4; const matrixSize = 4 * 4 * 4;
this.uniformBufferSize = matrixSize * 2;
this.uniformBuffer = device.createBuffer({
label: "gltf uniform 0",
size: this.uniformBufferSize,
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
});
this.nodeBufferSize = matrixSize * this.gltf.json.nodes.length; this.nodeBufferSize = matrixSize * this.gltf.json.nodes.length;
this.nodeBuffer = device.createBuffer({ this.nodeBuffer = device.createBuffer({
label: "gltf node buffer", label: "gltf node buffer",
@ -173,7 +165,7 @@ class GltfRenderer {
layout: bindGroupLayouts[0], layout: bindGroupLayouts[0],
entries: [{ entries: [{
binding: 0, binding: 0,
resource: { buffer: this.uniformBuffer }, resource: { buffer: viewUniformBuffer },
}, { }, {
binding: 1, binding: 1,
resource: { buffer: this.nodeBuffer }, resource: { buffer: this.nodeBuffer },
@ -235,33 +227,12 @@ class GltfRenderer {
return lastKey; return lastKey;
} }
render(device, colorView, depthTexture) render(renderPass)
{ {
const encoder = device.createCommandEncoder();
const renderPass = encoder.beginRenderPass({
colorAttachments: [{
view: colorView,
loadOp: "clear",
clearValue: { r: 0.2, g: 0.2, b: 0.4, a: 1 },
storeOp: "store",
}],
depthStencilAttachment: {
view: depthTexture.createView(),
depthClearValue: 1.0,
depthLoadOp: 'clear',
depthStoreOp: 'store',
},
});
var lastKey = undefined; var lastKey = undefined;
for (let nodeIndex of this.gltf.json.scenes[0].nodes) { for (let nodeIndex of this.gltf.json.scenes[0].nodes) {
lastKey = this.renderNode(renderPass, lastKey, nodeIndex); lastKey = this.renderNode(renderPass, lastKey, nodeIndex);
} }
renderPass.end();
const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);
} }
} }
@ -333,8 +304,14 @@ async function loadTextures(device, memory, module, gltf)
return textures; return textures;
} }
async function loadGltf(device, canvasFormat, memory, module) async function loadGltf(device, canvasFormat, viewUniformBuffer, memory, module)
{ {
const code = await getPath("gltf.wgsl");
const shaderModule = device.createShaderModule({
label: "gltf module",
code: await code,
});
const gltf = await splitGltf("gltf/lamp.gltf", "gltf/lamp.bin"); const gltf = await splitGltf("gltf/lamp.gltf", "gltf/lamp.bin");
const nodesHandle = loadGltfNodes(module, gltf); const nodesHandle = loadGltfNodes(module, gltf);
@ -348,13 +325,7 @@ async function loadGltf(device, canvasFormat, memory, module)
const textures = await loadTextures(device, memory, module, gltf); const textures = await loadTextures(device, memory, module, gltf);
const code = await getPath("gltf.wgsl"); const renderer = new GltfRenderer(device, canvasFormat, viewUniformBuffer, shaderModule, gltf, textures[2]);
const shaderModule = device.createShaderModule({
label: "gltf module",
code: await code,
});
const renderer = new GltfRenderer(device, canvasFormat, shaderModule, gltf, textures[0]);
console.log(renderer.nodeBuffer); console.log(renderer.nodeBuffer);
device.queue.writeBuffer(renderer.nodeBuffer, 0, device.queue.writeBuffer(renderer.nodeBuffer, 0,
memory.buffer, nodesHandle, (4 * 4 * 4) * gltf.json.nodes.length); memory.buffer, nodesHandle, (4 * 4 * 4) * gltf.json.nodes.length);

160
light.js Normal file
View File

@ -0,0 +1,160 @@
import { getPath } from "./common.js";
function parseHeader(buffer)
{
const array = new Uint32Array(buffer);
/*
console.log("index count", icosphereU32[0]);
console.log("index buffer offset", icosphereU32[1]);
console.log("index buffer size", icosphereU32[2]);
console.log("vertex buffer offset", icosphereU32[3]);
console.log("vertex buffer size", icosphereU32[4]);
*/
return {
indexCount: array[0],
indexOffset: array[1],
indexSize: array[2],
vertexOffset: array[3],
vertexSize: array[4],
};
}
class LightRenderer {
constructor(device, canvasFormat, viewUniformBuffer,
shaderModule, binBuffer, label)
{
//////////////////////////////////////////////////////////////////////
// buffer
//////////////////////////////////////////////////////////////////////
const header = parseHeader(binBuffer);
this.header = header;
this.buffer = device.createBuffer({
label: `${label} renderer buffer`,
size: header.indexSize + header.vertexSize,
usage: GPUBufferUsage.INDEX | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});
this.indexOffset = 0;
this.vertexOffset = header.indexSize;
device.queue.writeBuffer(this.buffer, this.indexOffset,
binBuffer, header.indexOffset, header.indexSize);
device.queue.writeBuffer(this.buffer, this.vertexOffset,
binBuffer, header.vertexOffset, header.vertexSize);
//////////////////////////////////////////////////////////////////////
// pipeline
//////////////////////////////////////////////////////////////////////
const bindGroupLayouts = [
device.createBindGroupLayout({
label: `${label} view matrix bind group layout`,
entries: [{
binding: 0,
visibility: GPUShaderStage.VERTEX,
buffer: { type: "uniform" }
},/* {
binding: 1,
visibility: GPUShaderStage.VERTEX,
buffer: { type: "read-only-storage" }
}*/]
}),
];
const pipelineLayout = device.createPipelineLayout({
label: `${label} pipeline layout`,
bindGroupLayouts: bindGroupLayouts,
});
const vertexBufferLayouts = [{
arrayStride: 36,
attributes: [{
format: "float32x3",
offset: 0,
shaderLocation: 0,
}, {
format: "float32x2",
offset: 12,
shaderLocation: 1,
}, {
format: "float16x4",
offset: 20,
shaderLocation: 2,
}, {
format: "float16x4",
offset: 28,
shaderLocation: 3,
}],
stepMode: "vertex",
}];
this.renderPipeline = device.createRenderPipeline({
label: `${label} pipeline`,
layout: pipelineLayout,
vertex: {
module: shaderModule,
entryPoint: "vertexMain",
buffers: vertexBufferLayouts,
},
fragment: {
module: shaderModule,
entryPoint: "fragmentMain",
targets: [{
format: canvasFormat,
}]
},
primitive: {
topology: "triangle-list",
},
depthStencil: {
depthWriteEnabled: true,
depthCompare: "less",
format: "depth24plus",
},
});
//////////////////////////////////////////////////////////////////////
// bind group
//////////////////////////////////////////////////////////////////////
this.bindGroups = [
device.createBindGroup({
label: `${label} bind group`,
layout: bindGroupLayouts[0],
entries: [{
binding: 0,
resource: { buffer: viewUniformBuffer },
}],
}),
];
}
render(renderPass)
{
renderPass.setPipeline(this.renderPipeline);
renderPass.setVertexBuffer(0, this.buffer, this.vertexOffset, this.header.vertexSize);
renderPass.setIndexBuffer(this.buffer, "uint16", this.indexOffset, this.header.indexSize);
renderPass.setBindGroup(0, this.bindGroups[0]);
renderPass.drawIndexed(this.header.indexCount);
}
}
async function loadLight(device, canvasFormat, viewUniformBuffer)
{
const lightWgsl = getPath("light.wgsl");
const shaderModule = device.createShaderModule({
label: "light shader",
code: await lightWgsl,
});
const response = await fetch("obj/icosphere.bin");
const binBuffer = await response.arrayBuffer();
const renderer = new LightRenderer(device, canvasFormat, viewUniformBuffer,
shaderModule, binBuffer, "light");
return renderer;
}
export { loadLight };

35
light.wgsl Normal file
View File

@ -0,0 +1,35 @@
struct Configuration {
matrix: mat4x4f,
matrixWorld: mat4x4f,
};
@group(0) @binding(0) var<uniform> config: Configuration;
struct VertexInput {
@location(0) position: vec3f,
@location(1) texture: vec2f,
@location(2) normal: vec4f,
@location(3) tangent: vec4f,
};
struct VertexOutput {
@builtin(position) position: vec4f,
@location(0) texture: vec2f,
};
@vertex
fn vertexMain(input: VertexInput) -> VertexOutput
{
let position = vec4f(input.position, 1);
var output: VertexOutput;
output.position = config.matrix * position;
output.texture = input.texture;
return output;
}
@fragment
fn fragmentMain(input: VertexOutput) -> @location(0) vec4f
{
return vec4(1, 0, 0, 1.0);
}

BIN
obj/icosphere.bin Normal file

Binary file not shown.

269
obj/icosphere.obj Normal file
View File

@ -0,0 +1,269 @@
# Blender 5.2.0 LTS
# www.blender.org
o Icosphere
v 0.000000 -1.000000 0.000000
v 0.723607 -0.447220 0.525725
v -0.276388 -0.447220 0.850649
v -0.894426 -0.447216 0.000000
v -0.276388 -0.447220 -0.850649
v 0.723607 -0.447220 -0.525725
v 0.276388 0.447220 0.850649
v -0.723607 0.447220 0.525725
v -0.723607 0.447220 -0.525725
v 0.276388 0.447220 -0.850649
v 0.894426 0.447216 0.000000
v 0.000000 1.000000 0.000000
v -0.162456 -0.850654 0.499995
v 0.425323 -0.850654 0.309011
v 0.262869 -0.525738 0.809012
v 0.850648 -0.525736 0.000000
v 0.425323 -0.850654 -0.309011
v -0.525730 -0.850652 0.000000
v -0.688189 -0.525736 0.499997
v -0.162456 -0.850654 -0.499995
v -0.688189 -0.525736 -0.499997
v 0.262869 -0.525738 -0.809012
v 0.951058 0.000000 0.309013
v 0.951058 0.000000 -0.309013
v 0.000000 0.000000 1.000000
v 0.587786 0.000000 0.809017
v -0.951058 0.000000 0.309013
v -0.587786 0.000000 0.809017
v -0.587786 0.000000 -0.809017
v -0.951058 0.000000 -0.309013
v 0.587786 0.000000 -0.809017
v 0.000000 0.000000 -1.000000
v 0.688189 0.525736 0.499997
v -0.262869 0.525738 0.809012
v -0.850648 0.525736 0.000000
v -0.262869 0.525738 -0.809012
v 0.688189 0.525736 -0.499997
v 0.162456 0.850654 0.499995
v 0.525730 0.850652 0.000000
v -0.425323 0.850654 0.309011
v -0.425323 0.850654 -0.309011
v 0.162456 0.850654 -0.499995
vn 0.1024 -0.9435 0.3151
vn 0.7002 -0.6617 0.2680
vn -0.2680 -0.9435 0.1947
vn -0.2680 -0.9435 -0.1947
vn 0.1024 -0.9435 -0.3151
vn 0.9050 -0.3304 0.2680
vn 0.0247 -0.3304 0.9435
vn -0.8897 -0.3304 0.3151
vn -0.5746 -0.3304 -0.7488
vn 0.5346 -0.3304 -0.7779
vn 0.8026 -0.1256 0.5831
vn -0.3066 -0.1256 0.9435
vn -0.9921 -0.1256 -0.0000
vn -0.3066 -0.1256 -0.9435
vn 0.8026 -0.1256 -0.5831
vn 0.4089 0.6617 0.6284
vn -0.4713 0.6617 0.5831
vn -0.7002 0.6617 -0.2680
vn 0.0385 0.6617 -0.7488
vn 0.7240 0.6617 -0.1947
vn 0.2680 0.9435 -0.1947
vn 0.4911 0.7947 -0.3568
vn 0.4089 0.6617 -0.6284
vn -0.1024 0.9435 -0.3151
vn -0.1876 0.7947 -0.5773
vn -0.4713 0.6617 -0.5831
vn -0.3313 0.9435 -0.0000
vn -0.6071 0.7947 -0.0000
vn -0.7002 0.6617 0.2680
vn -0.1024 0.9435 0.3151
vn -0.1876 0.7947 0.5773
vn 0.0385 0.6617 0.7488
vn 0.2680 0.9435 0.1947
vn 0.4911 0.7947 0.3568
vn 0.7240 0.6617 0.1947
vn 0.8897 0.3304 -0.3151
vn 0.7947 0.1876 -0.5773
vn 0.5746 0.3304 -0.7488
vn -0.0247 0.3304 -0.9435
vn -0.3035 0.1876 -0.9342
vn -0.5346 0.3304 -0.7779
vn -0.9050 0.3304 -0.2680
vn -0.9822 0.1876 -0.0000
vn -0.9050 0.3304 0.2680
vn -0.5346 0.3304 0.7779
vn -0.3035 0.1876 0.9342
vn -0.0247 0.3304 0.9435
vn 0.5746 0.3304 0.7488
vn 0.7947 0.1876 0.5773
vn 0.8897 0.3304 0.3151
vn 0.3066 0.1256 -0.9435
vn 0.3035 -0.1876 -0.9342
vn 0.0247 -0.3304 -0.9435
vn -0.8026 0.1256 -0.5831
vn -0.7947 -0.1876 -0.5773
vn -0.8897 -0.3304 -0.3151
vn -0.8026 0.1256 0.5831
vn -0.7947 -0.1876 0.5773
vn -0.5746 -0.3304 0.7488
vn 0.3066 0.1256 0.9435
vn 0.3035 -0.1876 0.9342
vn 0.5346 -0.3304 0.7779
vn 0.9921 0.1256 -0.0000
vn 0.9822 -0.1876 -0.0000
vn 0.9050 -0.3304 -0.2680
vn 0.4713 -0.6617 -0.5831
vn 0.1876 -0.7947 -0.5773
vn -0.0385 -0.6617 -0.7488
vn -0.4089 -0.6617 -0.6284
vn -0.4911 -0.7947 -0.3568
vn -0.7240 -0.6617 -0.1947
vn -0.7240 -0.6617 0.1947
vn -0.4911 -0.7947 0.3568
vn -0.4089 -0.6617 0.6284
vn 0.7002 -0.6617 -0.2680
vn 0.6071 -0.7947 -0.0000
vn 0.3313 -0.9435 -0.0000
vn -0.0385 -0.6617 0.7488
vn 0.1876 -0.7947 0.5773
vn 0.4713 -0.6617 0.5831
vt 0.181819 0.000000
vt 0.227273 0.078731
vt 0.136365 0.078731
vt 0.272728 0.157461
vt 0.318182 0.078731
vt 0.363637 0.157461
vt 0.909091 0.000000
vt 0.954545 0.078731
vt 0.863636 0.078731
vt 0.727273 0.000000
vt 0.772727 0.078731
vt 0.681818 0.078731
vt 0.545455 0.000000
vt 0.590909 0.078731
vt 0.500000 0.078731
vt 0.318182 0.236191
vt 0.090910 0.157461
vt 0.181819 0.157461
vt 0.136365 0.236191
vt 0.818182 0.157461
vt 0.909091 0.157461
vt 0.863636 0.236191
vt 0.636364 0.157461
vt 0.727273 0.157461
vt 0.681818 0.236191
vt 0.454546 0.157461
vt 0.545455 0.157461
vt 0.500000 0.236191
vt 0.227273 0.236191
vt 0.045455 0.236191
vt 0.772727 0.236191
vt 0.590909 0.236191
vt 0.409092 0.236191
vt 0.181819 0.314921
vt 0.272728 0.314921
vt 0.227273 0.393651
vt 0.000000 0.314921
vt 0.090910 0.314921
vt 0.045455 0.393651
vt 0.727273 0.314921
vt 0.818182 0.314921
vt 0.772727 0.393651
vt 0.545455 0.314921
vt 0.636364 0.314921
vt 0.590909 0.393651
vt 0.363637 0.314921
vt 0.454546 0.314921
vt 0.409092 0.393651
vt 0.500000 0.393651
vt 0.454546 0.472382
vt 0.681818 0.393651
vt 0.636364 0.472382
vt 0.863636 0.393651
vt 0.818182 0.472382
vt 0.909091 0.314921
vt 0.136365 0.393651
vt 0.090910 0.472382
vt 0.318182 0.393651
vt 0.272728 0.472382
vt 0.954545 0.236191
vt 1.000000 0.157461
vt 0.409092 0.078731
vt 0.363637 0.000000
s 0
f 1/1/1 14/2/1 13/3/1
f 2/4/2 14/5/2 16/6/2
f 1/7/3 13/8/3 18/9/3
f 1/10/4 18/11/4 20/12/4
f 1/13/5 20/14/5 17/15/5
f 2/4/6 16/6/6 23/16/6
f 3/17/7 15/18/7 25/19/7
f 4/20/8 19/21/8 27/22/8
f 5/23/9 21/24/9 29/25/9
f 6/26/10 22/27/10 31/28/10
f 2/4/11 23/16/11 26/29/11
f 3/17/12 25/19/12 28/30/12
f 4/20/13 27/22/13 30/31/13
f 5/23/14 29/25/14 32/32/14
f 6/26/15 31/28/15 24/33/15
f 7/34/16 33/35/16 38/36/16
f 8/37/17 34/38/17 40/39/17
f 9/40/18 35/41/18 41/42/18
f 10/43/19 36/44/19 42/45/19
f 11/46/20 37/47/20 39/48/20
f 39/48/21 42/49/21 12/50/21
f 39/48/22 37/47/22 42/49/22
f 37/47/23 10/43/23 42/49/23
f 42/45/24 41/51/24 12/52/24
f 42/45/25 36/44/25 41/51/25
f 36/44/26 9/40/26 41/51/26
f 41/42/27 40/53/27 12/54/27
f 41/42/28 35/41/28 40/53/28
f 35/41/29 8/55/29 40/53/29
f 40/39/30 38/56/30 12/57/30
f 40/39/31 34/38/31 38/56/31
f 34/38/32 7/34/32 38/56/32
f 38/36/33 39/58/33 12/59/33
f 38/36/34 33/35/34 39/58/34
f 33/35/35 11/46/35 39/58/35
f 24/33/36 37/47/36 11/46/36
f 24/33/37 31/28/37 37/47/37
f 31/28/38 10/43/38 37/47/38
f 32/32/39 36/44/39 10/43/39
f 32/32/40 29/25/40 36/44/40
f 29/25/41 9/40/41 36/44/41
f 30/31/42 35/41/42 9/40/42
f 30/31/43 27/22/43 35/41/43
f 27/22/44 8/55/44 35/41/44
f 28/30/45 34/38/45 8/37/45
f 28/30/46 25/19/46 34/38/46
f 25/19/47 7/34/47 34/38/47
f 26/29/48 33/35/48 7/34/48
f 26/29/49 23/16/49 33/35/49
f 23/16/50 11/46/50 33/35/50
f 31/28/51 32/32/51 10/43/51
f 31/28/52 22/27/52 32/32/52
f 22/27/53 5/23/53 32/32/53
f 29/25/54 30/31/54 9/40/54
f 29/25/55 21/24/55 30/31/55
f 21/24/56 4/20/56 30/31/56
f 27/22/57 28/60/57 8/55/57
f 27/22/58 19/21/58 28/60/58
f 19/21/59 3/61/59 28/60/59
f 25/19/60 26/29/60 7/34/60
f 25/19/61 15/18/61 26/29/61
f 15/18/62 2/4/62 26/29/62
f 23/16/63 24/33/63 11/46/63
f 23/16/64 16/6/64 24/33/64
f 16/6/65 6/26/65 24/33/65
f 17/15/66 22/27/66 6/26/66
f 17/15/67 20/14/67 22/27/67
f 20/14/68 5/23/68 22/27/68
f 20/12/69 21/24/69 5/23/69
f 20/12/70 18/11/70 21/24/70
f 18/11/71 4/20/71 21/24/71
f 18/9/72 19/21/72 4/20/72
f 18/9/73 13/8/73 19/21/73
f 13/8/74 3/61/74 19/21/74
f 16/6/75 17/62/75 6/26/75
f 16/6/76 14/5/76 17/62/76
f 14/5/77 1/63/77 17/62/77
f 13/3/78 15/18/78 3/17/78
f 13/3/79 14/2/79 15/18/79
f 14/2/80 2/4/80 15/18/80

View File

@ -5,9 +5,9 @@ CFLAGS = \
-g \ -g \
-O3 \ -O3 \
-flto \ -flto \
-ffast-math \
-nostdlib \ -nostdlib \
-I$(MINIZ) \ -I$(MINIZ) \
-I.. \
-I. \ -I. \
-Werror \ -Werror \
-Wfatal-errors \ -Wfatal-errors \
@ -29,6 +29,9 @@ LDFLAGS = \
-Wl,--export=node_init_translation \ -Wl,--export=node_init_translation \
-Wl,--export=png_build_crc_table \ -Wl,--export=png_build_crc_table \
-Wl,--export=png_decode \ -Wl,--export=png_decode \
-Wl,--export=camera_move \
-Wl,--export=camera_init \
-Wl,--export=camera_view_projection \
-Wl,--import-undefined \ -Wl,--import-undefined \
-Wl,--print-map \ -Wl,--print-map \
-Wl,--import-memory \ -Wl,--import-memory \
@ -45,7 +48,8 @@ PNG_OBJ = \
stdlib.o \ stdlib.o \
$(MINIZ)/miniz_tinfl.o \ $(MINIZ)/miniz_tinfl.o \
memory.o \ memory.o \
node.o node.o \
camera.o
module.wasm: $(PNG_OBJ) module.wasm: $(PNG_OBJ)
clang++ $(CFLAGS) $(LDFLAGS) -o $@ $^ clang++ $(CFLAGS) $(LDFLAGS) -o $@ $^

138
src/camera.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "directxmath/DirectXMath.h"
#include "camera.h"
struct CameraState {
XMFLOAT3 eye;
XMFLOAT3 look;
XMFLOAT3 up;
float fov;
float pitch;
float yaw;
XMFLOAT3 light_position;
};
struct ViewState {
XMFLOAT4X4 viewProj;
XMFLOAT4X4 lightViewProj;
XMFLOAT4 lightPosition;
};
static inline XMMATRIX camera_view(CameraState const * state)
{
XMMATRIX view = XMMatrixLookToRH(XMLoadFloat3(&state->eye),
XMLoadFloat3(&state->look),
XMLoadFloat3(&state->up));
return view;
}
static inline XMMATRIX camera_projection(CameraState const * state, float aspect)
{
float near_z = 0.01;
float far_z = 1000.0;
XMMATRIX projection = XMMatrixPerspectiveFovRH(state->fov,
aspect,
near_z,
far_z);
return projection;
};
extern "C" void log(float x);
static inline float min(float a, float b)
{
return a < b ? a : b;
}
static inline float max(float a, float b)
{
return a > b ? a : b;
}
void camera_move(CameraState * state,
int lu, int ll, int ld, int lr,
int lal, int lar,
int ru, int rl, int rd, int rr)
{
const float linearSpeed = 0.1;
const float rotationalSpeed = 0.01;
XMFLOAT3 move = {0, 0, 0};
if (ll)
move.x -= 1.0;
if (lr)
move.x += 1.0;
if (lu)
move.z -= 1.0;
if (ld)
move.z += 1.0;
if (lal)
move.y += 1.0;
if (lar)
move.y -= 1.0;
//XMStoreFloat3(&move, XMVector3Normalize(XMLoadFloat3(&move)));
if (rl)
state->yaw += rotationalSpeed;
if (rr)
state->yaw -= rotationalSpeed;
if (ru)
state->pitch += rotationalSpeed;
if (rd)
state->pitch -= rotationalSpeed;
state->pitch = min(state->pitch, XM_PIDIV4);
state->pitch = max(state->pitch, -XM_PIDIV4);
float sinyaw;
float cosyaw;
XMScalarSinCos(&sinyaw, &cosyaw, state->yaw);
// eye
float x = move.x * -cosyaw - move.z * sinyaw;
float y = move.y;
float z = move.x * sinyaw - move.z * cosyaw;
state->eye.x += x * linearSpeed;
state->eye.y += y * linearSpeed;
state->eye.z += z * linearSpeed;
// look
float sinpitch;
float cospitch;
XMScalarSinCos(&sinpitch, &cospitch, state->pitch);
state->look.x = cospitch * sinyaw;
state->look.y = sinpitch;
state->look.z = cospitch * cosyaw;
}
void camera_init(CameraState * camera_state)
{
camera_state->fov = XMConvertToRadians(45 * 1.5);
camera_state->yaw = XM_PI;
camera_state->pitch = 0.0f;
camera_state->up = {0, 1, 0};
camera_state->look = {0, 0, -1};
camera_state->eye = {0, 0, 5};
camera_state->light_position = {1, 1, 1};
}
void camera_view_projection(CameraState const * camera_state,
ViewState * view_state,
float aspect)
{
XMMATRIX view = camera_view(camera_state);
XMMATRIX projection = camera_projection(camera_state, aspect);
XMMATRIX view_projection = view * projection;
XMMATRIX light_world = XMMatrixTranslationFromVector(XMLoadFloat3(&camera_state->light_position));
XMStoreFloat4x4(&view_state->viewProj, view_projection);
XMStoreFloat4x4(&view_state->lightViewProj, light_world * view_projection);
XMStoreFloat4(&view_state->lightPosition, XMLoadFloat3(&camera_state->light_position));
}

13
src/camera.h Normal file
View File

@ -0,0 +1,13 @@
struct CameraState;
struct ViewState;
extern "C" {
void camera_move(CameraState * camera_state,
int lu, int ll, int ld, int lr,
int lal, int lar,
int ru, int rl, int rd, int rr);
void camera_init(CameraState * camera_state);
void camera_view_projection(CameraState const * camera_state,
ViewState * view_state,
float aspect);
};

View File

@ -0,0 +1,369 @@
//-------------------------------------------------------------------------------------
// DirectXCollision.h -- C++ Collision Math library
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
// https://go.microsoft.com/fwlink/?LinkID=615560
//-------------------------------------------------------------------------------------
#pragma once
#include "DirectXMath.h"
namespace DirectX
{
enum ContainmentType
{
DISJOINT = 0,
INTERSECTS = 1,
CONTAINS = 2
};
enum PlaneIntersectionType
{
FRONT = 0,
INTERSECTING = 1,
BACK = 2
};
struct BoundingBox;
struct BoundingOrientedBox;
struct BoundingFrustum;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4324 4820)
// C4324: alignment padding warnings
// C4820: Off by default noise
#endif
//-------------------------------------------------------------------------------------
// Bounding sphere
//-------------------------------------------------------------------------------------
struct BoundingSphere
{
XMFLOAT3 Center; // Center of the sphere.
float Radius; // Radius of the sphere.
// Creators
BoundingSphere() noexcept : Center(0, 0, 0), Radius(1.f) {}
BoundingSphere(const BoundingSphere&) = default;
BoundingSphere& operator=(const BoundingSphere&) = default;
BoundingSphere(BoundingSphere&&) = default;
BoundingSphere& operator=(BoundingSphere&&) = default;
constexpr BoundingSphere(_In_ const XMFLOAT3& center, _In_ float radius) noexcept
: Center(center), Radius(radius) {}
// Methods
void XM_CALLCONV Transform(_Out_ BoundingSphere& Out, _In_ FXMMATRIX M) const noexcept;
void XM_CALLCONV Transform(_Out_ BoundingSphere& Out, _In_ float Scale, _In_ FXMVECTOR Rotation, _In_ FXMVECTOR Translation) const noexcept;
// Transform the sphere
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR Point) const noexcept;
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
ContainmentType Contains(_In_ const BoundingSphere& sh) const noexcept;
ContainmentType Contains(_In_ const BoundingBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingOrientedBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingFrustum& fr) const noexcept;
bool Intersects(_In_ const BoundingSphere& sh) const noexcept;
bool Intersects(_In_ const BoundingBox& box) const noexcept;
bool Intersects(_In_ const BoundingOrientedBox& box) const noexcept;
bool Intersects(_In_ const BoundingFrustum& fr) const noexcept;
bool XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
// Triangle-sphere test
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR Plane) const noexcept;
// Plane-sphere test
bool XM_CALLCONV Intersects(_In_ FXMVECTOR Origin, _In_ FXMVECTOR Direction, _Out_ float& Dist) const noexcept;
// Ray-sphere test
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR Plane0, _In_ FXMVECTOR Plane1, _In_ FXMVECTOR Plane2,
_In_ GXMVECTOR Plane3, _In_ HXMVECTOR Plane4, _In_ HXMVECTOR Plane5) const noexcept;
// Test sphere against six planes (see BoundingFrustum::GetPlanes)
// Static methods
static void CreateMerged(_Out_ BoundingSphere& Out, _In_ const BoundingSphere& S1, _In_ const BoundingSphere& S2) noexcept;
static void CreateFromBoundingBox(_Out_ BoundingSphere& Out, _In_ const BoundingBox& box) noexcept;
static void CreateFromBoundingBox(_Out_ BoundingSphere& Out, _In_ const BoundingOrientedBox& box) noexcept;
static void CreateFromPoints(_Out_ BoundingSphere& Out, _In_ size_t Count,
_In_reads_bytes_(sizeof(XMFLOAT3) + Stride * (Count - 1)) const XMFLOAT3* pPoints, _In_ size_t Stride) noexcept;
static void CreateFromFrustum(_Out_ BoundingSphere& Out, _In_ const BoundingFrustum& fr) noexcept;
};
//-------------------------------------------------------------------------------------
// Axis-aligned bounding box
//-------------------------------------------------------------------------------------
struct BoundingBox
{
static constexpr size_t CORNER_COUNT = 8;
XMFLOAT3 Center; // Center of the box.
XMFLOAT3 Extents; // Distance from the center to each side.
// Creators
BoundingBox() noexcept : Center(0, 0, 0), Extents(1.f, 1.f, 1.f) {}
BoundingBox(const BoundingBox&) = default;
BoundingBox& operator=(const BoundingBox&) = default;
BoundingBox(BoundingBox&&) = default;
BoundingBox& operator=(BoundingBox&&) = default;
constexpr BoundingBox(_In_ const XMFLOAT3& center, _In_ const XMFLOAT3& extents) noexcept
: Center(center), Extents(extents) {}
// Methods
void XM_CALLCONV Transform(_Out_ BoundingBox& Out, _In_ FXMMATRIX M) const noexcept;
void XM_CALLCONV Transform(_Out_ BoundingBox& Out, _In_ float Scale, _In_ FXMVECTOR Rotation, _In_ FXMVECTOR Translation) const noexcept;
void GetCorners(_Out_writes_(8) XMFLOAT3* Corners) const noexcept;
// Gets the 8 corners of the box
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR Point) const noexcept;
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
ContainmentType Contains(_In_ const BoundingSphere& sh) const noexcept;
ContainmentType Contains(_In_ const BoundingBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingOrientedBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingFrustum& fr) const noexcept;
bool Intersects(_In_ const BoundingSphere& sh) const noexcept;
bool Intersects(_In_ const BoundingBox& box) const noexcept;
bool Intersects(_In_ const BoundingOrientedBox& box) const noexcept;
bool Intersects(_In_ const BoundingFrustum& fr) const noexcept;
bool XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
// Triangle-Box test
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR Plane) const noexcept;
// Plane-box test
bool XM_CALLCONV Intersects(_In_ FXMVECTOR Origin, _In_ FXMVECTOR Direction, _Out_ float& Dist) const noexcept;
// Ray-Box test
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR Plane0, _In_ FXMVECTOR Plane1, _In_ FXMVECTOR Plane2,
_In_ GXMVECTOR Plane3, _In_ HXMVECTOR Plane4, _In_ HXMVECTOR Plane5) const noexcept;
// Test box against six planes (see BoundingFrustum::GetPlanes)
// Static methods
static void CreateMerged(_Out_ BoundingBox& Out, _In_ const BoundingBox& b1, _In_ const BoundingBox& b2) noexcept;
static void CreateFromSphere(_Out_ BoundingBox& Out, _In_ const BoundingSphere& sh) noexcept;
static void XM_CALLCONV CreateFromPoints(_Out_ BoundingBox& Out, _In_ FXMVECTOR pt1, _In_ FXMVECTOR pt2) noexcept;
static void CreateFromPoints(_Out_ BoundingBox& Out, _In_ size_t Count,
_In_reads_bytes_(sizeof(XMFLOAT3) + Stride * (Count - 1)) const XMFLOAT3* pPoints, _In_ size_t Stride) noexcept;
};
//-------------------------------------------------------------------------------------
// Oriented bounding box
//-------------------------------------------------------------------------------------
struct BoundingOrientedBox
{
static constexpr size_t CORNER_COUNT = 8;
XMFLOAT3 Center; // Center of the box.
XMFLOAT3 Extents; // Distance from the center to each side.
XMFLOAT4 Orientation; // Unit quaternion representing rotation (box -> world).
// Creators
BoundingOrientedBox() noexcept : Center(0, 0, 0), Extents(1.f, 1.f, 1.f), Orientation(0, 0, 0, 1.f) {}
BoundingOrientedBox(const BoundingOrientedBox&) = default;
BoundingOrientedBox& operator=(const BoundingOrientedBox&) = default;
BoundingOrientedBox(BoundingOrientedBox&&) = default;
BoundingOrientedBox& operator=(BoundingOrientedBox&&) = default;
constexpr BoundingOrientedBox(_In_ const XMFLOAT3& center, _In_ const XMFLOAT3& extents, _In_ const XMFLOAT4& orientation) noexcept
: Center(center), Extents(extents), Orientation(orientation) {}
// Methods
void XM_CALLCONV Transform(_Out_ BoundingOrientedBox& Out, _In_ FXMMATRIX M) const noexcept;
void XM_CALLCONV Transform(_Out_ BoundingOrientedBox& Out, _In_ float Scale, _In_ FXMVECTOR Rotation, _In_ FXMVECTOR Translation) const noexcept;
void GetCorners(_Out_writes_(8) XMFLOAT3* Corners) const noexcept;
// Gets the 8 corners of the box
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR Point) const noexcept;
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
ContainmentType Contains(_In_ const BoundingSphere& sh) const noexcept;
ContainmentType Contains(_In_ const BoundingBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingOrientedBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingFrustum& fr) const noexcept;
bool Intersects(_In_ const BoundingSphere& sh) const noexcept;
bool Intersects(_In_ const BoundingBox& box) const noexcept;
bool Intersects(_In_ const BoundingOrientedBox& box) const noexcept;
bool Intersects(_In_ const BoundingFrustum& fr) const noexcept;
bool XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
// Triangle-OrientedBox test
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR Plane) const noexcept;
// Plane-OrientedBox test
bool XM_CALLCONV Intersects(_In_ FXMVECTOR Origin, _In_ FXMVECTOR Direction, _Out_ float& Dist) const noexcept;
// Ray-OrientedBox test
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR Plane0, _In_ FXMVECTOR Plane1, _In_ FXMVECTOR Plane2,
_In_ GXMVECTOR Plane3, _In_ HXMVECTOR Plane4, _In_ HXMVECTOR Plane5) const noexcept;
// Test OrientedBox against six planes (see BoundingFrustum::GetPlanes)
// Static methods
static void CreateFromBoundingBox(_Out_ BoundingOrientedBox& Out, _In_ const BoundingBox& box) noexcept;
static void CreateFromPoints(_Out_ BoundingOrientedBox& Out, _In_ size_t Count,
_In_reads_bytes_(sizeof(XMFLOAT3) + Stride * (Count - 1)) const XMFLOAT3* pPoints, _In_ size_t Stride) noexcept;
};
//-------------------------------------------------------------------------------------
// Bounding frustum
//-------------------------------------------------------------------------------------
struct BoundingFrustum
{
static constexpr size_t CORNER_COUNT = 8;
XMFLOAT3 Origin; // Origin of the frustum (and projection).
XMFLOAT4 Orientation; // Quaternion representing rotation.
float RightSlope; // Positive X (X/Z)
float LeftSlope; // Negative X
float TopSlope; // Positive Y (Y/Z)
float BottomSlope; // Negative Y
float Near, Far; // Z of the near plane and far plane.
// Creators
BoundingFrustum() noexcept :
Origin(0, 0, 0), Orientation(0, 0, 0, 1.f), RightSlope(1.f), LeftSlope(-1.f),
TopSlope(1.f), BottomSlope(-1.f), Near(0), Far(1.f) {}
BoundingFrustum(const BoundingFrustum&) = default;
BoundingFrustum& operator=(const BoundingFrustum&) = default;
BoundingFrustum(BoundingFrustum&&) = default;
BoundingFrustum& operator=(BoundingFrustum&&) = default;
constexpr BoundingFrustum(_In_ const XMFLOAT3& origin, _In_ const XMFLOAT4& orientation,
_In_ float rightSlope, _In_ float leftSlope, _In_ float topSlope, _In_ float bottomSlope,
_In_ float nearPlane, _In_ float farPlane) noexcept
: Origin(origin), Orientation(orientation),
RightSlope(rightSlope), LeftSlope(leftSlope), TopSlope(topSlope), BottomSlope(bottomSlope),
Near(nearPlane), Far(farPlane) {}
BoundingFrustum(_In_ CXMMATRIX Projection, bool rhcoords = false) noexcept;
// Methods
void XM_CALLCONV Transform(_Out_ BoundingFrustum& Out, _In_ FXMMATRIX M) const noexcept;
void XM_CALLCONV Transform(_Out_ BoundingFrustum& Out, _In_ float Scale, _In_ FXMVECTOR Rotation, _In_ FXMVECTOR Translation) const noexcept;
void GetCorners(_Out_writes_(8) XMFLOAT3* Corners) const noexcept;
// Gets the 8 corners of the frustum
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR Point) const noexcept;
ContainmentType XM_CALLCONV Contains(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
ContainmentType Contains(_In_ const BoundingSphere& sp) const noexcept;
ContainmentType Contains(_In_ const BoundingBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingOrientedBox& box) const noexcept;
ContainmentType Contains(_In_ const BoundingFrustum& fr) const noexcept;
// Frustum-Frustum test
bool Intersects(_In_ const BoundingSphere& sh) const noexcept;
bool Intersects(_In_ const BoundingBox& box) const noexcept;
bool Intersects(_In_ const BoundingOrientedBox& box) const noexcept;
bool Intersects(_In_ const BoundingFrustum& fr) const noexcept;
bool XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2) const noexcept;
// Triangle-Frustum test
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR Plane) const noexcept;
// Plane-Frustum test
bool XM_CALLCONV Intersects(_In_ FXMVECTOR rayOrigin, _In_ FXMVECTOR Direction, _Out_ float& Dist) const noexcept;
// Ray-Frustum test
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR Plane0, _In_ FXMVECTOR Plane1, _In_ FXMVECTOR Plane2,
_In_ GXMVECTOR Plane3, _In_ HXMVECTOR Plane4, _In_ HXMVECTOR Plane5) const noexcept;
// Test frustum against six planes (see BoundingFrustum::GetPlanes)
void GetPlanes(_Out_opt_ XMVECTOR* NearPlane, _Out_opt_ XMVECTOR* FarPlane, _Out_opt_ XMVECTOR* RightPlane,
_Out_opt_ XMVECTOR* LeftPlane, _Out_opt_ XMVECTOR* TopPlane, _Out_opt_ XMVECTOR* BottomPlane) const noexcept;
// Create 6 Planes representation of Frustum
// Static methods
static void XM_CALLCONV CreateFromMatrix(_Out_ BoundingFrustum& Out, _In_ FXMMATRIX Projection, bool rhcoords = false) noexcept;
};
//-----------------------------------------------------------------------------
// Triangle intersection testing routines.
//-----------------------------------------------------------------------------
namespace TriangleTests
{
bool XM_CALLCONV Intersects(_In_ FXMVECTOR Origin, _In_ FXMVECTOR Direction, _In_ FXMVECTOR V0, _In_ GXMVECTOR V1, _In_ HXMVECTOR V2, _Out_ float& Dist) noexcept;
// Ray-Triangle
bool XM_CALLCONV Intersects(_In_ FXMVECTOR A0, _In_ FXMVECTOR A1, _In_ FXMVECTOR A2, _In_ GXMVECTOR B0, _In_ HXMVECTOR B1, _In_ HXMVECTOR B2) noexcept;
// Triangle-Triangle
PlaneIntersectionType XM_CALLCONV Intersects(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2, _In_ GXMVECTOR Plane) noexcept;
// Plane-Triangle
ContainmentType XM_CALLCONV ContainedBy(_In_ FXMVECTOR V0, _In_ FXMVECTOR V1, _In_ FXMVECTOR V2,
_In_ GXMVECTOR Plane0, _In_ HXMVECTOR Plane1, _In_ HXMVECTOR Plane2,
_In_ CXMVECTOR Plane3, _In_ CXMVECTOR Plane4, _In_ CXMVECTOR Plane5) noexcept;
// Test a triangle against six planes at once (see BoundingFrustum::GetPlanes)
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
/****************************************************************************
*
* Implementation
*
****************************************************************************/
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4068 4365 4616 6001)
// C4068/4616: ignore unknown pragmas
// C4365: Off by default noise
// C6001: False positives
#endif
#ifdef _PREFAST_
#pragma prefast(push)
#pragma prefast(disable : 25000, "FXMVECTOR is 16 bytes")
#pragma prefast(disable : 26495, "Union initialization confuses /analyze")
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wunknown-warning-option"
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
#include "DirectXCollision.inl"
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef _PREFAST_
#pragma prefast(pop)
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
} // namespace DirectX

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
// DirectXMathConvert.inl -- SIMD C++ Math library // DirectXMathConvert.inl -- SIMD C++ Math library
// //
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License. // Licensed under the MIT License.
// //
// http://go.microsoft.com/fwlink/?LinkID=615560 // https://go.microsoft.com/fwlink/?LinkID=615560
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
#pragma once #pragma once
@ -15,11 +15,13 @@
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4701) #pragma warning(disable:4701)
// C4701: false positives // C4701: false positives
#endif
inline XMVECTOR XM_CALLCONV XMConvertVectorIntToFloat inline XMVECTOR XM_CALLCONV XMConvertVectorIntToFloat
( (
@ -32,14 +34,16 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorIntToFloat
float fScale = 1.0f / static_cast<float>(1U << DivExponent); float fScale = 1.0f / static_cast<float>(1U << DivExponent);
uint32_t ElementIndex = 0; uint32_t ElementIndex = 0;
XMVECTOR Result; XMVECTOR Result;
do { do
{
auto iTemp = static_cast<int32_t>(VInt.vector4_u32[ElementIndex]); auto iTemp = static_cast<int32_t>(VInt.vector4_u32[ElementIndex]);
Result.vector4_f32[ElementIndex] = static_cast<float>(iTemp)* fScale; Result.vector4_f32[ElementIndex] = static_cast<float>(iTemp)* fScale;
} while (++ElementIndex < 4); }
while (++ElementIndex < 4);
return Result; return Result;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float fScale = 1.0f / (float)(1U << DivExponent); float fScale = 1.0f / static_cast<float>(1U << DivExponent);
float32x4_t vResult = vcvtq_f32_s32(VInt); float32x4_t vResult = vcvtq_f32_s32(vreinterpretq_s32_f32(VInt));
return vmulq_n_f32(vResult, fScale); return vmulq_n_f32(vResult, fScale);
#else // _XM_SSE_INTRINSICS_ #else // _XM_SSE_INTRINSICS_
// Convert to floats // Convert to floats
@ -67,7 +71,8 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToInt
auto fScale = static_cast<float>(1U << MulExponent); auto fScale = static_cast<float>(1U << MulExponent);
uint32_t ElementIndex = 0; uint32_t ElementIndex = 0;
XMVECTOR Result; XMVECTOR Result;
do { do
{
int32_t iResult; int32_t iResult;
float fTemp = VFloat.vector4_f32[ElementIndex] * fScale; float fTemp = VFloat.vector4_f32[ElementIndex] * fScale;
if (fTemp <= -(65536.0f * 32768.0f)) if (fTemp <= -(65536.0f * 32768.0f))
@ -78,23 +83,25 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToInt
{ {
iResult = 0x7FFFFFFF; iResult = 0x7FFFFFFF;
} }
else { else
{
iResult = static_cast<int32_t>(fTemp); iResult = static_cast<int32_t>(fTemp);
} }
Result.vector4_u32[ElementIndex] = static_cast<uint32_t>(iResult); Result.vector4_u32[ElementIndex] = static_cast<uint32_t>(iResult);
} while (++ElementIndex < 4); }
while (++ElementIndex < 4);
return Result; return Result;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float32x4_t vResult = vmulq_n_f32(VFloat, (float)(1U << MulExponent)); float32x4_t vResult = vmulq_n_f32(VFloat, static_cast<float>(1U << MulExponent));
// In case of positive overflow, detect it // In case of positive overflow, detect it
uint32x4_t vOverflow = vcgtq_f32(vResult, g_XMMaxInt); uint32x4_t vOverflow = vcgtq_f32(vResult, g_XMMaxInt);
// Float to int conversion // Float to int conversion
int32x4_t vResulti = vcvtq_s32_f32(vResult); int32x4_t vResulti = vcvtq_s32_f32(vResult);
// If there was positive overflow, set to 0x7FFFFFFF // If there was positive overflow, set to 0x7FFFFFFF
vResult = vandq_u32(vOverflow, g_XMAbsMask); vResult = vreinterpretq_f32_u32(vandq_u32(vOverflow, g_XMAbsMask));
vOverflow = vbicq_u32(vResulti, vOverflow); vOverflow = vbicq_u32(vreinterpretq_u32_s32(vResulti), vOverflow);
vOverflow = vorrq_u32(vOverflow, vResult); vOverflow = vorrq_u32(vOverflow, vreinterpretq_u32_f32(vResult));
return vOverflow; return vreinterpretq_f32_u32(vOverflow);
#else // _XM_SSE_INTRINSICS_ #else // _XM_SSE_INTRINSICS_
XMVECTOR vResult = _mm_set_ps1(static_cast<float>(1U << MulExponent)); XMVECTOR vResult = _mm_set_ps1(static_cast<float>(1U << MulExponent));
vResult = _mm_mul_ps(vResult, VFloat); vResult = _mm_mul_ps(vResult, VFloat);
@ -123,13 +130,15 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorUIntToFloat
float fScale = 1.0f / static_cast<float>(1U << DivExponent); float fScale = 1.0f / static_cast<float>(1U << DivExponent);
uint32_t ElementIndex = 0; uint32_t ElementIndex = 0;
XMVECTOR Result; XMVECTOR Result;
do { do
{
Result.vector4_f32[ElementIndex] = static_cast<float>(VUInt.vector4_u32[ElementIndex])* fScale; Result.vector4_f32[ElementIndex] = static_cast<float>(VUInt.vector4_u32[ElementIndex])* fScale;
} while (++ElementIndex < 4); }
while (++ElementIndex < 4);
return Result; return Result;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float fScale = 1.0f / (float)(1U << DivExponent); float fScale = 1.0f / static_cast<float>(1U << DivExponent);
float32x4_t vResult = vcvtq_f32_u32(VUInt); float32x4_t vResult = vcvtq_f32_u32(vreinterpretq_u32_f32(VUInt));
return vmulq_n_f32(vResult, fScale); return vmulq_n_f32(vResult, fScale);
#else // _XM_SSE_INTRINSICS_ #else // _XM_SSE_INTRINSICS_
// For the values that are higher than 0x7FFFFFFF, a fixup is needed // For the values that are higher than 0x7FFFFFFF, a fixup is needed
@ -167,7 +176,8 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt
auto fScale = static_cast<float>(1U << MulExponent); auto fScale = static_cast<float>(1U << MulExponent);
uint32_t ElementIndex = 0; uint32_t ElementIndex = 0;
XMVECTOR Result; XMVECTOR Result;
do { do
{
uint32_t uResult; uint32_t uResult;
float fTemp = VFloat.vector4_f32[ElementIndex] * fScale; float fTemp = VFloat.vector4_f32[ElementIndex] * fScale;
if (fTemp <= 0.0f) if (fTemp <= 0.0f)
@ -178,22 +188,24 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt
{ {
uResult = 0xFFFFFFFFU; uResult = 0xFFFFFFFFU;
} }
else { else
{
uResult = static_cast<uint32_t>(fTemp); uResult = static_cast<uint32_t>(fTemp);
} }
Result.vector4_u32[ElementIndex] = uResult; Result.vector4_u32[ElementIndex] = uResult;
} while (++ElementIndex < 4); }
while (++ElementIndex < 4);
return Result; return Result;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float32x4_t vResult = vmulq_n_f32(VFloat, (float)(1U << MulExponent)); float32x4_t vResult = vmulq_n_f32(VFloat, static_cast<float>(1U << MulExponent));
// In case of overflow, detect it // In case of overflow, detect it
uint32x4_t vOverflow = vcgtq_f32(vResult, g_XMMaxUInt); uint32x4_t vOverflow = vcgtq_f32(vResult, g_XMMaxUInt);
// Float to int conversion // Float to int conversion
uint32x4_t vResulti = vcvtq_u32_f32(vResult); uint32x4_t vResulti = vcvtq_u32_f32(vResult);
// If there was overflow, set to 0xFFFFFFFFU // If there was overflow, set to 0xFFFFFFFFU
vResult = vbicq_u32(vResulti, vOverflow); vResult = vreinterpretq_f32_u32(vbicq_u32(vResulti, vOverflow));
vOverflow = vorrq_u32(vOverflow, vResult); vOverflow = vorrq_u32(vOverflow, vreinterpretq_u32_f32(vResult));
return vOverflow; return vreinterpretq_f32_u32(vOverflow);
#else // _XM_SSE_INTRINSICS_ #else // _XM_SSE_INTRINSICS_
XMVECTOR vResult = _mm_set_ps1(static_cast<float>(1U << MulExponent)); XMVECTOR vResult = _mm_set_ps1(static_cast<float>(1U << MulExponent));
vResult = _mm_mul_ps(vResult, VFloat); vResult = _mm_mul_ps(vResult, VFloat);
@ -218,7 +230,9 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt
#endif #endif
} }
#ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif
/**************************************************************************** /****************************************************************************
* *
@ -226,7 +240,7 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
_Use_decl_annotations_ _Use_decl_annotations_
inline XMVECTOR XM_CALLCONV XMLoadInt(const uint32_t* pSource) noexcept inline XMVECTOR XM_CALLCONV XMLoadInt(const uint32_t* pSource) noexcept
{ {
@ -240,7 +254,7 @@ inline XMVECTOR XM_CALLCONV XMLoadInt(const uint32_t* pSource) noexcept
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x4_t zero = vdupq_n_u32(0); uint32x4_t zero = vdupq_n_u32(0);
return vld1q_lane_u32(pSource, zero, 0); return vreinterpretq_f32_u32(vld1q_lane_u32(pSource, zero, 0));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
return _mm_load_ss(reinterpret_cast<const float*>(pSource)); return _mm_load_ss(reinterpret_cast<const float*>(pSource));
#endif #endif
@ -281,7 +295,7 @@ inline XMVECTOR XM_CALLCONV XMLoadInt2(const uint32_t* pSource) noexcept
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t x = vld1_u32(pSource); uint32x2_t x = vld1_u32(pSource);
uint32x2_t zero = vdup_n_u32(0); uint32x2_t zero = vdup_n_u32(0);
return vcombine_u32(x, zero); return vreinterpretq_f32_u32(vcombine_u32(x, zero));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
return _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource))); return _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource)));
#endif #endif
@ -301,13 +315,13 @@ inline XMVECTOR XM_CALLCONV XMLoadInt2A(const uint32_t* pSource) noexcept
V.vector4_u32[3] = 0; V.vector4_u32[3] = 0;
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
uint32x2_t x = vld1_u32_ex(pSource, 64); uint32x2_t x = vld1_u32_ex(pSource, 64);
#else #else
uint32x2_t x = vld1_u32(pSource); uint32x2_t x = vld1_u32(pSource);
#endif #endif
uint32x2_t zero = vdup_n_u32(0); uint32x2_t zero = vdup_n_u32(0);
return vcombine_u32(x, zero); return vreinterpretq_f32_u32(vcombine_u32(x, zero));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
return _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource))); return _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource)));
#endif #endif
@ -348,7 +362,7 @@ inline XMVECTOR XM_CALLCONV XMLoadFloat2A(const XMFLOAT2A* pSource) noexcept
V.vector4_f32[3] = 0.f; V.vector4_f32[3] = 0.f;
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x2_t x = vld1_f32_ex(reinterpret_cast<const float*>(pSource), 64); float32x2_t x = vld1_f32_ex(reinterpret_cast<const float*>(pSource), 64);
#else #else
float32x2_t x = vld1_f32(reinterpret_cast<const float*>(pSource)); float32x2_t x = vld1_f32(reinterpret_cast<const float*>(pSource));
@ -434,7 +448,7 @@ inline XMVECTOR XM_CALLCONV XMLoadInt3(const uint32_t* pSource) noexcept
uint32x2_t x = vld1_u32(pSource); uint32x2_t x = vld1_u32(pSource);
uint32x2_t zero = vdup_n_u32(0); uint32x2_t zero = vdup_n_u32(0);
uint32x2_t y = vld1_lane_u32(pSource + 2, zero, 0); uint32x2_t y = vld1_lane_u32(pSource + 2, zero, 0);
return vcombine_u32(x, y); return vreinterpretq_f32_u32(vcombine_u32(x, y));
#elif defined(_XM_SSE4_INTRINSICS_) #elif defined(_XM_SSE4_INTRINSICS_)
__m128 xy = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource))); __m128 xy = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource)));
__m128 z = _mm_load_ss(reinterpret_cast<const float*>(pSource + 2)); __m128 z = _mm_load_ss(reinterpret_cast<const float*>(pSource + 2));
@ -461,12 +475,12 @@ inline XMVECTOR XM_CALLCONV XMLoadInt3A(const uint32_t* pSource) noexcept
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
// Reads an extra integer which is zero'd // Reads an extra integer which is zero'd
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
uint32x4_t V = vld1q_u32_ex(pSource, 128); uint32x4_t V = vld1q_u32_ex(pSource, 128);
#else #else
uint32x4_t V = vld1q_u32(pSource); uint32x4_t V = vld1q_u32(pSource);
#endif #endif
return vsetq_lane_u32(0, V, 3); return vreinterpretq_f32_u32(vsetq_lane_u32(0, V, 3));
#elif defined(_XM_SSE4_INTRINSICS_) #elif defined(_XM_SSE4_INTRINSICS_)
__m128 xy = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource))); __m128 xy = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<const double*>(pSource)));
__m128 z = _mm_load_ss(reinterpret_cast<const float*>(pSource + 2)); __m128 z = _mm_load_ss(reinterpret_cast<const float*>(pSource + 2));
@ -521,12 +535,16 @@ inline XMVECTOR XM_CALLCONV XMLoadFloat3A(const XMFLOAT3A* pSource) noexcept
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
// Reads an extra float which is zero'd // Reads an extra float which is zero'd
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x4_t V = vld1q_f32_ex(reinterpret_cast<const float*>(pSource), 128); float32x4_t V = vld1q_f32_ex(reinterpret_cast<const float*>(pSource), 128);
#else #else
float32x4_t V = vld1q_f32(reinterpret_cast<const float*>(pSource)); float32x4_t V = vld1q_f32(reinterpret_cast<const float*>(pSource));
#endif #endif
return vsetq_lane_f32(0, V, 3); return vsetq_lane_f32(0, V, 3);
#elif defined(_XM_SSE4_INTRINSICS_)
// Reads an extra float which is zero'd
__m128 V = _mm_load_ps(&pSource->x);
return _mm_blend_ps(_mm_setzero_ps(), V, 0x7);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// Reads an extra float which is zero'd // Reads an extra float which is zero'd
__m128 V = _mm_load_ps(&pSource->x); __m128 V = _mm_load_ps(&pSource->x);
@ -614,7 +632,7 @@ inline XMVECTOR XM_CALLCONV XMLoadInt4(const uint32_t* pSource) noexcept
V.vector4_u32[3] = pSource[3]; V.vector4_u32[3] = pSource[3];
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
return vld1q_u32(pSource); return vreinterpretq_f32_u32(vld1q_u32(pSource));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
__m128i V = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pSource)); __m128i V = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pSource));
return _mm_castsi128_ps(V); return _mm_castsi128_ps(V);
@ -635,10 +653,10 @@ inline XMVECTOR XM_CALLCONV XMLoadInt4A(const uint32_t* pSource) noexcept
V.vector4_u32[3] = pSource[3]; V.vector4_u32[3] = pSource[3];
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
return vld1q_u32_ex(pSource, 128); return vld1q_u32_ex(pSource, 128);
#else #else
return vld1q_u32(pSource); return vreinterpretq_f32_u32(vld1q_u32(pSource));
#endif #endif
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
__m128i V = _mm_load_si128(reinterpret_cast<const __m128i*>(pSource)); __m128i V = _mm_load_si128(reinterpret_cast<const __m128i*>(pSource));
@ -679,7 +697,7 @@ inline XMVECTOR XM_CALLCONV XMLoadFloat4A(const XMFLOAT4A* pSource) noexcept
V.vector4_f32[3] = pSource->w; V.vector4_f32[3] = pSource->w;
return V; return V;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
return vld1q_f32_ex(reinterpret_cast<const float*>(pSource), 128); return vld1q_f32_ex(reinterpret_cast<const float*>(pSource), 128);
#else #else
return vld1q_f32(reinterpret_cast<const float*>(pSource)); return vld1q_f32(reinterpret_cast<const float*>(pSource));
@ -780,8 +798,8 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat3x3(const XMFLOAT3X3* pSource) noexcept
float32x4_t T = vextq_f32(v0, v1, 3); float32x4_t T = vextq_f32(v0, v1, 3);
XMMATRIX M; XMMATRIX M;
M.r[0] = vandq_u32(v0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(v0), g_XMMask3));
M.r[1] = vandq_u32(T, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T), g_XMMask3));
M.r[2] = vcombine_f32(vget_high_f32(v1), v2); M.r[2] = vcombine_f32(vget_high_f32(v1), v2);
M.r[3] = g_XMIdentityR3; M.r[3] = g_XMIdentityR3;
return M; return M;
@ -846,9 +864,9 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3(const XMFLOAT4X3* pSource) noexcept
float32x4_t T3 = vextq_f32(v2, v2, 1); float32x4_t T3 = vextq_f32(v2, v2, 1);
XMMATRIX M; XMMATRIX M;
M.r[0] = vandq_u32(v0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(v0), g_XMMask3));
M.r[1] = vandq_u32(T1, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T1), g_XMMask3));
M.r[2] = vandq_u32(T2, g_XMMask3); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T2), g_XMMask3));
M.r[3] = vsetq_lane_f32(1.f, T3, 3); M.r[3] = vsetq_lane_f32(1.f, T3, 3);
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -867,11 +885,18 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3(const XMFLOAT4X3* pSource) noexcept
// vTemp2 = x2,y2,z2,z2 // vTemp2 = x2,y2,z2,z2
vTemp2 = XM_PERMUTE_PS(vTemp2, _MM_SHUFFLE(1, 1, 0, 2)); vTemp2 = XM_PERMUTE_PS(vTemp2, _MM_SHUFFLE(1, 1, 0, 2));
// vTemp1 = x1,y1,z1,0 // vTemp1 = x1,y1,z1,0
vTemp1 = _mm_and_ps(vTemp1, g_XMMask3);
// vTemp2 = x2,y2,z2,0 // vTemp2 = x2,y2,z2,0
vTemp2 = _mm_and_ps(vTemp2, g_XMMask3);
// vTemp3 = x3,y3,z3,0 // vTemp3 = x3,y3,z3,0
#ifdef _XM_SSE4_INTRINSICS_
XMVECTOR zero = _mm_setzero_ps();
vTemp1 = _mm_blend_ps(zero, vTemp1, 0x7);
vTemp2 = _mm_blend_ps(zero, vTemp2, 0x7);
vTemp3 = _mm_blend_ps(zero, vTemp3, 0x7);
#else
vTemp1 = _mm_and_ps(vTemp1, g_XMMask3);
vTemp2 = _mm_and_ps(vTemp2, g_XMMask3);
vTemp3 = _mm_and_ps(vTemp3, g_XMMask3); vTemp3 = _mm_and_ps(vTemp3, g_XMMask3);
#endif
// vTemp4i = x4,y4,z4,0 // vTemp4i = x4,y4,z4,0
__m128i vTemp4i = _mm_srli_si128(_mm_castps_si128(vTemp4), 32 / 8); __m128i vTemp4i = _mm_srli_si128(_mm_castps_si128(vTemp4), 32 / 8);
// vTemp4i = x4,y4,z4,1.0f // vTemp4i = x4,y4,z4,1.0f
@ -915,7 +940,7 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3A(const XMFLOAT4X3A* pSource) noexcept
return M; return M;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x4_t v0 = vld1q_f32_ex(&pSource->m[0][0], 128); float32x4_t v0 = vld1q_f32_ex(&pSource->m[0][0], 128);
float32x4_t v1 = vld1q_f32_ex(&pSource->m[1][1], 128); float32x4_t v1 = vld1q_f32_ex(&pSource->m[1][1], 128);
float32x4_t v2 = vld1q_f32_ex(&pSource->m[2][2], 128); float32x4_t v2 = vld1q_f32_ex(&pSource->m[2][2], 128);
@ -930,9 +955,9 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3A(const XMFLOAT4X3A* pSource) noexcept
float32x4_t T3 = vextq_f32(v2, v2, 1); float32x4_t T3 = vextq_f32(v2, v2, 1);
XMMATRIX M; XMMATRIX M;
M.r[0] = vandq_u32(v0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(v0), g_XMMask3));
M.r[1] = vandq_u32(T1, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T1), g_XMMask3));
M.r[2] = vandq_u32(T2, g_XMMask3); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T2), g_XMMask3));
M.r[3] = vsetq_lane_f32(1.f, T3, 3); M.r[3] = vsetq_lane_f32(1.f, T3, 3);
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -951,11 +976,18 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x3A(const XMFLOAT4X3A* pSource) noexcept
// vTemp2 = x2,y2,z2,z2 // vTemp2 = x2,y2,z2,z2
vTemp2 = XM_PERMUTE_PS(vTemp2, _MM_SHUFFLE(1, 1, 0, 2)); vTemp2 = XM_PERMUTE_PS(vTemp2, _MM_SHUFFLE(1, 1, 0, 2));
// vTemp1 = x1,y1,z1,0 // vTemp1 = x1,y1,z1,0
vTemp1 = _mm_and_ps(vTemp1, g_XMMask3);
// vTemp2 = x2,y2,z2,0 // vTemp2 = x2,y2,z2,0
vTemp2 = _mm_and_ps(vTemp2, g_XMMask3);
// vTemp3 = x3,y3,z3,0 // vTemp3 = x3,y3,z3,0
#ifdef _XM_SSE4_INTRINSICS_
XMVECTOR zero = _mm_setzero_ps();
vTemp1 = _mm_blend_ps(zero, vTemp1, 0x7);
vTemp2 = _mm_blend_ps(zero, vTemp2, 0x7);
vTemp3 = _mm_blend_ps(zero, vTemp3, 0x7);
#else
vTemp1 = _mm_and_ps(vTemp1, g_XMMask3);
vTemp2 = _mm_and_ps(vTemp2, g_XMMask3);
vTemp3 = _mm_and_ps(vTemp3, g_XMMask3); vTemp3 = _mm_and_ps(vTemp3, g_XMMask3);
#endif
// vTemp4i = x4,y4,z4,0 // vTemp4i = x4,y4,z4,0
__m128i vTemp4i = _mm_srli_si128(_mm_castps_si128(vTemp4), 32 / 8); __m128i vTemp4i = _mm_srli_si128(_mm_castps_si128(vTemp4), 32 / 8);
// vTemp4i = x4,y4,z4,1.0f // vTemp4i = x4,y4,z4,1.0f
@ -1012,9 +1044,9 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat3x4(const XMFLOAT3X4* pSource) noexcept
float32x4_t T3 = vcombine_f32(vTemp0.val[3], rh); float32x4_t T3 = vcombine_f32(vTemp0.val[3], rh);
XMMATRIX M = {}; XMMATRIX M = {};
M.r[0] = vandq_u32(T0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T0), g_XMMask3));
M.r[1] = vandq_u32(T1, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T1), g_XMMask3));
M.r[2] = vandq_u32(T2, g_XMMask3); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T2), g_XMMask3));
M.r[3] = vsetq_lane_f32(1.f, T3, 3); M.r[3] = vsetq_lane_f32(1.f, T3, 3);
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -1077,7 +1109,7 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat3x4A(const XMFLOAT3X4A* pSource) noexcept
return M; return M;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x2x4_t vTemp0 = vld4_f32_ex(&pSource->_11, 128); float32x2x4_t vTemp0 = vld4_f32_ex(&pSource->_11, 128);
float32x4_t vTemp1 = vld1q_f32_ex(&pSource->_31, 128); float32x4_t vTemp1 = vld1q_f32_ex(&pSource->_31, 128);
#else #else
@ -1096,9 +1128,9 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat3x4A(const XMFLOAT3X4A* pSource) noexcept
float32x4_t T3 = vcombine_f32(vTemp0.val[3], rh); float32x4_t T3 = vcombine_f32(vTemp0.val[3], rh);
XMMATRIX M = {}; XMMATRIX M = {};
M.r[0] = vandq_u32(T0, g_XMMask3); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T0), g_XMMask3));
M.r[1] = vandq_u32(T1, g_XMMask3); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T1), g_XMMask3));
M.r[2] = vandq_u32(T2, g_XMMask3); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(T2), g_XMMask3));
M.r[3] = vsetq_lane_f32(1.f, T3, 3); M.r[3] = vsetq_lane_f32(1.f, T3, 3);
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -1208,7 +1240,7 @@ inline XMMATRIX XM_CALLCONV XMLoadFloat4x4A(const XMFLOAT4X4A* pSource) noexcept
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
XMMATRIX M; XMMATRIX M;
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
M.r[0] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_11), 128); M.r[0] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_11), 128);
M.r[1] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_21), 128); M.r[1] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_21), 128);
M.r[2] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_31), 128); M.r[2] = vld1q_f32_ex(reinterpret_cast<const float*>(&pSource->_31), 128);
@ -1283,7 +1315,7 @@ inline void XM_CALLCONV XMStoreInt2
pDestination[0] = V.vector4_u32[0]; pDestination[0] = V.vector4_u32[0];
pDestination[1] = V.vector4_u32[1]; pDestination[1] = V.vector4_u32[1];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t VL = vget_low_u32(V); uint32x2_t VL = vget_low_u32(vreinterpretq_u32_f32(V));
vst1_u32(pDestination, VL); vst1_u32(pDestination, VL);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
_mm_store_sd(reinterpret_cast<double*>(pDestination), _mm_castps_pd(V)); _mm_store_sd(reinterpret_cast<double*>(pDestination), _mm_castps_pd(V));
@ -1304,8 +1336,8 @@ inline void XM_CALLCONV XMStoreInt2A
pDestination[0] = V.vector4_u32[0]; pDestination[0] = V.vector4_u32[0];
pDestination[1] = V.vector4_u32[1]; pDestination[1] = V.vector4_u32[1];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t VL = vget_low_u32(V); uint32x2_t VL = vget_low_u32(vreinterpretq_u32_f32(V));
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1_u32_ex(pDestination, VL, 64); vst1_u32_ex(pDestination, VL, 64);
#else #else
vst1_u32(pDestination, VL); vst1_u32(pDestination, VL);
@ -1350,7 +1382,7 @@ inline void XM_CALLCONV XMStoreFloat2A
pDestination->y = V.vector4_f32[1]; pDestination->y = V.vector4_f32[1];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float32x2_t VL = vget_low_f32(V); float32x2_t VL = vget_low_f32(V);
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1_f32_ex(reinterpret_cast<float*>(pDestination), VL, 64); vst1_f32_ex(reinterpret_cast<float*>(pDestination), VL, 64);
#else #else
vst1_f32(reinterpret_cast<float*>(pDestination), VL); vst1_f32(reinterpret_cast<float*>(pDestination), VL);
@ -1373,9 +1405,9 @@ inline void XM_CALLCONV XMStoreSInt2
pDestination->x = static_cast<int32_t>(V.vector4_f32[0]); pDestination->x = static_cast<int32_t>(V.vector4_f32[0]);
pDestination->y = static_cast<int32_t>(V.vector4_f32[1]); pDestination->y = static_cast<int32_t>(V.vector4_f32[1]);
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
int32x2_t v = vget_low_s32(V); float32x2_t v = vget_low_f32(V);
v = vcvt_s32_f32(v); int32x2_t iv = vcvt_s32_f32(v);
vst1_s32(reinterpret_cast<int32_t*>(pDestination), v); vst1_s32(reinterpret_cast<int32_t*>(pDestination), iv);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// In case of positive overflow, detect it // In case of positive overflow, detect it
XMVECTOR vOverflow = _mm_cmpgt_ps(V, g_XMMaxInt); XMVECTOR vOverflow = _mm_cmpgt_ps(V, g_XMMaxInt);
@ -1443,7 +1475,7 @@ inline void XM_CALLCONV XMStoreInt3
pDestination[1] = V.vector4_u32[1]; pDestination[1] = V.vector4_u32[1];
pDestination[2] = V.vector4_u32[2]; pDestination[2] = V.vector4_u32[2];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t VL = vget_low_u32(V); uint32x2_t VL = vget_low_u32(vreinterpretq_u32_f32(V));
vst1_u32(pDestination, VL); vst1_u32(pDestination, VL);
vst1q_lane_u32(pDestination + 2, *reinterpret_cast<const uint32x4_t*>(&V), 2); vst1q_lane_u32(pDestination + 2, *reinterpret_cast<const uint32x4_t*>(&V), 2);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -1468,8 +1500,8 @@ inline void XM_CALLCONV XMStoreInt3A
pDestination[1] = V.vector4_u32[1]; pDestination[1] = V.vector4_u32[1];
pDestination[2] = V.vector4_u32[2]; pDestination[2] = V.vector4_u32[2];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
uint32x2_t VL = vget_low_u32(V); uint32x2_t VL = vget_low_u32(vreinterpretq_u32_f32(V));
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1_u32_ex(pDestination, VL, 64); vst1_u32_ex(pDestination, VL, 64);
#else #else
vst1_u32(pDestination, VL); vst1_u32(pDestination, VL);
@ -1526,7 +1558,7 @@ inline void XM_CALLCONV XMStoreFloat3A
pDestination->z = V.vector4_f32[2]; pDestination->z = V.vector4_f32[2];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float32x2_t VL = vget_low_f32(V); float32x2_t VL = vget_low_f32(V);
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1_f32_ex(reinterpret_cast<float*>(pDestination), VL, 64); vst1_f32_ex(reinterpret_cast<float*>(pDestination), VL, 64);
#else #else
vst1_f32(reinterpret_cast<float*>(pDestination), VL); vst1_f32(reinterpret_cast<float*>(pDestination), VL);
@ -1634,7 +1666,7 @@ inline void XM_CALLCONV XMStoreInt4
pDestination[2] = V.vector4_u32[2]; pDestination[2] = V.vector4_u32[2];
pDestination[3] = V.vector4_u32[3]; pDestination[3] = V.vector4_u32[3];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
vst1q_u32(pDestination, V); vst1q_u32(pDestination, vreinterpretq_u32_f32(V));
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
_mm_storeu_si128(reinterpret_cast<__m128i*>(pDestination), _mm_castps_si128(V)); _mm_storeu_si128(reinterpret_cast<__m128i*>(pDestination), _mm_castps_si128(V));
#endif #endif
@ -1656,10 +1688,10 @@ inline void XM_CALLCONV XMStoreInt4A
pDestination[2] = V.vector4_u32[2]; pDestination[2] = V.vector4_u32[2];
pDestination[3] = V.vector4_u32[3]; pDestination[3] = V.vector4_u32[3];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1q_u32_ex(pDestination, V, 128); vst1q_u32_ex(pDestination, V, 128);
#else #else
vst1q_u32(pDestination, V); vst1q_u32(pDestination, vreinterpretq_u32_f32(V));
#endif #endif
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
_mm_store_si128(reinterpret_cast<__m128i*>(pDestination), _mm_castps_si128(V)); _mm_store_si128(reinterpret_cast<__m128i*>(pDestination), _mm_castps_si128(V));
@ -1703,7 +1735,7 @@ inline void XM_CALLCONV XMStoreFloat4A
pDestination->z = V.vector4_f32[2]; pDestination->z = V.vector4_f32[2];
pDestination->w = V.vector4_f32[3]; pDestination->w = V.vector4_f32[3];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1q_f32_ex(reinterpret_cast<float*>(pDestination), V, 128); vst1q_f32_ex(reinterpret_cast<float*>(pDestination), V, 128);
#else #else
vst1q_f32(reinterpret_cast<float*>(pDestination), V); vst1q_f32(reinterpret_cast<float*>(pDestination), V);
@ -1913,7 +1945,7 @@ inline void XM_CALLCONV XMStoreFloat4x3A
pDestination->m[3][2] = M.r[3].vector4_f32[2]; pDestination->m[3][2] = M.r[3].vector4_f32[2];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
float32x4_t T1 = vextq_f32(M.r[0], M.r[1], 1); float32x4_t T1 = vextq_f32(M.r[0], M.r[1], 1);
float32x4_t T2 = vbslq_f32(g_XMMask3, M.r[0], T1); float32x4_t T2 = vbslq_f32(g_XMMask3, M.r[0], T1);
vst1q_f32_ex(&pDestination->m[0][0], T2, 128); vst1q_f32_ex(&pDestination->m[0][0], T2, 128);
@ -2057,7 +2089,7 @@ inline void XM_CALLCONV XMStoreFloat3x4A
float32x4x2_t T0 = vzipq_f32(P0.val[0], P1.val[0]); float32x4x2_t T0 = vzipq_f32(P0.val[0], P1.val[0]);
float32x4x2_t T1 = vzipq_f32(P0.val[1], P1.val[1]); float32x4x2_t T1 = vzipq_f32(P0.val[1], P1.val[1]);
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1q_f32_ex(&pDestination->m[0][0], T0.val[0], 128); vst1q_f32_ex(&pDestination->m[0][0], T0.val[0], 128);
vst1q_f32_ex(&pDestination->m[1][0], T0.val[1], 128); vst1q_f32_ex(&pDestination->m[1][0], T0.val[1], 128);
vst1q_f32_ex(&pDestination->m[2][0], T1.val[0], 128); vst1q_f32_ex(&pDestination->m[2][0], T1.val[0], 128);
@ -2166,7 +2198,7 @@ inline void XM_CALLCONV XMStoreFloat4x4A
pDestination->m[3][3] = M.r[3].vector4_f32[3]; pDestination->m[3][3] = M.r[3].vector4_f32[3];
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__) && !defined(_ARM64_DISTINCT_NEON_TYPES)
vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_11), M.r[0], 128); vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_11), M.r[0], 128);
vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_21), M.r[1], 128); vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_21), M.r[1], 128);
vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_31), M.r[2], 128); vst1q_f32_ex(reinterpret_cast<float*>(&pDestination->_31), M.r[2], 128);

View File

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
// DirectXMathMatrix.inl -- SIMD C++ Math library // DirectXMathMatrix.inl -- SIMD C++ Math library
// //
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License. // Licensed under the MIT License.
// //
// http://go.microsoft.com/fwlink/?LinkID=615560 // https://go.microsoft.com/fwlink/?LinkID=615560
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
#pragma once #pragma once
@ -15,13 +15,13 @@
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Comparison operations // Comparison operations
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if !defined(_XM_NO_INTRINSICS_) && defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) #if !defined(_XM_NO_INTRINSICS_) && defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma float_control(push) #pragma float_control(push)
#pragma float_control(precise, on) #pragma float_control(precise, on)
#endif #endif
@ -32,7 +32,8 @@ inline bool XM_CALLCONV XMMatrixIsNaN(FXMMATRIX M) noexcept
#if defined(_XM_NO_INTRINSICS_) #if defined(_XM_NO_INTRINSICS_)
size_t i = 16; size_t i = 16;
auto pWork = reinterpret_cast<const uint32_t*>(&M.m[0][0]); auto pWork = reinterpret_cast<const uint32_t*>(&M.m[0][0]);
do { do
{
// Fetch value into integer unit // Fetch value into integer unit
uint32_t uTest = pWork[0]; uint32_t uTest = pWork[0];
// Remove sign // Remove sign
@ -44,27 +45,30 @@ inline bool XM_CALLCONV XMMatrixIsNaN(FXMMATRIX M) noexcept
break; // NaN found break; // NaN found
} }
++pWork; // Next entry ++pWork; // Next entry
} while (--i); }
while (--i);
return (i != 0); // i == 0 if nothing matched return (i != 0); // i == 0 if nothing matched
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
// Load in registers // Load in registers
XMVECTOR vX = M.r[0]; float32x4_t vX = M.r[0];
XMVECTOR vY = M.r[1]; float32x4_t vY = M.r[1];
XMVECTOR vZ = M.r[2]; float32x4_t vZ = M.r[2];
XMVECTOR vW = M.r[3]; float32x4_t vW = M.r[3];
// Test themselves to check for NaN // Test themselves to check for NaN
vX = vmvnq_u32(vceqq_f32(vX, vX)); uint32x4_t xmask = vmvnq_u32(vceqq_f32(vX, vX));
vY = vmvnq_u32(vceqq_f32(vY, vY)); uint32x4_t ymask = vmvnq_u32(vceqq_f32(vY, vY));
vZ = vmvnq_u32(vceqq_f32(vZ, vZ)); uint32x4_t zmask = vmvnq_u32(vceqq_f32(vZ, vZ));
vW = vmvnq_u32(vceqq_f32(vW, vW)); uint32x4_t wmask = vmvnq_u32(vceqq_f32(vW, vW));
// Or all the results // Or all the results
vX = vorrq_u32(vX, vZ); xmask = vorrq_u32(xmask, zmask);
vY = vorrq_u32(vY, vW); ymask = vorrq_u32(ymask, wmask);
vX = vorrq_u32(vX, vY); xmask = vorrq_u32(xmask, ymask);
// If any tested true, return true // If any tested true, return true
uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vX), vget_high_u8(vX)); uint8x8x2_t vTemp = vzip_u8(
uint16x4x2_t vTemp2 = vzip_u16(vTemp.val[0], vTemp.val[1]); vget_low_u8(vreinterpretq_u8_u32(xmask)),
uint32_t r = vget_lane_u32(vTemp2.val[1], 1); vget_high_u8(vreinterpretq_u8_u32(xmask)));
uint16x4x2_t vTemp2 = vzip_u16(vreinterpret_u16_u8(vTemp.val[0]), vreinterpret_u16_u8(vTemp.val[1]));
uint32_t r = vget_lane_u32(vreinterpret_u32_u16(vTemp2.val[1]), 1);
return (r != 0); return (r != 0);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// Load in registers // Load in registers
@ -87,7 +91,7 @@ inline bool XM_CALLCONV XMMatrixIsNaN(FXMMATRIX M) noexcept
#endif #endif
} }
#if !defined(_XM_NO_INTRINSICS_) && defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) #if !defined(_XM_NO_INTRINSICS_) && defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma float_control(pop) #pragma float_control(pop)
#endif #endif
@ -99,7 +103,8 @@ inline bool XM_CALLCONV XMMatrixIsInfinite(FXMMATRIX M) noexcept
#if defined(_XM_NO_INTRINSICS_) #if defined(_XM_NO_INTRINSICS_)
size_t i = 16; size_t i = 16;
auto pWork = reinterpret_cast<const uint32_t*>(&M.m[0][0]); auto pWork = reinterpret_cast<const uint32_t*>(&M.m[0][0]);
do { do
{
// Fetch value into integer unit // Fetch value into integer unit
uint32_t uTest = pWork[0]; uint32_t uTest = pWork[0];
// Remove sign // Remove sign
@ -110,27 +115,35 @@ inline bool XM_CALLCONV XMMatrixIsInfinite(FXMMATRIX M) noexcept
break; // INF found break; // INF found
} }
++pWork; // Next entry ++pWork; // Next entry
} while (--i); }
while (--i);
return (i != 0); // i == 0 if nothing matched return (i != 0); // i == 0 if nothing matched
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
// Load in registers
float32x4_t vX = M.r[0];
float32x4_t vY = M.r[1];
float32x4_t vZ = M.r[2];
float32x4_t vW = M.r[3];
// Mask off the sign bits // Mask off the sign bits
XMVECTOR vTemp1 = vandq_u32(M.r[0], g_XMAbsMask); vX = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(vX), g_XMAbsMask));
XMVECTOR vTemp2 = vandq_u32(M.r[1], g_XMAbsMask); vY = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(vY), g_XMAbsMask));
XMVECTOR vTemp3 = vandq_u32(M.r[2], g_XMAbsMask); vZ = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(vZ), g_XMAbsMask));
XMVECTOR vTemp4 = vandq_u32(M.r[3], g_XMAbsMask); vW = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(vW), g_XMAbsMask));
// Compare to infinity // Compare to infinity
vTemp1 = vceqq_f32(vTemp1, g_XMInfinity); uint32x4_t xmask = vceqq_f32(vX, g_XMInfinity);
vTemp2 = vceqq_f32(vTemp2, g_XMInfinity); uint32x4_t ymask = vceqq_f32(vY, g_XMInfinity);
vTemp3 = vceqq_f32(vTemp3, g_XMInfinity); uint32x4_t zmask = vceqq_f32(vZ, g_XMInfinity);
vTemp4 = vceqq_f32(vTemp4, g_XMInfinity); uint32x4_t wmask = vceqq_f32(vW, g_XMInfinity);
// Or the answers together // Or the answers together
vTemp1 = vorrq_u32(vTemp1, vTemp2); xmask = vorrq_u32(xmask, zmask);
vTemp3 = vorrq_u32(vTemp3, vTemp4); ymask = vorrq_u32(ymask, wmask);
vTemp1 = vorrq_u32(vTemp1, vTemp3); xmask = vorrq_u32(xmask, ymask);
// If any are infinity, the signs are true. // If any tested true, return true
uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vTemp1), vget_high_u8(vTemp1)); uint8x8x2_t vTemp = vzip_u8(
uint16x4x2_t vTemp5 = vzip_u16(vTemp.val[0], vTemp.val[1]); vget_low_u8(vreinterpretq_u8_u32(xmask)),
uint32_t r = vget_lane_u32(vTemp5.val[1], 1); vget_high_u8(vreinterpretq_u8_u32(xmask)));
uint16x4x2_t vTemp2 = vzip_u16(vreinterpret_u16_u8(vTemp.val[0]), vreinterpret_u16_u8(vTemp.val[1]));
uint32_t r = vget_lane_u32(vreinterpret_u32_u16(vTemp2.val[1]), 1);
return (r != 0); return (r != 0);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// Mask off the sign bits // Mask off the sign bits
@ -187,16 +200,16 @@ inline bool XM_CALLCONV XMMatrixIsIdentity(FXMMATRIX M) noexcept
uOne |= uZero; uOne |= uZero;
return (uOne == 0); return (uOne == 0);
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
XMVECTOR vTemp1 = vceqq_f32(M.r[0], g_XMIdentityR0); uint32x4_t xmask = vceqq_f32(M.r[0], g_XMIdentityR0);
XMVECTOR vTemp2 = vceqq_f32(M.r[1], g_XMIdentityR1); uint32x4_t ymask = vceqq_f32(M.r[1], g_XMIdentityR1);
XMVECTOR vTemp3 = vceqq_f32(M.r[2], g_XMIdentityR2); uint32x4_t zmask = vceqq_f32(M.r[2], g_XMIdentityR2);
XMVECTOR vTemp4 = vceqq_f32(M.r[3], g_XMIdentityR3); uint32x4_t wmask = vceqq_f32(M.r[3], g_XMIdentityR3);
vTemp1 = vandq_u32(vTemp1, vTemp2); xmask = vandq_u32(xmask, zmask);
vTemp3 = vandq_u32(vTemp3, vTemp4); ymask = vandq_u32(ymask, wmask);
vTemp1 = vandq_u32(vTemp1, vTemp3); xmask = vandq_u32(xmask, ymask);
uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vTemp1), vget_high_u8(vTemp1)); uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vreinterpretq_u8_u32(xmask)), vget_high_u8(vreinterpretq_u8_u32(xmask)));
uint16x4x2_t vTemp5 = vzip_u16(vTemp.val[0], vTemp.val[1]); uint16x4x2_t vTemp2 = vzip_u16(vreinterpret_u16_u8(vTemp.val[0]), vreinterpret_u16_u8(vTemp.val[1]));
uint32_t r = vget_lane_u32(vTemp5.val[1], 1); uint32_t r = vget_lane_u32(vreinterpret_u32_u16(vTemp2.val[1]), 1);
return (r == 0xFFFFFFFFU); return (r == 0xFFFFFFFFU);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
XMVECTOR vTemp1 = _mm_cmpeq_ps(M.r[0], g_XMIdentityR0); XMVECTOR vTemp1 = _mm_cmpeq_ps(M.r[0], g_XMIdentityR0);
@ -265,10 +278,10 @@ inline XMMATRIX XM_CALLCONV XMMatrixMultiply
float32x2_t VL = vget_low_f32(M1.r[0]); float32x2_t VL = vget_low_f32(M1.r[0]);
float32x2_t VH = vget_high_f32(M1.r[0]); float32x2_t VH = vget_high_f32(M1.r[0]);
// Perform the operation on the first row // Perform the operation on the first row
XMVECTOR vX = vmulq_lane_f32(M2.r[0], VL, 0); float32x4_t vX = vmulq_lane_f32(M2.r[0], VL, 0);
XMVECTOR vY = vmulq_lane_f32(M2.r[1], VL, 1); float32x4_t vY = vmulq_lane_f32(M2.r[1], VL, 1);
XMVECTOR vZ = vmlaq_lane_f32(vX, M2.r[2], VH, 0); float32x4_t vZ = vmlaq_lane_f32(vX, M2.r[2], VH, 0);
XMVECTOR vW = vmlaq_lane_f32(vY, M2.r[3], VH, 1); float32x4_t vW = vmlaq_lane_f32(vY, M2.r[3], VH, 1);
mResult.r[0] = vaddq_f32(vZ, vW); mResult.r[0] = vaddq_f32(vZ, vW);
// Repeat for the other 3 rows // Repeat for the other 3 rows
VL = vget_low_f32(M1.r[1]); VL = vget_low_f32(M1.r[1]);
@ -478,10 +491,10 @@ inline XMMATRIX XM_CALLCONV XMMatrixMultiplyTranspose
float32x2_t VL = vget_low_f32(M1.r[0]); float32x2_t VL = vget_low_f32(M1.r[0]);
float32x2_t VH = vget_high_f32(M1.r[0]); float32x2_t VH = vget_high_f32(M1.r[0]);
// Perform the operation on the first row // Perform the operation on the first row
XMVECTOR vX = vmulq_lane_f32(M2.r[0], VL, 0); float32x4_t vX = vmulq_lane_f32(M2.r[0], VL, 0);
XMVECTOR vY = vmulq_lane_f32(M2.r[1], VL, 1); float32x4_t vY = vmulq_lane_f32(M2.r[1], VL, 1);
XMVECTOR vZ = vmlaq_lane_f32(vX, M2.r[2], VH, 0); float32x4_t vZ = vmlaq_lane_f32(vX, M2.r[2], VH, 0);
XMVECTOR vW = vmlaq_lane_f32(vY, M2.r[3], VH, 1); float32x4_t vW = vmlaq_lane_f32(vY, M2.r[3], VH, 1);
float32x4_t r0 = vaddq_f32(vZ, vW); float32x4_t r0 = vaddq_f32(vZ, vW);
// Repeat for the other 3 rows // Repeat for the other 3 rows
VL = vget_low_f32(M1.r[1]); VL = vget_low_f32(M1.r[1]);
@ -1403,9 +1416,9 @@ inline XMMATRIX XM_CALLCONV XMMatrixScalingFromVector(FXMVECTOR Scale) noexcept
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
XMMATRIX M; XMMATRIX M;
M.r[0] = vandq_u32(Scale, g_XMMaskX); M.r[0] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(Scale), g_XMMaskX));
M.r[1] = vandq_u32(Scale, g_XMMaskY); M.r[1] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(Scale), g_XMMaskY));
M.r[2] = vandq_u32(Scale, g_XMMaskZ); M.r[2] = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(Scale), g_XMMaskZ));
M.r[3] = g_XMIdentityR3.v; M.r[3] = g_XMIdentityR3.v;
return M; return M;
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
@ -1455,12 +1468,12 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationX(float Angle) noexcept
float fCosAngle; float fCosAngle;
XMScalarSinCos(&fSinAngle, &fCosAngle, Angle); XMScalarSinCos(&fSinAngle, &fCosAngle, Angle);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMVECTOR T1 = vsetq_lane_f32(fCosAngle, Zero, 1); float32x4_t T1 = vsetq_lane_f32(fCosAngle, Zero, 1);
T1 = vsetq_lane_f32(fSinAngle, T1, 2); T1 = vsetq_lane_f32(fSinAngle, T1, 2);
XMVECTOR T2 = vsetq_lane_f32(-fSinAngle, Zero, 1); float32x4_t T2 = vsetq_lane_f32(-fSinAngle, Zero, 1);
T2 = vsetq_lane_f32(fCosAngle, T2, 2); T2 = vsetq_lane_f32(fCosAngle, T2, 2);
XMMATRIX M; XMMATRIX M;
@ -1528,12 +1541,12 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationY(float Angle) noexcept
float fCosAngle; float fCosAngle;
XMScalarSinCos(&fSinAngle, &fCosAngle, Angle); XMScalarSinCos(&fSinAngle, &fCosAngle, Angle);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMVECTOR T0 = vsetq_lane_f32(fCosAngle, Zero, 0); float32x4_t T0 = vsetq_lane_f32(fCosAngle, Zero, 0);
T0 = vsetq_lane_f32(-fSinAngle, T0, 2); T0 = vsetq_lane_f32(-fSinAngle, T0, 2);
XMVECTOR T2 = vsetq_lane_f32(fSinAngle, Zero, 0); float32x4_t T2 = vsetq_lane_f32(fSinAngle, Zero, 0);
T2 = vsetq_lane_f32(fCosAngle, T2, 2); T2 = vsetq_lane_f32(fCosAngle, T2, 2);
XMMATRIX M; XMMATRIX M;
@ -1601,12 +1614,12 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationZ(float Angle) noexcept
float fCosAngle; float fCosAngle;
XMScalarSinCos(&fSinAngle, &fCosAngle, Angle); XMScalarSinCos(&fSinAngle, &fCosAngle, Angle);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMVECTOR T0 = vsetq_lane_f32(fCosAngle, Zero, 0); float32x4_t T0 = vsetq_lane_f32(fCosAngle, Zero, 0);
T0 = vsetq_lane_f32(fSinAngle, T0, 1); T0 = vsetq_lane_f32(fSinAngle, T0, 1);
XMVECTOR T1 = vsetq_lane_f32(-fSinAngle, Zero, 0); float32x4_t T1 = vsetq_lane_f32(-fSinAngle, Zero, 0);
T1 = vsetq_lane_f32(fCosAngle, T1, 1); T1 = vsetq_lane_f32(fCosAngle, T1, 1);
XMMATRIX M; XMMATRIX M;
@ -1646,8 +1659,41 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationRollPitchYaw
float Roll float Roll
) noexcept ) noexcept
{ {
#if defined(_XM_NO_INTRINSICS_)
float cp = cosf(Pitch);
float sp = sinf(Pitch);
float cy = cosf(Yaw);
float sy = sinf(Yaw);
float cr = cosf(Roll);
float sr = sinf(Roll);
XMMATRIX M;
M.m[0][0] = cr * cy + sr * sp * sy;
M.m[0][1] = sr * cp;
M.m[0][2] = sr * sp * cy - cr * sy;
M.m[0][3] = 0.0f;
M.m[1][0] = cr * sp * sy - sr * cy;
M.m[1][1] = cr * cp;
M.m[1][2] = sr * sy + cr * sp * cy;
M.m[1][3] = 0.0f;
M.m[2][0] = cp * sy;
M.m[2][1] = -sp;
M.m[2][2] = cp * cy;
M.m[2][3] = 0.0f;
M.m[3][0] = 0.0f;
M.m[3][1] = 0.0f;
M.m[3][2] = 0.0f;
M.m[3][3] = 1.0f;
return M;
#else
XMVECTOR Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f); XMVECTOR Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f);
return XMMatrixRotationRollPitchYawFromVector(Angles); return XMMatrixRotationRollPitchYawFromVector(Angles);
#endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -1657,8 +1703,69 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationRollPitchYawFromVector
FXMVECTOR Angles // <Pitch, Yaw, Roll, undefined> FXMVECTOR Angles // <Pitch, Yaw, Roll, undefined>
) noexcept ) noexcept
{ {
XMVECTOR Q = XMQuaternionRotationRollPitchYawFromVector(Angles); #if defined(_XM_NO_INTRINSICS_)
return XMMatrixRotationQuaternion(Q); float cp = cosf(Angles.vector4_f32[0]);
float sp = sinf(Angles.vector4_f32[0]);
float cy = cosf(Angles.vector4_f32[1]);
float sy = sinf(Angles.vector4_f32[1]);
float cr = cosf(Angles.vector4_f32[2]);
float sr = sinf(Angles.vector4_f32[2]);
XMMATRIX M;
M.m[0][0] = cr * cy + sr * sp * sy;
M.m[0][1] = sr * cp;
M.m[0][2] = sr * sp * cy - cr * sy;
M.m[0][3] = 0.0f;
M.m[1][0] = cr * sp * sy - sr * cy;
M.m[1][1] = cr * cp;
M.m[1][2] = sr * sy + cr * sp * cy;
M.m[1][3] = 0.0f;
M.m[2][0] = cp * sy;
M.m[2][1] = -sp;
M.m[2][2] = cp * cy;
M.m[2][3] = 0.0f;
M.m[3][0] = 0.0f;
M.m[3][1] = 0.0f;
M.m[3][2] = 0.0f;
M.m[3][3] = 1.0f;
return M;
#else
static const XMVECTORF32 Sign = { { { 1.0f, -1.0f, -1.0f, 1.0f } } };
XMVECTOR SinAngles, CosAngles;
XMVectorSinCos(&SinAngles, &CosAngles, Angles);
XMVECTOR P0 = XMVectorPermute<XM_PERMUTE_1X, XM_PERMUTE_0Z, XM_PERMUTE_1Z, XM_PERMUTE_1X>(SinAngles, CosAngles);
XMVECTOR Y0 = XMVectorPermute<XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_1X, XM_PERMUTE_1Y>(SinAngles, CosAngles);
XMVECTOR P1 = XMVectorPermute<XM_PERMUTE_1Z, XM_PERMUTE_0Z, XM_PERMUTE_1Z, XM_PERMUTE_0Z>(SinAngles, CosAngles);
XMVECTOR Y1 = XMVectorPermute<XM_PERMUTE_1Y, XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_0Y>(SinAngles, CosAngles);
XMVECTOR P2 = XMVectorPermute<XM_PERMUTE_0Z, XM_PERMUTE_1Z, XM_PERMUTE_0Z, XM_PERMUTE_1Z>(SinAngles, CosAngles);
XMVECTOR P3 = XMVectorPermute<XM_PERMUTE_0Y, XM_PERMUTE_0Y, XM_PERMUTE_1Y, XM_PERMUTE_1Y>(SinAngles, CosAngles);
XMVECTOR Y2 = XMVectorSplatX(SinAngles);
XMVECTOR NS = XMVectorNegate(SinAngles);
XMVECTOR Q0 = XMVectorMultiply(P0, Y0);
XMVECTOR Q1 = XMVectorMultiply(P1, Sign.v);
Q1 = XMVectorMultiply(Q1, Y1);
XMVECTOR Q2 = XMVectorMultiply(P2, Y2);
Q2 = XMVectorMultiplyAdd(Q2, P3, Q1);
XMVECTOR V0 = XMVectorPermute<XM_PERMUTE_1X, XM_PERMUTE_0Y, XM_PERMUTE_1Z, XM_PERMUTE_0W>(Q0, Q2);
XMVECTOR V1 = XMVectorPermute<XM_PERMUTE_1Y, XM_PERMUTE_0Z, XM_PERMUTE_1W, XM_PERMUTE_0W>(Q0, Q2);
XMVECTOR V2 = XMVectorPermute<XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_0W, XM_PERMUTE_0W>(Q0, NS);
XMMATRIX M;
M.r[0] = XMVectorSelect(g_XMZero, V0, g_XMSelect1110.v);
M.r[1] = XMVectorSelect(g_XMZero, V1, g_XMSelect1110.v);
M.r[2] = XMVectorSelect(g_XMZero, V2, g_XMSelect1110.v);
M.r[3] = g_XMIdentityR3;
return M;
#endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -1770,8 +1877,42 @@ inline XMMATRIX XM_CALLCONV XMMatrixRotationAxis
inline XMMATRIX XM_CALLCONV XMMatrixRotationQuaternion(FXMVECTOR Quaternion) noexcept inline XMMATRIX XM_CALLCONV XMMatrixRotationQuaternion(FXMVECTOR Quaternion) noexcept
{ {
#if defined(_XM_NO_INTRINSICS_) || defined(_XM_ARM_NEON_INTRINSICS_) #if defined(_XM_NO_INTRINSICS_)
float qx = Quaternion.vector4_f32[0];
float qxx = qx * qx;
float qy = Quaternion.vector4_f32[1];
float qyy = qy * qy;
float qz = Quaternion.vector4_f32[2];
float qzz = qz * qz;
float qw = Quaternion.vector4_f32[3];
XMMATRIX M;
M.m[0][0] = 1.f - 2.f * qyy - 2.f * qzz;
M.m[0][1] = 2.f * qx * qy + 2.f * qz * qw;
M.m[0][2] = 2.f * qx * qz - 2.f * qy * qw;
M.m[0][3] = 0.f;
M.m[1][0] = 2.f * qx * qy - 2.f * qz * qw;
M.m[1][1] = 1.f - 2.f * qxx - 2.f * qzz;
M.m[1][2] = 2.f * qy * qz + 2.f * qx * qw;
M.m[1][3] = 0.f;
M.m[2][0] = 2.f * qx * qz + 2.f * qy * qw;
M.m[2][1] = 2.f * qy * qz - 2.f * qx * qw;
M.m[2][2] = 1.f - 2.f * qxx - 2.f * qyy;
M.m[2][3] = 0.f;
M.m[3][0] = 0.f;
M.m[3][1] = 0.f;
M.m[3][2] = 0.f;
M.m[3][3] = 1.0f;
return M;
#elif defined(_XM_ARM_NEON_INTRINSICS_)
static const XMVECTORF32 Constant1110 = { { { 1.0f, 1.0f, 1.0f, 0.0f } } }; static const XMVECTORF32 Constant1110 = { { { 1.0f, 1.0f, 1.0f, 0.0f } } };
XMVECTOR Q0 = XMVectorAdd(Quaternion, Quaternion); XMVECTOR Q0 = XMVectorAdd(Quaternion, Quaternion);
@ -2166,7 +2307,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveLH
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float TwoNearZ = NearZ + NearZ; float TwoNearZ = NearZ + NearZ;
float fRange = FarZ / (FarZ - NearZ); float fRange = FarZ / (FarZ - NearZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(TwoNearZ / ViewWidth, Zero, 0); M.r[0] = vsetq_lane_f32(TwoNearZ / ViewWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(TwoNearZ / ViewHeight, Zero, 1); M.r[1] = vsetq_lane_f32(TwoNearZ / ViewHeight, Zero, 1);
@ -2253,7 +2394,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveRH
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float TwoNearZ = NearZ + NearZ; float TwoNearZ = NearZ + NearZ;
float fRange = FarZ / (NearZ - FarZ); float fRange = FarZ / (NearZ - FarZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(TwoNearZ / ViewWidth, Zero, 0); M.r[0] = vsetq_lane_f32(TwoNearZ / ViewWidth, Zero, 0);
@ -2351,7 +2492,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveFovLH
float fRange = FarZ / (FarZ - NearZ); float fRange = FarZ / (FarZ - NearZ);
float Height = CosFov / SinFov; float Height = CosFov / SinFov;
float Width = Height / AspectRatio; float Width = Height / AspectRatio;
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(Width, Zero, 0); M.r[0] = vsetq_lane_f32(Width, Zero, 0);
@ -2378,10 +2519,10 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveFovLH
XMVECTOR vTemp = _mm_setzero_ps(); XMVECTOR vTemp = _mm_setzero_ps();
// Copy x only // Copy x only
vTemp = _mm_move_ss(vTemp, vValues); vTemp = _mm_move_ss(vTemp, vValues);
// CosFov / SinFov,0,0,0 // Height / AspectRatio,0,0,0
XMMATRIX M; XMMATRIX M;
M.r[0] = vTemp; M.r[0] = vTemp;
// 0,Height / AspectRatio,0,0 // 0,Height,0,0
vTemp = vValues; vTemp = vValues;
vTemp = _mm_and_ps(vTemp, g_XMMaskY); vTemp = _mm_and_ps(vTemp, g_XMMaskY);
M.r[1] = vTemp; M.r[1] = vTemp;
@ -2452,7 +2593,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveFovRH
float fRange = FarZ / (NearZ - FarZ); float fRange = FarZ / (NearZ - FarZ);
float Height = CosFov / SinFov; float Height = CosFov / SinFov;
float Width = Height / AspectRatio; float Width = Height / AspectRatio;
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(Width, Zero, 0); M.r[0] = vsetq_lane_f32(Width, Zero, 0);
@ -2478,10 +2619,10 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveFovRH
XMVECTOR vTemp = _mm_setzero_ps(); XMVECTOR vTemp = _mm_setzero_ps();
// Copy x only // Copy x only
vTemp = _mm_move_ss(vTemp, vValues); vTemp = _mm_move_ss(vTemp, vValues);
// CosFov / SinFov,0,0,0 // Height / AspectRatio,0,0,0
XMMATRIX M; XMMATRIX M;
M.r[0] = vTemp; M.r[0] = vTemp;
// 0,Height / AspectRatio,0,0 // 0,Height,0,0
vTemp = vValues; vTemp = vValues;
vTemp = _mm_and_ps(vTemp, g_XMMaskY); vTemp = _mm_and_ps(vTemp, g_XMMaskY);
M.r[1] = vTemp; M.r[1] = vTemp;
@ -2549,7 +2690,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveOffCenterLH
float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
float fRange = FarZ / (FarZ - NearZ); float fRange = FarZ / (FarZ - NearZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(TwoNearZ * ReciprocalWidth, Zero, 0); M.r[0] = vsetq_lane_f32(TwoNearZ * ReciprocalWidth, Zero, 0);
@ -2647,7 +2788,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixPerspectiveOffCenterRH
float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
float fRange = FarZ / (NearZ - FarZ); float fRange = FarZ / (NearZ - FarZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(TwoNearZ * ReciprocalWidth, Zero, 0); M.r[0] = vsetq_lane_f32(TwoNearZ * ReciprocalWidth, Zero, 0);
@ -2737,7 +2878,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicLH
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float fRange = 1.0f / (FarZ - NearZ); float fRange = 1.0f / (FarZ - NearZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(2.0f / ViewWidth, Zero, 0); M.r[0] = vsetq_lane_f32(2.0f / ViewWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(2.0f / ViewHeight, Zero, 1); M.r[1] = vsetq_lane_f32(2.0f / ViewHeight, Zero, 1);
@ -2821,7 +2962,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicRH
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
float fRange = 1.0f / (NearZ - FarZ); float fRange = 1.0f / (NearZ - FarZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(2.0f / ViewWidth, Zero, 0); M.r[0] = vsetq_lane_f32(2.0f / ViewWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(2.0f / ViewHeight, Zero, 1); M.r[1] = vsetq_lane_f32(2.0f / ViewHeight, Zero, 1);
@ -2910,7 +3051,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicOffCenterLH
float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
float fRange = 1.0f / (FarZ - NearZ); float fRange = 1.0f / (FarZ - NearZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(ReciprocalWidth + ReciprocalWidth, Zero, 0); M.r[0] = vsetq_lane_f32(ReciprocalWidth + ReciprocalWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(ReciprocalHeight + ReciprocalHeight, Zero, 1); M.r[1] = vsetq_lane_f32(ReciprocalHeight + ReciprocalHeight, Zero, 1);
@ -3010,7 +3151,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicOffCenterRH
float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
float fRange = 1.0f / (NearZ - FarZ); float fRange = 1.0f / (NearZ - FarZ);
const XMVECTOR Zero = vdupq_n_f32(0); const float32x4_t Zero = vdupq_n_f32(0);
XMMATRIX M; XMMATRIX M;
M.r[0] = vsetq_lane_f32(ReciprocalWidth + ReciprocalWidth, Zero, 0); M.r[0] = vsetq_lane_f32(ReciprocalWidth + ReciprocalWidth, Zero, 0);
M.r[1] = vsetq_lane_f32(ReciprocalHeight + ReciprocalHeight, Zero, 1); M.r[1] = vsetq_lane_f32(ReciprocalHeight + ReciprocalHeight, Zero, 1);
@ -3072,7 +3213,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicOffCenterRH
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline XMMATRIX::XMMATRIX inline XMMATRIX::XMMATRIX
( (
@ -3164,7 +3305,7 @@ inline XMMATRIX& XMMATRIX::operator/= (float S) noexcept
r[3] = XMVectorDivide(r[3], vS); r[3] = XMVectorDivide(r[3], vS);
return *this; return *this;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || __aarch64__ #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__
float32x4_t vS = vdupq_n_f32(S); float32x4_t vS = vdupq_n_f32(S);
r[0] = vdivq_f32(r[0], vS); r[0] = vdivq_f32(r[0], vS);
r[1] = vdivq_f32(r[1], vS); r[1] = vdivq_f32(r[1], vS);
@ -3178,7 +3319,7 @@ inline XMMATRIX& XMMATRIX::operator/= (float S) noexcept
R0 = vmul_f32(S0, R0); R0 = vmul_f32(S0, R0);
S0 = vrecps_f32(R0, vS); S0 = vrecps_f32(R0, vS);
R0 = vmul_f32(S0, R0); R0 = vmul_f32(S0, R0);
float32x4_t Reciprocal = vcombine_u32(R0, R0); float32x4_t Reciprocal = vcombine_f32(R0, R0);
r[0] = vmulq_f32(r[0], Reciprocal); r[0] = vmulq_f32(r[0], Reciprocal);
r[1] = vmulq_f32(r[1], Reciprocal); r[1] = vmulq_f32(r[1], Reciprocal);
r[2] = vmulq_f32(r[2], Reciprocal); r[2] = vmulq_f32(r[2], Reciprocal);
@ -3251,7 +3392,7 @@ inline XMMATRIX XMMATRIX::operator/ (float S) const noexcept
R.r[3] = XMVectorDivide(r[3], vS); R.r[3] = XMVectorDivide(r[3], vS);
return R; return R;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || __aarch64__ #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__
float32x4_t vS = vdupq_n_f32(S); float32x4_t vS = vdupq_n_f32(S);
XMMATRIX R; XMMATRIX R;
R.r[0] = vdivq_f32(r[0], vS); R.r[0] = vdivq_f32(r[0], vS);
@ -3266,7 +3407,7 @@ inline XMMATRIX XMMATRIX::operator/ (float S) const noexcept
R0 = vmul_f32(S0, R0); R0 = vmul_f32(S0, R0);
S0 = vrecps_f32(R0, vS); S0 = vrecps_f32(R0, vS);
R0 = vmul_f32(S0, R0); R0 = vmul_f32(S0, R0);
float32x4_t Reciprocal = vcombine_u32(R0, R0); float32x4_t Reciprocal = vcombine_f32(R0, R0);
XMMATRIX R; XMMATRIX R;
R.r[0] = vmulq_f32(r[0], Reciprocal); R.r[0] = vmulq_f32(r[0], Reciprocal);
R.r[1] = vmulq_f32(r[1], Reciprocal); R.r[1] = vmulq_f32(r[1], Reciprocal);
@ -3291,7 +3432,7 @@ inline XMMATRIX XM_CALLCONV operator*
( (
float S, float S,
FXMMATRIX M FXMMATRIX M
) noexcept ) noexcept
{ {
XMMATRIX R; XMMATRIX R;
R.r[0] = XMVectorScale(M.r[0], S); R.r[0] = XMVectorScale(M.r[0], S);
@ -3307,7 +3448,7 @@ inline XMMATRIX XM_CALLCONV operator*
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
_Use_decl_annotations_ _Use_decl_annotations_
inline XMFLOAT3X3::XMFLOAT3X3(const float* pArray) noexcept inline XMFLOAT3X3::XMFLOAT3X3(const float* pArray) noexcept
{ {
@ -3327,7 +3468,7 @@ inline XMFLOAT3X3::XMFLOAT3X3(const float* pArray) noexcept
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
_Use_decl_annotations_ _Use_decl_annotations_
inline XMFLOAT4X3::XMFLOAT4X3(const float* pArray) noexcept inline XMFLOAT4X3::XMFLOAT4X3(const float* pArray) noexcept
{ {
@ -3384,7 +3525,7 @@ inline XMFLOAT3X4::XMFLOAT3X4(const float* pArray) noexcept
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
_Use_decl_annotations_ _Use_decl_annotations_
inline XMFLOAT4X4::XMFLOAT4X4(const float* pArray) noexcept inline XMFLOAT4X4::XMFLOAT4X4(const float* pArray) noexcept
{ {

View File

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
// DirectXMathMisc.inl -- SIMD C++ Math library // DirectXMathMisc.inl -- SIMD C++ Math library
// //
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License. // Licensed under the MIT License.
// //
// http://go.microsoft.com/fwlink/?LinkID=615560 // https://go.microsoft.com/fwlink/?LinkID=615560
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
#pragma once #pragma once
@ -15,11 +15,11 @@
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Comparison operations // Comparison operations
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline bool XM_CALLCONV XMQuaternionEqual inline bool XM_CALLCONV XMQuaternionEqual
( (
@ -120,12 +120,12 @@ inline XMVECTOR XM_CALLCONV XMQuaternionMultiply
vResult = vmlaq_f32(vResult, Q2X, ControlWZYX); vResult = vmlaq_f32(vResult, Q2X, ControlWZYX);
// Mul by Q1ZWXY // Mul by Q1ZWXY
vTemp = vrev64q_u32(vTemp); vTemp = vreinterpretq_f32_u32(vrev64q_u32(vreinterpretq_u32_f32(vTemp)));
Q2Y = vmulq_f32(Q2Y, vTemp); Q2Y = vmulq_f32(Q2Y, vTemp);
vResult = vmlaq_f32(vResult, Q2Y, ControlZWXY); vResult = vmlaq_f32(vResult, Q2Y, ControlZWXY);
// Mul by Q1YXWZ // Mul by Q1YXWZ
vTemp = vrev64q_u32(vTemp); vTemp = vreinterpretq_f32_u32(vrev64q_u32(vreinterpretq_u32_f32(vTemp)));
vTemp = vcombine_f32(vget_high_f32(vTemp), vget_low_f32(vTemp)); vTemp = vcombine_f32(vget_high_f32(vTemp), vget_low_f32(vTemp));
Q2Z = vmulq_f32(Q2Z, vTemp); Q2Z = vmulq_f32(Q2Z, vTemp);
vResult = vmlaq_f32(vResult, Q2Z, ControlYXWZ); vResult = vmlaq_f32(vResult, Q2Z, ControlYXWZ);
@ -228,8 +228,6 @@ inline XMVECTOR XM_CALLCONV XMQuaternionConjugate(FXMVECTOR Q) noexcept
inline XMVECTOR XM_CALLCONV XMQuaternionInverse(FXMVECTOR Q) noexcept inline XMVECTOR XM_CALLCONV XMQuaternionInverse(FXMVECTOR Q) noexcept
{ {
const XMVECTOR Zero = XMVectorZero();
XMVECTOR L = XMVector4LengthSq(Q); XMVECTOR L = XMVector4LengthSq(Q);
XMVECTOR Conjugate = XMQuaternionConjugate(Q); XMVECTOR Conjugate = XMQuaternionConjugate(Q);
@ -237,7 +235,7 @@ inline XMVECTOR XM_CALLCONV XMQuaternionInverse(FXMVECTOR Q) noexcept
XMVECTOR Result = XMVectorDivide(Conjugate, L); XMVECTOR Result = XMVectorDivide(Conjugate, L);
Result = XMVectorSelect(Result, Zero, Control); Result = XMVectorSelect(Result, g_XMZero, Control);
return Result; return Result;
} }
@ -582,9 +580,30 @@ inline XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYaw
float Roll float Roll
) noexcept ) noexcept
{ {
#if defined(_XM_NO_INTRINSICS_)
const float halfpitch = Pitch * 0.5f;
float cp = cosf(halfpitch);
float sp = sinf(halfpitch);
const float halfyaw = Yaw * 0.5f;
float cy = cosf(halfyaw);
float sy = sinf(halfyaw);
const float halfroll = Roll * 0.5f;
float cr = cosf(halfroll);
float sr = sinf(halfroll);
XMVECTORF32 vResult = { { {
cr * sp * cy + sr * cp * sy,
cr * cp * sy - sr * sp * cy,
sr * cp * cy - cr * sp * sy,
cr * cp * cy + sr * sp * sy
} } };
return vResult;
#else
XMVECTOR Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f); XMVECTOR Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f);
XMVECTOR Q = XMQuaternionRotationRollPitchYawFromVector(Angles); return XMQuaternionRotationRollPitchYawFromVector(Angles);
return Q; #endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -594,6 +613,27 @@ inline XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYawFromVector
FXMVECTOR Angles // <Pitch, Yaw, Roll, 0> FXMVECTOR Angles // <Pitch, Yaw, Roll, 0>
) noexcept ) noexcept
{ {
#if defined(_XM_NO_INTRINSICS_)
const float halfpitch = Angles.vector4_f32[0] * 0.5f;
float cp = cosf(halfpitch);
float sp = sinf(halfpitch);
const float halfyaw = Angles.vector4_f32[1] * 0.5f;
float cy = cosf(halfyaw);
float sy = sinf(halfyaw);
const float halfroll = Angles.vector4_f32[2] * 0.5f;
float cr = cosf(halfroll);
float sr = sinf(halfroll);
XMVECTORF32 vResult = { { {
cr * sp * cy + sr * cp * sy,
cr * cp * sy - sr * sp * cy,
sr * cp * cy - cr * sp * sy,
cr * cp * cy + sr * sp * sy
} } };
return vResult;
#else
static const XMVECTORF32 Sign = { { { 1.0f, -1.0f, -1.0f, 1.0f } } }; static const XMVECTORF32 Sign = { { { 1.0f, -1.0f, -1.0f, 1.0f } } };
XMVECTOR HalfAngles = XMVectorMultiply(Angles, g_XMOneHalf.v); XMVECTOR HalfAngles = XMVectorMultiply(Angles, g_XMOneHalf.v);
@ -615,6 +655,7 @@ inline XMVECTOR XM_CALLCONV XMQuaternionRotationRollPitchYawFromVector
XMVECTOR Q = XMVectorMultiplyAdd(Q1, R1, Q0); XMVECTOR Q = XMVectorMultiplyAdd(Q1, R1, Q0);
return Q; return Q;
#endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -728,74 +769,74 @@ inline XMVECTOR XM_CALLCONV XMQuaternionRotationMatrix(FXMMATRIX M) noexcept
static const XMVECTORU32 Select0110 = { { { XM_SELECT_0, XM_SELECT_1, XM_SELECT_1, XM_SELECT_0 } } }; static const XMVECTORU32 Select0110 = { { { XM_SELECT_0, XM_SELECT_1, XM_SELECT_1, XM_SELECT_0 } } };
static const XMVECTORU32 Select0010 = { { { XM_SELECT_0, XM_SELECT_0, XM_SELECT_1, XM_SELECT_0 } } }; static const XMVECTORU32 Select0010 = { { { XM_SELECT_0, XM_SELECT_0, XM_SELECT_1, XM_SELECT_0 } } };
XMVECTOR r0 = M.r[0]; float32x4_t r0 = M.r[0];
XMVECTOR r1 = M.r[1]; float32x4_t r1 = M.r[1];
XMVECTOR r2 = M.r[2]; float32x4_t r2 = M.r[2];
XMVECTOR r00 = vdupq_lane_f32(vget_low_f32(r0), 0); float32x4_t r00 = vdupq_lane_f32(vget_low_f32(r0), 0);
XMVECTOR r11 = vdupq_lane_f32(vget_low_f32(r1), 1); float32x4_t r11 = vdupq_lane_f32(vget_low_f32(r1), 1);
XMVECTOR r22 = vdupq_lane_f32(vget_high_f32(r2), 0); float32x4_t r22 = vdupq_lane_f32(vget_high_f32(r2), 0);
// x^2 >= y^2 equivalent to r11 - r00 <= 0 // x^2 >= y^2 equivalent to r11 - r00 <= 0
XMVECTOR r11mr00 = vsubq_f32(r11, r00); float32x4_t r11mr00 = vsubq_f32(r11, r00);
XMVECTOR x2gey2 = vcleq_f32(r11mr00, g_XMZero); uint32x4_t x2gey2 = vcleq_f32(r11mr00, g_XMZero);
// z^2 >= w^2 equivalent to r11 + r00 <= 0 // z^2 >= w^2 equivalent to r11 + r00 <= 0
XMVECTOR r11pr00 = vaddq_f32(r11, r00); float32x4_t r11pr00 = vaddq_f32(r11, r00);
XMVECTOR z2gew2 = vcleq_f32(r11pr00, g_XMZero); uint32x4_t z2gew2 = vcleq_f32(r11pr00, g_XMZero);
// x^2 + y^2 >= z^2 + w^2 equivalent to r22 <= 0 // x^2 + y^2 >= z^2 + w^2 equivalent to r22 <= 0
XMVECTOR x2py2gez2pw2 = vcleq_f32(r22, g_XMZero); uint32x4_t x2py2gez2pw2 = vcleq_f32(r22, g_XMZero);
// (4*x^2, 4*y^2, 4*z^2, 4*w^2) // (4*x^2, 4*y^2, 4*z^2, 4*w^2)
XMVECTOR t0 = vmulq_f32(XMPMMP, r00); float32x4_t t0 = vmulq_f32(XMPMMP, r00);
XMVECTOR x2y2z2w2 = vmlaq_f32(t0, XMMPMP, r11); float32x4_t x2y2z2w2 = vmlaq_f32(t0, XMMPMP, r11);
x2y2z2w2 = vmlaq_f32(x2y2z2w2, XMMMPP, r22); x2y2z2w2 = vmlaq_f32(x2y2z2w2, XMMMPP, r22);
x2y2z2w2 = vaddq_f32(x2y2z2w2, g_XMOne); x2y2z2w2 = vaddq_f32(x2y2z2w2, g_XMOne);
// (r01, r02, r12, r11) // (r01, r02, r12, r11)
t0 = vextq_f32(r0, r0, 1); t0 = vextq_f32(r0, r0, 1);
XMVECTOR t1 = vextq_f32(r1, r1, 1); float32x4_t t1 = vextq_f32(r1, r1, 1);
t0 = vcombine_f32(vget_low_f32(t0), vrev64_f32(vget_low_f32(t1))); t0 = vcombine_f32(vget_low_f32(t0), vrev64_f32(vget_low_f32(t1)));
// (r10, r20, r21, r10) // (r10, r20, r21, r10)
t1 = vextq_f32(r2, r2, 3); t1 = vextq_f32(r2, r2, 3);
XMVECTOR r10 = vdupq_lane_f32(vget_low_f32(r1), 0); float32x4_t r10 = vdupq_lane_f32(vget_low_f32(r1), 0);
t1 = vbslq_f32(Select0110, t1, r10); t1 = vbslq_f32(Select0110, t1, r10);
// (4*x*y, 4*x*z, 4*y*z, unused) // (4*x*y, 4*x*z, 4*y*z, unused)
XMVECTOR xyxzyz = vaddq_f32(t0, t1); float32x4_t xyxzyz = vaddq_f32(t0, t1);
// (r21, r20, r10, r10) // (r21, r20, r10, r10)
t0 = vcombine_f32(vrev64_f32(vget_low_f32(r2)), vget_low_f32(r10)); t0 = vcombine_f32(vrev64_f32(vget_low_f32(r2)), vget_low_f32(r10));
// (r12, r02, r01, r12) // (r12, r02, r01, r12)
XMVECTOR t2 = vcombine_f32(vrev64_f32(vget_high_f32(r0)), vrev64_f32(vget_low_f32(r0))); float32x4_t t2 = vcombine_f32(vrev64_f32(vget_high_f32(r0)), vrev64_f32(vget_low_f32(r0)));
XMVECTOR t3 = vdupq_lane_f32(vget_high_f32(r1), 0); float32x4_t t3 = vdupq_lane_f32(vget_high_f32(r1), 0);
t1 = vbslq_f32(Select0110, t2, t3); t1 = vbslq_f32(Select0110, t2, t3);
// (4*x*w, 4*y*w, 4*z*w, unused) // (4*x*w, 4*y*w, 4*z*w, unused)
XMVECTOR xwywzw = vsubq_f32(t0, t1); float32x4_t xwywzw = vsubq_f32(t0, t1);
xwywzw = vmulq_f32(XMMPMP, xwywzw); xwywzw = vmulq_f32(XMMPMP, xwywzw);
// (4*x*x, 4*x*y, 4*x*z, 4*x*w) // (4*x*x, 4*x*y, 4*x*z, 4*x*w)
t0 = vextq_f32(xyxzyz, xyxzyz, 3); t0 = vextq_f32(xyxzyz, xyxzyz, 3);
t1 = vbslq_f32(Select0110, t0, x2y2z2w2); t1 = vbslq_f32(Select0110, t0, x2y2z2w2);
t2 = vdupq_lane_f32(vget_low_f32(xwywzw), 0); t2 = vdupq_lane_f32(vget_low_f32(xwywzw), 0);
XMVECTOR tensor0 = vbslq_f32(g_XMSelect1110, t1, t2); float32x4_t tensor0 = vbslq_f32(g_XMSelect1110, t1, t2);
// (4*y*x, 4*y*y, 4*y*z, 4*y*w) // (4*y*x, 4*y*y, 4*y*z, 4*y*w)
t0 = vbslq_f32(g_XMSelect1011, xyxzyz, x2y2z2w2); t0 = vbslq_f32(g_XMSelect1011, xyxzyz, x2y2z2w2);
t1 = vdupq_lane_f32(vget_low_f32(xwywzw), 1); t1 = vdupq_lane_f32(vget_low_f32(xwywzw), 1);
XMVECTOR tensor1 = vbslq_f32(g_XMSelect1110, t0, t1); float32x4_t tensor1 = vbslq_f32(g_XMSelect1110, t0, t1);
// (4*z*x, 4*z*y, 4*z*z, 4*z*w) // (4*z*x, 4*z*y, 4*z*z, 4*z*w)
t0 = vextq_f32(xyxzyz, xyxzyz, 1); t0 = vextq_f32(xyxzyz, xyxzyz, 1);
t1 = vcombine_f32(vget_low_f32(t0), vrev64_f32(vget_high_f32(xwywzw))); t1 = vcombine_f32(vget_low_f32(t0), vrev64_f32(vget_high_f32(xwywzw)));
XMVECTOR tensor2 = vbslq_f32(Select0010, x2y2z2w2, t1); float32x4_t tensor2 = vbslq_f32(Select0010, x2y2z2w2, t1);
// (4*w*x, 4*w*y, 4*w*z, 4*w*w) // (4*w*x, 4*w*y, 4*w*z, 4*w*w)
XMVECTOR tensor3 = vbslq_f32(g_XMSelect1110, xwywzw, x2y2z2w2); float32x4_t tensor3 = vbslq_f32(g_XMSelect1110, xwywzw, x2y2z2w2);
// Select the row of the tensor-product matrix that has the largest // Select the row of the tensor-product matrix that has the largest
// magnitude. // magnitude.
@ -925,11 +966,11 @@ inline void XM_CALLCONV XMQuaternionToAxisAngle
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Comparison operations // Comparison operations
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline bool XM_CALLCONV XMPlaneEqual inline bool XM_CALLCONV XMPlaneEqual
( (
@ -1176,7 +1217,7 @@ inline void XM_CALLCONV XMPlaneIntersectPlane
inline XMVECTOR XM_CALLCONV XMPlaneTransform inline XMVECTOR XM_CALLCONV XMPlaneTransform
( (
FXMVECTOR P, FXMVECTOR P,
FXMMATRIX M FXMMATRIX ITM
) noexcept ) noexcept
{ {
XMVECTOR W = XMVectorSplatW(P); XMVECTOR W = XMVectorSplatW(P);
@ -1184,10 +1225,10 @@ inline XMVECTOR XM_CALLCONV XMPlaneTransform
XMVECTOR Y = XMVectorSplatY(P); XMVECTOR Y = XMVectorSplatY(P);
XMVECTOR X = XMVectorSplatX(P); XMVECTOR X = XMVectorSplatX(P);
XMVECTOR Result = XMVectorMultiply(W, M.r[3]); XMVECTOR Result = XMVectorMultiply(W, ITM.r[3]);
Result = XMVectorMultiplyAdd(Z, M.r[2], Result); Result = XMVectorMultiplyAdd(Z, ITM.r[2], Result);
Result = XMVectorMultiplyAdd(Y, M.r[1], Result); Result = XMVectorMultiplyAdd(Y, ITM.r[1], Result);
Result = XMVectorMultiplyAdd(X, M.r[0], Result); Result = XMVectorMultiplyAdd(X, ITM.r[0], Result);
return Result; return Result;
} }
@ -1200,7 +1241,7 @@ inline XMFLOAT4* XM_CALLCONV XMPlaneTransformStream
const XMFLOAT4* pInputStream, const XMFLOAT4* pInputStream,
size_t InputStride, size_t InputStride,
size_t PlaneCount, size_t PlaneCount,
FXMMATRIX M FXMMATRIX ITM
) noexcept ) noexcept
{ {
return XMVector4TransformStream(pOutputStream, return XMVector4TransformStream(pOutputStream,
@ -1208,7 +1249,7 @@ inline XMFLOAT4* XM_CALLCONV XMPlaneTransformStream
pInputStream, pInputStream,
InputStride, InputStride,
PlaneCount, PlaneCount,
M); ITM);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -1257,11 +1298,11 @@ inline XMVECTOR XM_CALLCONV XMPlaneFromPoints
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Comparison operations // Comparison operations
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline bool XM_CALLCONV XMColorEqual inline bool XM_CALLCONV XMColorEqual
( (
@ -1358,8 +1399,8 @@ inline XMVECTOR XM_CALLCONV XMColorNegative(FXMVECTOR vColor) noexcept
} } }; } } };
return vResult.v; return vResult.v;
#elif defined(_XM_ARM_NEON_INTRINSICS_) #elif defined(_XM_ARM_NEON_INTRINSICS_)
XMVECTOR vTemp = veorq_u32(vColor, g_XMNegate3); uint32x4_t vTemp = veorq_u32(vreinterpretq_u32_f32(vColor), g_XMNegate3);
return vaddq_f32(vTemp, g_XMOne3); return vaddq_f32(vreinterpretq_f32_u32(vTemp), g_XMOne3);
#elif defined(_XM_SSE_INTRINSICS_) #elif defined(_XM_SSE_INTRINSICS_)
// Negate only x,y and z. // Negate only x,y and z.
XMVECTOR vTemp = _mm_xor_ps(vColor, g_XMNegate3); XMVECTOR vTemp = _mm_xor_ps(vColor, g_XMNegate3);
@ -1520,7 +1561,7 @@ inline XMVECTOR XM_CALLCONV XMColorRGBToHSL(FXMVECTOR rgb) noexcept
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace Internal namespace MathInternal
{ {
inline XMVECTOR XM_CALLCONV XMColorHue2Clr(FXMVECTOR p, FXMVECTOR q, FXMVECTOR h) noexcept inline XMVECTOR XM_CALLCONV XMColorHue2Clr(FXMVECTOR p, FXMVECTOR q, FXMVECTOR h) noexcept
@ -1558,7 +1599,7 @@ namespace Internal
return p; return p;
} }
} // namespace Internal } // namespace MathInternal
inline XMVECTOR XM_CALLCONV XMColorHSLToRGB(FXMVECTOR hsl) noexcept inline XMVECTOR XM_CALLCONV XMColorHSLToRGB(FXMVECTOR hsl) noexcept
{ {
@ -1588,9 +1629,9 @@ inline XMVECTOR XM_CALLCONV XMColorHSLToRGB(FXMVECTOR hsl) noexcept
XMVECTOR p = XMVectorSubtract(XMVectorMultiply(g_XMTwo, l), q); XMVECTOR p = XMVectorSubtract(XMVectorMultiply(g_XMTwo, l), q);
XMVECTOR r = DirectX::Internal::XMColorHue2Clr(p, q, XMVectorAdd(h, oneThird)); XMVECTOR r = DirectX::MathInternal::XMColorHue2Clr(p, q, XMVectorAdd(h, oneThird));
XMVECTOR g = DirectX::Internal::XMColorHue2Clr(p, q, h); XMVECTOR g = DirectX::MathInternal::XMColorHue2Clr(p, q, h);
XMVECTOR b = DirectX::Internal::XMColorHue2Clr(p, q, XMVectorSubtract(h, oneThird)); XMVECTOR b = DirectX::MathInternal::XMColorHue2Clr(p, q, XMVectorSubtract(h, oneThird));
XMVECTOR rg = XMVectorSelect(g, r, g_XMSelect1000); XMVECTOR rg = XMVectorSelect(g, r, g_XMSelect1000);
XMVECTOR ba = XMVectorSelect(hsl, b, g_XMSelect1110); XMVECTOR ba = XMVectorSelect(hsl, b, g_XMSelect1110);
@ -1779,6 +1820,33 @@ inline XMVECTOR XM_CALLCONV XMColorYUVToRGB_HD(FXMVECTOR yuv) noexcept
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline XMVECTOR XM_CALLCONV XMColorRGBToYUV_UHD(FXMVECTOR rgb) noexcept
{
static const XMVECTORF32 Scale0 = { { { 0.2627f, -0.1215f, 0.6150f, 0.0f } } };
static const XMVECTORF32 Scale1 = { { { 0.6780f, -0.3136f, -0.5655f, 0.0f } } };
static const XMVECTORF32 Scale2 = { { { 0.0593f, 0.4351f, -0.0495f, 0.0f } } };
XMMATRIX M(Scale0, Scale1, Scale2, g_XMZero);
XMVECTOR clr = XMVector3Transform(rgb, M);
return XMVectorSelect(rgb, clr, g_XMSelect1110);
}
//------------------------------------------------------------------------------
inline XMVECTOR XM_CALLCONV XMColorYUVToRGB_UHD(FXMVECTOR yuv) noexcept
{
static const XMVECTORF32 Scale1 = { { { 0.0f, -0.1891f, 2.1620f, 0.0f } } };
static const XMVECTORF32 Scale2 = { { { 1.1989f, -0.4645f, 0.0f, 0.0f } } };
XMMATRIX M(g_XMOne, Scale1, Scale2, g_XMZero);
XMVECTOR clr = XMVector3Transform(yuv, M);
return XMVectorSelect(yuv, clr, g_XMSelect1110);
}
//------------------------------------------------------------------------------
inline XMVECTOR XM_CALLCONV XMColorRGBToXYZ(FXMVECTOR rgb) noexcept inline XMVECTOR XM_CALLCONV XMColorRGBToXYZ(FXMVECTOR rgb) noexcept
{ {
static const XMVECTORF32 Scale0 = { { { 0.4887180f, 0.1762044f, 0.0000000f, 0.0f } } }; static const XMVECTORF32 Scale0 = { { { 0.4887180f, 0.1762044f, 0.0000000f, 0.0f } } };
@ -1899,13 +1967,13 @@ inline XMVECTOR XM_CALLCONV XMColorSRGBToRGB(FXMVECTOR srgb) noexcept
* *
****************************************************************************/ ****************************************************************************/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline bool XMVerifyCPUSupport() noexcept inline bool XMVerifyCPUSupport() noexcept
{ {
#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #if defined(_XM_SSE_INTRINSICS_) && !defined(__powerpc64__) && !defined(_XM_NO_INTRINSICS_)
int CPUInfo[4] = { -1 }; int CPUInfo[4] = { -1 };
#if defined(__clang__) || defined(__GNUC__) #if (defined(__clang__) || defined(__GNUC__)) && !defined(_MSC_VER) && !defined(__MINGW32__)
__cpuid(0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]); __cpuid(0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else #else
__cpuid(CPUInfo, 0); __cpuid(CPUInfo, 0);
@ -1919,7 +1987,7 @@ inline bool XMVerifyCPUSupport() noexcept
return false; return false;
#endif #endif
#if defined(__clang__) || defined(__GNUC__) #if (defined(__clang__) || defined(__GNUC__)) && !defined(_MSC_VER) && !defined(__MINGW32__)
__cpuid(1, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]); __cpuid(1, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else #else
__cpuid(CPUInfo, 1); __cpuid(CPUInfo, 1);
@ -1954,7 +2022,7 @@ inline bool XMVerifyCPUSupport() noexcept
return false; // No SSE2/SSE support return false; // No SSE2/SSE support
#if defined(__AVX2__) || defined(_XM_AVX2_INTRINSICS_) #if defined(__AVX2__) || defined(_XM_AVX2_INTRINSICS_)
#if defined(__clang__) || defined(__GNUC__) #if (defined(__clang__) || defined(__GNUC__)) && !defined(_MSC_VER) && !defined(__MINGW32__)
__cpuid_count(7, 0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]); __cpuid_count(7, 0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else #else
__cpuidex(CPUInfo, 7, 0); __cpuidex(CPUInfo, 7, 0);

View File

@ -3,7 +3,7 @@
#include "memory.h" #include "memory.h"
#include "node.h" #include "node.h"
#include "directxmath/directxmath.h" #include "directxmath/DirectXMath.h"
size_t node_alloc(int count) size_t node_alloc(int count)
{ {

View File