Skip to content

Commit

Permalink
wip: add corridor with moving texture
Browse files Browse the repository at this point in the history
  • Loading branch information
Floran05 committed Jan 31, 2025
1 parent 3629738 commit 99565cf
Show file tree
Hide file tree
Showing 3 changed files with 222 additions and 94 deletions.
161 changes: 133 additions & 28 deletions map/client/cesium/utils/utils.cesium.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,24 @@ async function loadCesium() {

loadCesium()


export function createWallGeometry (positions, minimumHeights = [], maximumHeights = []) {
if (!positions || positions.length < 2) return

minimumHeights = minimumHeights || Array(positions.length).fill(0)
minimumHeights = Array.isArray(minimumHeights) ? minimumHeights : Array(positions.length).fill(minimumHeights)
if(!maximumHeights){
if (!maximumHeights) {
maximumHeights = []
for(let i = 0, j = positions.length; i < j; ++i){
for (let i = 0, j = positions.length; i < j; ++i) {
const cartographic = Cesium.Cartographic.fromCartesian(positions[i])
maximumHeights.push(cartographic.height)
}
}
maximumHeights = Array.isArray(maximumHeights) ? maximumHeights : Array(positions.length).fill(maximumHeights)

const setHeight = (cartesian, height) => {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
cartographic.height = height;
return Cesium.Cartographic.toCartesian(cartographic);
const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
cartographic.height = height
return Cesium.Cartographic.toCartesian(cartographic)
}

// Generate positions and st
Expand Down Expand Up @@ -79,17 +80,17 @@ export function createWallGeometry (positions, minimumHeights = [], maximumHeigh
position: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.DOUBLE,
componentsPerAttribute: 3,
values: wallPositions,
values: wallPositions
}),
st: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 2,
values: new Float64Array(st),
}),
values: new Float64Array(st)
})
},
indices: new Uint16Array(indices),
primitiveType: Cesium.PrimitiveType.TRIANGLES,
boundingSphere: Cesium.BoundingSphere.fromVertices(wallPositions),
boundingSphere: Cesium.BoundingSphere.fromVertices(wallPositions)
}),
dimensions: {
minHeight,
Expand All @@ -98,28 +99,132 @@ export function createWallGeometry (positions, minimumHeights = [], maximumHeigh
}
}

export function createCorridorGeometry (positions, width, height) {
if (!positions || positions.length < 2) return

const setHeight = (cartesian, height) => {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
cartographic.height = height
return Cesium.Cartographic.toCartesian(cartographic)
}

const computeOffset = (current, previous, next, offset) => {
let direction

if (!previous) {
// If it's the first point, use only the direction to the next
direction = Cesium.Cartesian3.subtract(next, current, new Cesium.Cartesian3())
} else if (!next) {
// If it's the last point, use only the direction from the previous
direction = Cesium.Cartesian3.subtract(current, previous, new Cesium.Cartesian3())
} else {
// Intermediate points: average of the directions before and after
const forward = Cesium.Cartesian3.subtract(next, current, new Cesium.Cartesian3())
const backward = Cesium.Cartesian3.subtract(current, previous, new Cesium.Cartesian3())
direction = Cesium.Cartesian3.add(forward, backward, new Cesium.Cartesian3())
}

Cesium.Cartesian3.normalize(direction, direction)

// Compute the perpendicular vector
const up = Cesium.Cartesian3.UNIT_Z
const perpendicular = Cesium.Cartesian3.cross(direction, up, new Cesium.Cartesian3())
Cesium.Cartesian3.normalize(perpendicular, perpendicular)

// Apply the offset
const offsetVector = Cesium.Cartesian3.multiplyByScalar(perpendicular, offset, new Cesium.Cartesian3())
return Cesium.Cartesian3.add(current, offsetVector, new Cesium.Cartesian3())
}

const indices = []
const distances = [0]
let lineLength = 0

for (let i = 0; i < positions.length - 1; i++) {
const p0 = positions[i]
const p1 = positions[i + 1]
const distance = Cesium.Cartesian3.distance(p0, p1)
distances.push(distance)
lineLength += distance

// Add indices
const baseIndex = i * 2
indices.push(
baseIndex, baseIndex + 1, baseIndex + 2,
baseIndex + 1, baseIndex + 3, baseIndex + 2
)
}

let percent = 0
const st = []
const corridorPositions = []
for (let i = 0; i < positions.length; i++) {
// Normalize distances for texture coordinates
percent += distances[i] / lineLength
if (i === positions.length - 1) percent = 1
st.push(percent, 0, percent, 1)

// Compute the offset positions to create the corridor
const leftOffset = setHeight(computeOffset(positions[i], positions[i - 1], positions[i + 1], -width / 2), height)
const rightOffset = setHeight(computeOffset(positions[i], positions[i - 1], positions[i + 1], width / 2), height)

corridorPositions.push(
leftOffset.x,
leftOffset.y,
leftOffset.z,
rightOffset.x,
rightOffset.y,
rightOffset.z
)
}

return {
geometry: new Cesium.Geometry({
attributes: {
position: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.DOUBLE,
componentsPerAttribute: 3,
values: corridorPositions
}),
st: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 2,
values: new Float64Array(st)
})
},
indices: new Uint16Array(indices),
primitiveType: Cesium.PrimitiveType.TRIANGLES,
boundingSphere: Cesium.BoundingSphere.fromVertices(corridorPositions)
}),
dimensions: {
lineLength,
width
}
}
}

