Proposed addition to OrbitControls?

Hey guys I was struggling with manually changing the camera independent of the OrbitControls. (ie if I change camera.rotation myself, OrbitControls would reset it)

I added a method “rotate” to OrbitControls that effectively exposed the internal method “rotateLeft” so that I cold do what I needed.

This is what I added.

	this.rotate = function(degrees) {

it works kind of cool (for me).

Other users made the same suggestion in the past. The project decided not to expose the internal control functions. Please read the discussion in the following PR for more information.

As with all the other examples, they’re just examples. Orbit controls could probably be written in infinitely many different ways and someone would find it perfect each time. Whether a method is public or private is a completely arbitrary thing.

Generally you’d make a PR and propose your changes yourself. 4-5 different people will review it and say if they like it or not and it gets approved or rejected.

In this particular case it seems that someone rather arbitrarily decided to make some methods private and now everything needs to be consistent with it.

I don’t quite understand why are people asking for features like this if they understand how to modify the code. It’s just a guideline for what is possible with the library.

There was an interesting experiment with monkeys that i think applies here. No one may actually know why this method is private when it’s perceivably much more useful as public, but it’s the way it always has been :slight_smile:


I am definitely one of those monkeys in this story. Not sure which.

So how do you go about moving the camera independently of OrbitControls? Do you modify it and then have to port your code with each subsequent release of Three? I wonder what percentage of projects use OrbitControls? For me it’s in the high 90’s.

That is a good question and i don’t know the answer to it.

If you assume that /examples are just examples of what you can do with the library, you can use it as a guideline:

Oh wow, you can do this? Cool, i need like 98% of it, let me tweak it a little bit…

If you assume it’s something more than that then you do run into the problem of keeping a fork in sync. However, you can expect the changes to happen less frequently than with the core, and you might also not need them.

Simply, does it do the job for you with that tweak?

Yes - use it while it works
No - look for alternatives

Does it do the job off the shelf?
Yes - use off the shelf
No - tweak

I’ve learned recently, the hard way, that developing three.js is far from being a democracy :slight_smile: We all have opinions but in the end it’s a few that count.

Could it all be better? YES!!! ← but that’s just my opinion :slight_smile:

The proper thing to do here would maybe be forking OrbitControls and posting in those issues something like:

Hey, if you need the methods foo and bar public on this class check out this repo

There’s no way to track how many people are using an example, thus making all of these decisions rather arbitrary. Ie. whatever’s there, people will use.

Person A thinks this should be private, nothing you can do about it. However if say a year from now you start seeing a lot more examples that use ImprovedOrbitControls it would be a tell of how people want to use this, and eventually Person A might cave in.

Unfortunately the problem with this is that three is so monolithic. Forking three-orbit-controls would make much more sense and be easier to merge back at some point if it’s deemed necessary than forking three.

I like how other big JS projects are structured, there are even examples in the 3d world:

They call their “examples” “extensions” which i think makes more sense given how people use three’s examples (i’d really like to hear an argument that OrbitControls is not an extension).

Even documents are in a seperate repo:

Imagine if you could just go to one repo and see issues only relating to that repo. Out of 540 currently open issues only 16 seem to mention OrbitControls, roughly 3%. They can get lost in the rest and people might miss them.

I also believe it causes a phenomenon called tribal knowledge.

Imagine you have someone sitting there every day going through ALL of these issues, and PRs and compare what they might now to what’s written in the docs or in the code. It’s probably going to be orders of magnitude different since that person would have to approve every change in the /examples and they’re not documented.

All that knowledge is “tribal” - there’s a tribe of three.js experts that know how three.js works without available documentation. But rather than it being told by the tribe elders (although this happens in various meetups and presentations), it’s technically written, but you could say in a secret sacred esoteric language - “the source”.

IMO this is not good as this role could just be replaced by proper documentation. But at least anyone can tackle the sacred texts (read the source).

Imagine if you had 100 different repos each with their own well defined scope and responsibility, how would that compare.

The conflation here comes, i believe, from the fact that three.js targets a really wide spectrum of users. There might be someone who just wants to use the library at a high level, while someone else might be building another library using this library.

Nobody said it was a democracy. I wouldn’t want it to be one. I’d rather have experts and veterans in charge of the PR approval process. That’s how every open-source library works, and it would be a maintenance nightmare if it wasn’t.


I don’t think that’s the tangent i was referring to @marquizzo. What’s being discussed here is a pure design decision, there’s probably 50% arguments for and 50% arguments against.

People want stuff, OP wants public methods, I want extensibility, someone else might want robustness, another one extensve documentation etc etc. Maybe democracy is the wrong analogy.

Just compare bablyon and three, both do very similar if not the same things (3d), but they work different, are structured different, are documented different etc. This absolutely does not imply that either tribe is any more or less veteran or has any more or less expertise, just different ideas on how things should be done.

Which brings us to the original point, what does the OP (or many like him) actually need? If OrbitControls already doesn’t do what you wan’t, how much do you care about being in sync with the project?

@webdood I believe the best solution here is to make a copy of ObitControls.js into your project and expose the rotateLeft, rotateUp, and any other methods you need. A very simple way of doing this is just by adding one line per method in OrbitControls.js:

// Starting at line 291
	function rotateLeft( angle ) {

		sphericalDelta.theta -= angle;


	this.rotateLeft = rotateLeft;	// <- this makes it public

	function rotateUp( angle ) {

		sphericalDelta.phi -= angle;


	this.rotateUp = rotateUp;	// <- this makes it public

… and so on. You can then access it externally by calling controls.rotateUp(0.1) or controls.rotateLeft(0.1).

If you group them like so:

  ... = foo = bar
  this.baz = baz

(at the end of the block) odds are you’ll run into no conflicts when syncing this with main.

For the most part, I’d wager a lack of experience. Look at how many examples in which OrbitControls is used. If I wasn’t paying attention to the path, I might think it’s a core component, and would expect it to be fleshed out with–or at least open to suggestions for–convenience functions like this.

Beyond that, there are scenarios (and I speak from experience here) where you are obligated to not alter third-party code, regardless of licensing. In these scenarios, I have been forced to perform monkey-patching, which I’m sure you know can be not only daunting, but also filled with all kinds of peril. I can fully understand apprehension toward this approach.

1 Like

It’s more the fact that you do

<script src='core'/>
<script src='OrbitControls'/>

than the path itself. Two distinct modules, one depends on the other. I think this is in due mostly for legacy reasons, ie start with a html page, add a <script> tag and write some three.js code still kind of being the official way you’re supposed to use the library.

I’d definitely argue against OrbitControls being “just an example” but i’m not entirely sure on what grounds to do that. My simple take is, if you had a sample of all the three.js apps out there, this “example” would be used in A LOT of them, while some other, maybe Octree would be used in A FEW of them. But all you have there is anecdotal evidence and guesses.

But how do you label it then?

What was your scenario for not altering 3rd party code? I was not allowed to modify three.js at my workplace for example, but we’ve rebuilt several controllers from bits and pieces of what’s in three.

Not to extend this sidebar too far, but I think the point that’s trying to be made by the three.js team is that they are trying to remain agnostic to specific use-cases. Although three.js provides lots of great examples (like OrbitControls), its primary objective is to be a friendly abstraction layer on top of WebGL (buffers, materials, lights, cameras). Everything else–including user interfaces and interactions–is extra.

The same as you. My employer errs on the side of caution regarding open-source. Yes, there is always the option of re-building a component in-house. But the old adage of “fast, cheap, and good: pick two” applies.