#828 Implemented the SpeckleMesh which extends three's Mesh and corrects the raycasting implementation to work with the positions encoded as pairs of lows and highs
This commit is contained in:
@@ -40,5 +40,5 @@ sandbox.makeSceneUI()
|
||||
sandbox.makeFilteringUI()
|
||||
// Load demo object
|
||||
sandbox.loadUrl(
|
||||
'https://latest.speckle.dev/streams/3ed8357f29/commits/d10f2af1ce?c=%5B44.9036,-24.475,37.28273,46.97876,-2.90317,-1.54942,0,1%5D'
|
||||
'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8?c=%5B-7.66134,10.82932,6.41935,-0.07739,-13.88552,1.8697,0,1%5D'
|
||||
)
|
||||
|
||||
@@ -9,7 +9,7 @@ import { NodeRenderView } from '../tree/NodeRenderView'
|
||||
import { Batch, BatchUpdateRange, GeometryType } from './Batch'
|
||||
import PointBatch from './PointBatch'
|
||||
import { FilterMaterialType } from '../FilteringManager'
|
||||
import { Material, WebGLRenderer } from 'three'
|
||||
import { WebGLRenderer } from 'three'
|
||||
import { FilterMaterial } from '../FilteringManager'
|
||||
|
||||
export default class Batcher {
|
||||
@@ -170,8 +170,14 @@ export default class Batcher {
|
||||
const batchIds = [...Array.from(new Set(rvs.map((value) => value.batchId)))]
|
||||
for (const k in this.batches) {
|
||||
if (!batchIds.includes(k)) {
|
||||
;(this.batches[k].renderObject as unknown as { material: Material }).material =
|
||||
this.materials.getGhostMaterial(this.batches[k].renderViews[0])
|
||||
this.batches[k].setDrawRanges({
|
||||
offset: 0,
|
||||
count: Infinity,
|
||||
material: this.materials.getFilterMaterial(
|
||||
this.batches[k].renderViews[0],
|
||||
FilterMaterialType.GHOST
|
||||
)
|
||||
})
|
||||
} else {
|
||||
const drawRanges = []
|
||||
for (let i = 0; i < this.batches[k].renderViews.length; i++) {
|
||||
|
||||
@@ -24,7 +24,7 @@ export default class LineBatch implements Batch {
|
||||
public batchMaterial: SpeckleLineMaterial
|
||||
private mesh: LineSegments2 | Line
|
||||
public colorBuffer: InstancedInterleavedBuffer
|
||||
public static vectorBuffer: Vector4 = new Vector4()
|
||||
private static readonly vector4Buffer: Vector4 = new Vector4()
|
||||
|
||||
public constructor(id: string, renderViews: NodeRenderView[]) {
|
||||
this.id = id
|
||||
@@ -87,11 +87,11 @@ export default class LineBatch implements Batch {
|
||||
ranges[i].offset * this.colorBuffer.stride +
|
||||
ranges[i].count * this.colorBuffer.stride
|
||||
|
||||
LineBatch.vectorBuffer.set(color.r, color.g, color.b, 1)
|
||||
LineBatch.vector4Buffer.set(color.r, color.g, color.b, 1)
|
||||
this.updateColorBuffer(
|
||||
start,
|
||||
ranges[i].count === Infinity ? this.colorBuffer.array.length : len,
|
||||
LineBatch.vectorBuffer
|
||||
LineBatch.vector4Buffer
|
||||
)
|
||||
}
|
||||
this.colorBuffer.updateRange = { offset: 0, count: data.length }
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
DynamicDrawUsage,
|
||||
Float32BufferAttribute,
|
||||
Material,
|
||||
Mesh,
|
||||
Object3D,
|
||||
Uint16BufferAttribute,
|
||||
Uint32BufferAttribute,
|
||||
@@ -12,6 +11,7 @@ import {
|
||||
} from 'three'
|
||||
import { Geometry } from '../converter/Geometry'
|
||||
import SpeckleStandardColoredMaterial from '../materials/SpeckleStandardColoredMaterial'
|
||||
import SpeckleMesh from '../objects/SpeckleMesh'
|
||||
import { NodeRenderView } from '../tree/NodeRenderView'
|
||||
import { World } from '../World'
|
||||
import { Batch, BatchUpdateRange, HideAllBatchUpdateRange } from './Batch'
|
||||
@@ -21,7 +21,7 @@ export default class MeshBatch implements Batch {
|
||||
public renderViews: NodeRenderView[]
|
||||
private geometry: BufferGeometry
|
||||
public batchMaterial: Material
|
||||
public mesh: Mesh
|
||||
public mesh: SpeckleMesh
|
||||
private gradientIndexBuffer: BufferAttribute
|
||||
|
||||
public constructor(id: string, renderViews: NodeRenderView[]) {
|
||||
@@ -257,7 +257,7 @@ export default class MeshBatch implements Batch {
|
||||
position,
|
||||
this.batchMaterial.vertexColors ? color : null
|
||||
)
|
||||
this.mesh = new Mesh(this.geometry, this.batchMaterial)
|
||||
this.mesh = new SpeckleMesh(this.geometry, this.batchMaterial)
|
||||
this.mesh.uuid = this.id
|
||||
}
|
||||
|
||||
@@ -285,6 +285,7 @@ export default class MeshBatch implements Batch {
|
||||
}
|
||||
|
||||
if (position) {
|
||||
/** When RTE enabled, we'll be storing the high component of the encoding here */
|
||||
this.geometry.setAttribute('position', new Float32BufferAttribute(position, 3))
|
||||
}
|
||||
|
||||
|
||||
@@ -33,13 +33,10 @@ export class Geometry {
|
||||
) {
|
||||
if (geometry.type === 'BufferGeometry') {
|
||||
const position_low = new Float32Array(doublePositions.length)
|
||||
const position_high = new Float32Array(doublePositions.length)
|
||||
/** We'll store the high component of the encoding inside three's default `position` attribute */
|
||||
const position_high = geometry.attributes.position.array as Float32Array
|
||||
Geometry.DoubleToHighLowBuffer(doublePositions, position_low, position_high)
|
||||
geometry.setAttribute('position_low', new Float32BufferAttribute(position_low, 3))
|
||||
geometry.setAttribute(
|
||||
'position_high',
|
||||
new Float32BufferAttribute(position_high, 3)
|
||||
)
|
||||
} else if (
|
||||
geometry.type === 'LineGeometry' ||
|
||||
geometry.type === 'LineSegmentsGeometry'
|
||||
@@ -191,7 +188,7 @@ export class Geometry {
|
||||
}
|
||||
|
||||
/** Please see https://speckle.systems/blog/improving-speckles-rte-implementation/ for additional details
|
||||
* regarding double -> float low; float high encoding.
|
||||
* regarding double -> <float low; float high> encoding.
|
||||
*/
|
||||
public static DoubleToHighLowVector(input: Vector3, low: Vector3, high: Vector3) {
|
||||
let doubleValue = input.x
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const speckleBasicVert = /* glsl */ `
|
||||
#include <common>
|
||||
#ifdef USE_RTE
|
||||
attribute vec3 position_high;
|
||||
// The high component is stored as the default 'position' attribute buffer
|
||||
attribute vec3 position_low;
|
||||
uniform vec3 uViewer_high;
|
||||
uniform vec3 uViewer_low;
|
||||
@@ -32,10 +32,13 @@ void main() {
|
||||
#include <skinning_vertex>
|
||||
// #include <project_vertex> COMMENTED CHUNK
|
||||
#ifdef USE_RTE
|
||||
/** Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl */
|
||||
/*
|
||||
Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl
|
||||
Note here, we're storing the high part of the position encoding inside three's default 'position' attribute buffer so we avoid redundancy
|
||||
*/
|
||||
vec3 t1 = position_low.xyz - uViewer_low;
|
||||
vec3 e = t1 - position_low.xyz;
|
||||
vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position_high.xyz - uViewer_high;
|
||||
vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position.xyz - uViewer_high;
|
||||
vec3 highDifference = t1 + t2;
|
||||
vec3 lowDifference = t2 - (highDifference - t1);
|
||||
vec4 mvPosition = vec4(highDifference.xyz + lowDifference.xyz , 1.);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const speckleLambertVert = /* glsl */ `
|
||||
#define LAMBERT
|
||||
#ifdef USE_RTE
|
||||
attribute vec3 position_high;
|
||||
// The high component is stored as the default 'position' attribute buffer
|
||||
attribute vec3 position_low;
|
||||
uniform vec3 uViewer_high;
|
||||
uniform vec3 uViewer_low;
|
||||
@@ -41,10 +41,13 @@ void main() {
|
||||
#include <skinning_vertex>
|
||||
//#include <project_vertex> COMMENTED CHUNK
|
||||
#ifdef USE_RTE
|
||||
/** Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl */
|
||||
/*
|
||||
Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl
|
||||
Note here, we're storing the high part of the position encoding inside three's default 'position' attribute buffer so we avoid redundancy
|
||||
*/
|
||||
vec3 t1 = position_low.xyz - uViewer_low;
|
||||
vec3 e = t1 - position_low.xyz;
|
||||
vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position_high.xyz - uViewer_high;
|
||||
vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position.xyz - uViewer_high;
|
||||
vec3 highDifference = t1 + t2;
|
||||
vec3 lowDifference = t2 - (highDifference - t1);
|
||||
vec4 mvPosition = vec4(highDifference.xyz + lowDifference.xyz , 1.);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const speckleStandardColoredVert = /* glsl */ `
|
||||
#define STANDARD
|
||||
#ifdef USE_RTE
|
||||
attribute vec3 position_high;
|
||||
// The high component is stored as the default 'position' attribute buffer
|
||||
attribute vec3 position_low;
|
||||
uniform vec3 uViewer_high;
|
||||
uniform vec3 uViewer_low;
|
||||
@@ -50,10 +50,13 @@ void main() {
|
||||
#include <displacementmap_vertex>
|
||||
//#include <project_vertex> // EDITED CHUNK
|
||||
#ifdef USE_RTE
|
||||
/** Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl */
|
||||
/*
|
||||
Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl
|
||||
Note here, we're storing the high part of the position encoding inside three's default 'position' attribute buffer so we avoid redundancy
|
||||
*/
|
||||
vec3 t1 = position_low.xyz - uViewer_low;
|
||||
vec3 e = t1 - position_low.xyz;
|
||||
vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position_high.xyz - uViewer_high;
|
||||
vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position.xyz - uViewer_high;
|
||||
vec3 highDifference = t1 + t2;
|
||||
vec3 lowDifference = t2 - (highDifference - t1);
|
||||
vec4 mvPosition = vec4(highDifference.xyz + lowDifference.xyz , 1.);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const speckleStandardVert = /* glsl */ `
|
||||
#define STANDARD
|
||||
#ifdef USE_RTE
|
||||
attribute vec3 position_high;
|
||||
// The high component is stored as the default 'position' attribute buffer
|
||||
attribute vec3 position_low;
|
||||
uniform vec3 uViewer_high;
|
||||
uniform vec3 uViewer_low;
|
||||
@@ -49,10 +49,13 @@ void main() {
|
||||
#include <displacementmap_vertex>
|
||||
//#include <project_vertex> // EDITED CHUNK
|
||||
#ifdef USE_RTE
|
||||
/** Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl */
|
||||
/*
|
||||
Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl
|
||||
Note here, we're storing the high part of the position encoding inside three's default 'position' attribute buffer so we avoid redundancy
|
||||
*/
|
||||
vec3 t1 = position_low.xyz - uViewer_low;
|
||||
vec3 e = t1 - position_low.xyz;
|
||||
vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position_high.xyz - uViewer_high;
|
||||
vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position.xyz - uViewer_high;
|
||||
vec3 highDifference = t1 + t2;
|
||||
vec3 lowDifference = t2 - (highDifference - t1);
|
||||
vec4 mvPosition = vec4(highDifference.xyz + lowDifference.xyz , 1.);
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
import {
|
||||
BackSide,
|
||||
DoubleSide,
|
||||
Matrix4,
|
||||
Mesh,
|
||||
Ray,
|
||||
Sphere,
|
||||
Triangle,
|
||||
Vector2,
|
||||
Vector3
|
||||
} from 'three'
|
||||
|
||||
const _inverseMatrix = new Matrix4()
|
||||
const _ray = new Ray()
|
||||
const _sphere = new Sphere()
|
||||
const _vTemp = new Vector3()
|
||||
const _vA = new Vector3()
|
||||
const _vB = new Vector3()
|
||||
const _vC = new Vector3()
|
||||
|
||||
const _tempA = new Vector3()
|
||||
const _tempB = new Vector3()
|
||||
const _tempC = new Vector3()
|
||||
|
||||
const _morphA = new Vector3()
|
||||
const _morphB = new Vector3()
|
||||
const _morphC = new Vector3()
|
||||
|
||||
const _uvA = new Vector2()
|
||||
const _uvB = new Vector2()
|
||||
const _uvC = new Vector2()
|
||||
|
||||
const _intersectionPoint = new Vector3()
|
||||
const _intersectionPointWorld = new Vector3()
|
||||
|
||||
export default class SpeckleMesh extends Mesh {
|
||||
raycast(raycaster, intersects) {
|
||||
const geometry = this.geometry
|
||||
const material = this.material
|
||||
const matrixWorld = this.matrixWorld
|
||||
|
||||
if (material === undefined) return
|
||||
|
||||
// Checking boundingSphere distance to ray
|
||||
|
||||
if (geometry.boundingSphere === null) geometry.computeBoundingSphere()
|
||||
|
||||
_sphere.copy(geometry.boundingSphere)
|
||||
_sphere.applyMatrix4(matrixWorld)
|
||||
|
||||
if (raycaster.ray.intersectsSphere(_sphere) === false) return
|
||||
|
||||
//
|
||||
|
||||
_inverseMatrix.copy(matrixWorld).invert()
|
||||
_ray.copy(raycaster.ray).applyMatrix4(_inverseMatrix)
|
||||
|
||||
// Check boundingBox before continuing
|
||||
|
||||
if (geometry.boundingBox !== null) {
|
||||
if (_ray.intersectsBox(geometry.boundingBox) === false) return
|
||||
}
|
||||
|
||||
let intersection
|
||||
|
||||
const index = geometry.index
|
||||
/** Stored high component if RTE is being used. Regular positions otherwise */
|
||||
const position = geometry.attributes.position
|
||||
/** Stored low component if RTE is being used. undefined otherwise */
|
||||
const positionLow = geometry.attributes['position_low']
|
||||
const morphPosition = geometry.morphAttributes.position
|
||||
const morphTargetsRelative = geometry.morphTargetsRelative
|
||||
const uv = geometry.attributes.uv
|
||||
const uv2 = geometry.attributes.uv2
|
||||
const groups = geometry.groups
|
||||
const drawRange = geometry.drawRange
|
||||
|
||||
if (index !== null) {
|
||||
// indexed buffer geometry
|
||||
|
||||
if (Array.isArray(material)) {
|
||||
for (let i = 0, il = groups.length; i < il; i++) {
|
||||
const group = groups[i]
|
||||
const groupMaterial = material[group.materialIndex]
|
||||
|
||||
const start = Math.max(group.start, drawRange.start)
|
||||
const end = Math.min(
|
||||
index.count,
|
||||
Math.min(group.start + group.count, drawRange.start + drawRange.count)
|
||||
)
|
||||
|
||||
for (let j = start, jl = end; j < jl; j += 3) {
|
||||
const a = index.getX(j)
|
||||
const b = index.getX(j + 1)
|
||||
const c = index.getX(j + 2)
|
||||
|
||||
intersection = checkBufferGeometryIntersection(
|
||||
this,
|
||||
groupMaterial,
|
||||
raycaster,
|
||||
_ray,
|
||||
positionLow,
|
||||
position,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
uv,
|
||||
uv2,
|
||||
a,
|
||||
b,
|
||||
c
|
||||
)
|
||||
|
||||
if (intersection) {
|
||||
intersection.faceIndex = Math.floor(j / 3) // triangle number in indexed buffer semantics
|
||||
intersection.face.materialIndex = group.materialIndex
|
||||
intersects.push(intersection)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const start = Math.max(0, drawRange.start)
|
||||
const end = Math.min(index.count, drawRange.start + drawRange.count)
|
||||
|
||||
for (let i = start, il = end; i < il; i += 3) {
|
||||
const a = index.getX(i)
|
||||
const b = index.getX(i + 1)
|
||||
const c = index.getX(i + 2)
|
||||
|
||||
intersection = checkBufferGeometryIntersection(
|
||||
this,
|
||||
material,
|
||||
raycaster,
|
||||
_ray,
|
||||
positionLow,
|
||||
position,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
uv,
|
||||
uv2,
|
||||
a,
|
||||
b,
|
||||
c
|
||||
)
|
||||
|
||||
if (intersection) {
|
||||
intersection.faceIndex = Math.floor(i / 3) // triangle number in indexed buffer semantics
|
||||
intersects.push(intersection)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (position !== undefined) {
|
||||
// non-indexed buffer geometry
|
||||
|
||||
if (Array.isArray(material)) {
|
||||
for (let i = 0, il = groups.length; i < il; i++) {
|
||||
const group = groups[i]
|
||||
const groupMaterial = material[group.materialIndex]
|
||||
|
||||
const start = Math.max(group.start, drawRange.start)
|
||||
const end = Math.min(
|
||||
position.count,
|
||||
Math.min(group.start + group.count, drawRange.start + drawRange.count)
|
||||
)
|
||||
|
||||
for (let j = start, jl = end; j < jl; j += 3) {
|
||||
const a = j
|
||||
const b = j + 1
|
||||
const c = j + 2
|
||||
|
||||
intersection = checkBufferGeometryIntersection(
|
||||
this,
|
||||
groupMaterial,
|
||||
raycaster,
|
||||
_ray,
|
||||
positionLow,
|
||||
position,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
uv,
|
||||
uv2,
|
||||
a,
|
||||
b,
|
||||
c
|
||||
)
|
||||
|
||||
if (intersection) {
|
||||
intersection.faceIndex = Math.floor(j / 3) // triangle number in non-indexed buffer semantics
|
||||
intersection.face.materialIndex = group.materialIndex
|
||||
intersects.push(intersection)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const start = Math.max(0, drawRange.start)
|
||||
const end = Math.min(position.count, drawRange.start + drawRange.count)
|
||||
|
||||
for (let i = start, il = end; i < il; i += 3) {
|
||||
const a = i
|
||||
const b = i + 1
|
||||
const c = i + 2
|
||||
|
||||
intersection = checkBufferGeometryIntersection(
|
||||
this,
|
||||
material,
|
||||
raycaster,
|
||||
_ray,
|
||||
positionLow,
|
||||
position,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
uv,
|
||||
uv2,
|
||||
a,
|
||||
b,
|
||||
c
|
||||
)
|
||||
|
||||
if (intersection) {
|
||||
intersection.faceIndex = Math.floor(i / 3) // triangle number in non-indexed buffer semantics
|
||||
intersects.push(intersection)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkIntersection(object, material, raycaster, ray, pA, pB, pC, point) {
|
||||
let intersect
|
||||
|
||||
if (material.side === BackSide) {
|
||||
intersect = ray.intersectTriangle(pC, pB, pA, true, point)
|
||||
} else {
|
||||
intersect = ray.intersectTriangle(pA, pB, pC, material.side !== DoubleSide, point)
|
||||
}
|
||||
|
||||
if (intersect === null) return null
|
||||
|
||||
_intersectionPointWorld.copy(point)
|
||||
_intersectionPointWorld.applyMatrix4(object.matrixWorld)
|
||||
|
||||
const distance = raycaster.ray.origin.distanceTo(_intersectionPointWorld)
|
||||
|
||||
if (distance < raycaster.near || distance > raycaster.far) return null
|
||||
|
||||
return {
|
||||
distance,
|
||||
point: _intersectionPointWorld.clone(),
|
||||
object,
|
||||
uv: undefined,
|
||||
uv2: undefined,
|
||||
face: undefined
|
||||
}
|
||||
}
|
||||
|
||||
/** If the geometry is non double->2floats encoded, the `positionHigh` argument will actually
|
||||
* hold the default `position` attribute values
|
||||
*/
|
||||
function checkBufferGeometryIntersection(
|
||||
object,
|
||||
material,
|
||||
raycaster,
|
||||
ray,
|
||||
positionLow,
|
||||
positionHigh,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
uv,
|
||||
uv2,
|
||||
a,
|
||||
b,
|
||||
c
|
||||
) {
|
||||
_vA.fromBufferAttribute(positionHigh, a)
|
||||
_vB.fromBufferAttribute(positionHigh, b)
|
||||
_vC.fromBufferAttribute(positionHigh, c)
|
||||
if (positionLow) {
|
||||
_vA.add(_vTemp.fromBufferAttribute(positionLow, a))
|
||||
_vB.add(_vTemp.fromBufferAttribute(positionLow, b))
|
||||
_vC.add(_vTemp.fromBufferAttribute(positionLow, c))
|
||||
}
|
||||
|
||||
const morphInfluences = object.morphTargetInfluences
|
||||
|
||||
if (morphPosition && morphInfluences) {
|
||||
_morphA.set(0, 0, 0)
|
||||
_morphB.set(0, 0, 0)
|
||||
_morphC.set(0, 0, 0)
|
||||
|
||||
for (let i = 0, il = morphPosition.length; i < il; i++) {
|
||||
const influence = morphInfluences[i]
|
||||
const morphAttribute = morphPosition[i]
|
||||
|
||||
if (influence === 0) continue
|
||||
|
||||
_tempA.fromBufferAttribute(morphAttribute, a)
|
||||
_tempB.fromBufferAttribute(morphAttribute, b)
|
||||
_tempC.fromBufferAttribute(morphAttribute, c)
|
||||
|
||||
if (morphTargetsRelative) {
|
||||
_morphA.addScaledVector(_tempA, influence)
|
||||
_morphB.addScaledVector(_tempB, influence)
|
||||
_morphC.addScaledVector(_tempC, influence)
|
||||
} else {
|
||||
_morphA.addScaledVector(_tempA.sub(_vA), influence)
|
||||
_morphB.addScaledVector(_tempB.sub(_vB), influence)
|
||||
_morphC.addScaledVector(_tempC.sub(_vC), influence)
|
||||
}
|
||||
}
|
||||
|
||||
_vA.add(_morphA)
|
||||
_vB.add(_morphB)
|
||||
_vC.add(_morphC)
|
||||
}
|
||||
|
||||
if (object.isSkinnedMesh) {
|
||||
object.boneTransform(a, _vA)
|
||||
object.boneTransform(b, _vB)
|
||||
object.boneTransform(c, _vC)
|
||||
}
|
||||
|
||||
const intersection = checkIntersection(
|
||||
object,
|
||||
material,
|
||||
raycaster,
|
||||
ray,
|
||||
_vA,
|
||||
_vB,
|
||||
_vC,
|
||||
_intersectionPoint
|
||||
)
|
||||
|
||||
if (intersection) {
|
||||
if (uv) {
|
||||
_uvA.fromBufferAttribute(uv, a)
|
||||
_uvB.fromBufferAttribute(uv, b)
|
||||
_uvC.fromBufferAttribute(uv, c)
|
||||
|
||||
intersection.uv = Triangle.getUV(
|
||||
_intersectionPoint,
|
||||
_vA,
|
||||
_vB,
|
||||
_vC,
|
||||
_uvA,
|
||||
_uvB,
|
||||
_uvC,
|
||||
new Vector2()
|
||||
)
|
||||
}
|
||||
|
||||
if (uv2) {
|
||||
_uvA.fromBufferAttribute(uv2, a)
|
||||
_uvB.fromBufferAttribute(uv2, b)
|
||||
_uvC.fromBufferAttribute(uv2, c)
|
||||
|
||||
intersection.uv2 = Triangle.getUV(
|
||||
_intersectionPoint,
|
||||
_vA,
|
||||
_vB,
|
||||
_vC,
|
||||
_uvA,
|
||||
_uvB,
|
||||
_uvC,
|
||||
new Vector2()
|
||||
)
|
||||
}
|
||||
|
||||
const face = {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
normal: new Vector3(),
|
||||
materialIndex: 0
|
||||
}
|
||||
|
||||
Triangle.getNormal(_vA, _vB, _vC, face.normal)
|
||||
|
||||
intersection.face = face
|
||||
}
|
||||
|
||||
return intersection
|
||||
}
|
||||
Reference in New Issue
Block a user