forked from jeromeetienne/threex.htmlmixer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
threex.htmlmixer.js
193 lines (160 loc) · 5.95 KB
/
threex.htmlmixer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
var THREEx = THREEx || {}
THREEx.HtmlMixer = THREEx.HtmlMixer || {}
/**
* define a context for THREEx.HtmlMixer
*
* @param {THREE.WebGLRenderer|THREE.CanvasRenderer} rendererWebgl the renderer in front
* @param {THREE.Scene} scene the original scene
* @param {THREE.Camera} camera the camera used for the last view
*/
THREEx.HtmlMixer.Context = function(rendererWebgl, scene, camera){
// update functions
var updateFcts = []
this.update = function(){
updateFcts.forEach(function(updateFct){
updateFct()
})
}
// build cssFactor to workaround bug due to no display
var cssFactor = 1000
this.cssFactor = cssFactor
//////////////////////////////////////////////////////////////////////////////////
// update renderer
//////////////////////////////////////////////////////////////////////////////////
var rendererCss = new THREE.CSS3DRenderer()
this.rendererCss= rendererCss
this.rendererWebgl = rendererWebgl
//////////////////////////////////////////////////////////////////////////////////
// Handle Camera
//////////////////////////////////////////////////////////////////////////////////
var cssCamera = new THREE.PerspectiveCamera(camera.fov, camera.aspect, camera.near*cssFactor, camera.far*cssFactor);
updateFcts.push(function(){
cssCamera.quaternion.copy(camera.quaternion)
cssCamera.position
.copy(camera.position)
.multiplyScalar(cssFactor)
})
//////////////////////////////////////////////////////////////////////////////////
// Comment //
//////////////////////////////////////////////////////////////////////////////////
// create a new scene to hold CSS
var cssScene = new THREE.Scene();
this.cssScene= cssScene
//////////////////////////////////////////////////////////////////////////////////
// Auto update objects
//////////////////////////////////////////////////////////////////////////////////
this.autoUpdateObjects = true
updateFcts.push(function(){
if( this.autoUpdateObjects !== true ) return
cssScene.traverse(function(cssObject){
if( cssObject instanceof THREE.Scene === true ) return
var mixerPlane = cssObject.userData.mixerPlane
if( mixerPlane === undefined ) return
mixerPlane.update()
})
}.bind(this))
//////////////////////////////////////////////////////////////////////////////////
// Render cssScene
//////////////////////////////////////////////////////////////////////////////////
updateFcts.push(function(delta, now){
rendererCss.render(cssScene, cssCamera)
})
}
/**
* define plane in THREEx.HtmlMixer
*
* @param {THREEx.HtmlMixer.Context} mixerContext context
* @param {HTMLElement} domElement the dom element to mix
* @param {Object} opts options to set
*/
THREEx.HtmlMixer.Plane = function(mixerContext, domElement, opts) {
opts = opts || {}
opts.elementW = opts.elementW !== undefined ? opts.elementW : 768
opts.planeW = opts.planeW !== undefined ? opts.planeW : 1
opts.planeH = opts.planeH !== undefined ? opts.planeH : 3/4
opts.object3d = opts.object3d !== undefined ? opts.object3d : null
this.domElement = domElement
// update functions
var updateFcts = []
this.update = function(){
updateFcts.forEach(function(updateFct){
updateFct()
})
}
var planeW = opts.planeW
var planeH = opts.planeH
if( opts.object3d === null ){
var planeMaterial = new THREE.MeshBasicMaterial({
opacity : 0,
color : new THREE.Color('black'),
blending: THREE.NoBlending,
side : THREE.DoubleSide,
})
var geometry = new THREE.PlaneGeometry( opts.planeW, opts.planeH )
var object3d = new THREE.Mesh( geometry, planeMaterial )
}else{
var object3d = opts.object3d
}
this.object3d = object3d
// width of iframe in pixels
var aspectRatio = planeH / planeW
var elementWidth = opts.elementW;
var elementHeight = elementWidth * aspectRatio
this.setDomElement = function(newDomElement){
console.log('setDomElement: newDomElement', newDomElement)
// remove the oldDomElement
var oldDomElement = domElement
if( oldDomElement.parentNode ){
oldDomElement.parentNode.removeChild(oldDomElement);
}
// update local variables
this.domElement = domElement = newDomElement
// update cssObject
cssObject.element = domElement
// reset the size of the domElement
setDomElementSize()
}
function setDomElementSize(){
domElement.style.width = elementWidth + "px";
domElement.style.height = elementHeight + "px";
}
setDomElementSize()
// create a CSS3DObject to display element
var cssObject = new THREE.CSS3DObject( domElement )
this.cssObject = cssObject
cssObject.scale.set(1,1,1)
.multiplyScalar(mixerContext.cssFactor/(elementWidth/planeW))
// hook cssObhect to mixerPlane
cssObject.userData.mixerPlane = this
//////////////////////////////////////////////////////////////////////////////////
// hook event so cssObject is attached to cssScene when object3d is added/removed
//////////////////////////////////////////////////////////////////////////////////
object3d.addEventListener('added', function(event){
mixerContext.cssScene.add(cssObject)
})
object3d.addEventListener('removed', function(event){
mixerContext.cssScene.remove(cssObject)
})
//////////////////////////////////////////////////////////////////////////////////
// Comment //
//////////////////////////////////////////////////////////////////////////////////
updateFcts.push(function(){
// get world position
object3d.updateMatrixWorld();
var worldMatrix = object3d.matrixWorld;
// get position/quaternion/scale of object3d
var position = new THREE.Vector3()
var scale = new THREE.Vector3()
var quaternion = new THREE.Quaternion()
worldMatrix.decompose(position, quaternion, scale)
// handle quaternion
cssObject.quaternion.copy(quaternion)
// handle position
cssObject.position
.copy(position)
.multiplyScalar(mixerContext.cssFactor)
// handle scale
var scaleFactor = elementWidth/(object3d.geometry.parameters.width*scale.x)
cssObject.scale.set(1,1,1).multiplyScalar(mixerContext.cssFactor/scaleFactor)
})
};