blob: 0c231938952a1ed0e491dc9a7761e4a54302e46d (
plain)
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
|
////////////////////////////////////////////////////////////////////////////////
//
// (C) 2012, Michail Vidiassov, John C. Bowman, Alexander Grahn
//
// asylabels.js
//
// version 20120912
//
////////////////////////////////////////////////////////////////////////////////
//
// 3D JavaScript to be used with media9.sty (option `add3Djscript') for
// Asymptote generated PRC files
//
// adds billboard behaviour to text labels in Asymptote PRC files so that
// they always face the camera under 3D rotation.
//
//
// This work may be distributed and/or modified under the
// conditions of the LaTeX Project Public License.
//
// The latest version of this license is in
// http://mirrors.ctan.org/tex-archive/macros/latex/base/lppl.txt
//
// This work has the LPPL maintenance status `maintained'.
//
// The Current Maintainer of this work is A. Grahn.
//
////////////////////////////////////////////////////////////////////////////////
var bbnodes=new Array(); // billboard meshes
var bbtrans=new Array(); // billboard transforms
function fulltransform(mesh)
{
var t=new Matrix4x4(mesh.transform);
if(mesh.parent.name != "") {
var parentTransform=fulltransform(mesh.parent);
t.multiplyInPlace(parentTransform);
return t;
} else
return t;
}
// find all text labels in the scene and determine pivoting points
var nodes=scene.nodes;
var nodescount=nodes.count;
var third=1.0/3.0;
for(var i=0; i < nodescount; i++) {
var node=nodes.getByIndex(i);
var name=node.name;
var end=name.lastIndexOf(".")-1;
if(end > 0) {
if(name.charAt(end) == "\001") {
var start=name.lastIndexOf("-")+1;
if(end > start) {
node.name=name.substr(0,start-1);
var nodeMatrix=fulltransform(node.parent);
var c=nodeMatrix.translation; // position
var d=Math.pow(Math.abs(nodeMatrix.determinant),third); // scale
bbnodes.push(node);
bbtrans.push(Matrix4x4().scale(d,d,d).translate(c).multiply(nodeMatrix.inverse));
}
}
}
}
var camera=scene.cameras.getByIndex(0);
var zero=new Vector3(0,0,0);
var bbcount=bbnodes.length;
// event handler to maintain camera-facing text labels
billboardHandler=new RenderEventHandler();
billboardHandler.onEvent=function(event)
{
var T=new Matrix4x4();
T.setView(zero,camera.position.subtract(camera.targetPosition),
camera.up.subtract(camera.position));
for(var j=0; j < bbcount; j++)
bbnodes[j].transform.set(T.multiply(bbtrans[j]));
runtime.refresh();
}
runtime.addEventHandler(billboardHandler);
runtime.refresh();
|