export function createMaterialWithMovingTexture (options) {
if(!options.image) return
if (!options.image) return

options = {
image: _.get(options, 'image'),
translucent: _.get(options, 'translucent', false),
speedX: _.get(options, 'speedX', 0),
speedY: _.get(options, 'speedY', 0),
repeatX: _.get(options, 'repeatX', 1),
repeatY: _.get(options, 'repeatY', 1)
image: options.image,
translucent: options.translucent || false,
speedX: options.speedX || 0,
speedY: options.speedY || 0,
repeatX: options.repeatX || 1,
repeatY: options.repeatY || 1
}

let material = null;
try{
let material = null
try {
// TODO : temporary throw to avoid to load material from type because it's not working
throw new Error("Load material from type is not working");
material = Cesium.Material.fromType('MovingMaterial');
material.uniforms.image = options.image;
material.uniforms.repeat = new Cesium.Cartesian2(options.repeatX, options.repeatY);
material.uniforms.offset = new Cesium.Cartesian2(0.0, 0.0);
material.translucent = options.translucent;
}catch(e){
material = Cesium.Material.fromType('MovingMaterial')
material.uniforms.image = options.image
material.uniforms.repeat = new Cesium.Cartesian2(options.repeatX, options.repeatY)
material.uniforms.offset = new Cesium.Cartesian2(0.0, 0.0)
material.translucent = options.translucent
throw new Error('Load material from type is not working')
} catch (e) {
material = new Cesium.Material({
fabric: {
type: 'MovingMaterial',
Expand Down Expand Up @@ -151,4 +256,4 @@ export function createMaterialWithMovingTexture (options) {
}

return material
}
}
22 changes: 11 additions & 11 deletions map/client/mixins/globe/mixin.base-globe.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,23 @@ export const baseGlobe = {

// Update moving materials
this.viewer.scene.preRender.addEventListener(() => {
if(!this.cesiumMaterials) return
if (!this.cesiumMaterials) return
_.forEach(this.cesiumMaterials, m => {
if(!m.material.uniforms.offset) return
m.material.uniforms.offset.x += m.speedX || 0;
m.material.uniforms.offset.y += m.speedY || 0;
if (!m.material.uniforms.offset) return

m.material.uniforms.offset.x += m.speedX || 0
m.material.uniforms.offset.y += m.speedY || 0
if (m.material.uniforms.offset.x > 1.0) {
m.material.uniforms.offset.x = 0;
m.material.uniforms.offset.x = 0
}
if (m.material.uniforms.offset.y > 1.0) {
m.material.uniforms.offset.y = 0;
m.material.uniforms.offset.y = 0
}
});
});
})
})

// Debug mode ?
//this.viewerOptions.debug = true
// this.viewerOptions.debug = true
if (this.viewerOptions.debug) this.viewer.extend(viewerCesiumInspectorMixin)
// Cesium always create a default provider when a globe is used
if (this.viewer.scene.imageryLayers) this.viewer.scene.imageryLayers.removeAll()
Expand Down Expand Up @@ -280,7 +280,7 @@ export const baseGlobe = {
cesiumLayer.show = false
} else { // Entity data source otherwise
// Remove primitives before removing the data source
if(cesiumLayer.primitives){
if (cesiumLayer.primitives) {
for (let i = 0, j = cesiumLayer.primitives.length; i < j; i++) {
this.viewer.scene.primitives.remove(cesiumLayer.primitives.get(i))
}
Expand Down
Loading

0 comments on commit 99565cf

Please sign in to comment.