profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/swift502/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.

swift502/Sketchbook 504

3D playground built on three.js and cannon.js

swift502/cannon.js 6

A lightweight 3D physics engine written in JavaScript.

swift502/Web 3

Personal website built with Middleman.

swift502/Octarr 1

Dynamic array-like octree written in C#

swift502/PaintWars 1

Simple 2D game written in C#

swift502/Sudoku 0

Sudoku puzzle game written in C#

starteddotsquid/LensFlares

started time in 2 hours

started7leodev/TimeOfDay

started time in 11 days

startedkinokomushroom/Godot-Piano-Transcription-Helper

started time in 12 days

pull request commentswift502/Sketchbook

Cameras

Sure. 🙂

Your work is already pretty impressive. Just not what I personally had in mind.

eachtime

comment created time in 21 days

Pull request review commentswift502/Sketchbook

Cameras

 export class CameraOperator implements IInputReceiver, IUpdatable 		this.phi += deltaY * (this.sensitivity.y / 2); 		this.phi = Math.min(85, Math.max(-85, this.phi)); 	}+	public nextCamType(){+		this._currentCam.type++;+		this._currentCam.view = 0;+		if( ! this._currentCam.types[ this._currentCam.type ] )+		{+			this._currentCam.type = 0;+		}++		return this._currentCam.types[ this._currentCam.type ];+	}++	public nextView(){+		if( this._currentCam.views[ this._currentCam.view + 1 ]){+			this._currentCam.view++;+		} else {+			this._currentCam.view = 0;+		}+		return this._currentCam.view;+	}++	public get currentCamType(){+		return this._currentCam.types[ this._currentCam.type ];+	}++	public get currentCam(){+		return this._viewpoints[ this._currentCam.name ][ this._currentCam.view ];+	}  	public update(timeScale: number): void 	{-		if (this.followMode === true)-		{-			this.camera.position.y = THREE.MathUtils.clamp(this.camera.position.y, this.target.y, Number.POSITIVE_INFINITY);-			this.camera.lookAt(this.target);-			let newPos = this.target.clone().add(new THREE.Vector3().subVectors(this.camera.position, this.target).normalize().multiplyScalar(this.targetRadius));-			this.camera.position.x = newPos.x;-			this.camera.position.y = newPos.y;-			this.camera.position.z = newPos.z;++		switch ( this.currentCamType ) {+			case 'follow':+				this.followCam( timeScale );+				break;+			case 'free':+				this.freeCam();+				break;+				default:+				this.freeCam();+				break; 		}-		else -		{-			this.radius = THREE.MathUtils.lerp(this.radius, this.targetRadius, 0.1);-	-			this.camera.position.x = this.target.x + this.radius * Math.sin(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);-			this.camera.position.y = this.target.y + this.radius * Math.sin(this.phi * Math.PI / 180);-			this.camera.position.z = this.target.z + this.radius * Math.cos(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);-			this.camera.updateMatrix();-			this.camera.lookAt(this.target);++	}++	private freeCam( ){+		this.radius = THREE.MathUtils.lerp(this.radius, this.targetRadius, 0.1);+		this.camera.position.x = this.target.x + this.radius * Math.sin(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);+		this.camera.position.y = this.target.y + this.radius * Math.sin(this.phi * Math.PI / 180);+		this.camera.position.z = this.target.z + this.radius * Math.cos(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);+		this.camera.updateMatrix();+		this.camera.lookAt(this.target);+	}++	private _viewpointRelativeTo(target: any){+		let name = target.classname;+		name = this._viewpoints[ name ] ? name : 'defaults';+		this._currentCam.name = name;+		this._currentCam.views = [ ...this._viewpoints[ this._currentCam.name ], ...this._viewpoints.shared ];++		const pov = this._currentCam.views[ this._currentCam.view ] ?? this._currentCam.views[ this._currentCam.views.length - 1 ];++		const position = pov.position.clone();+		position.applyQuaternion( target.quaternion );+		position.add( target.position );++		const direction = pov.direction.clone();+		direction.applyQuaternion( target.quaternion );+		direction.add( target.position );++		return { position, direction, lerp: pov.lerp };+	}++	private followCam( timeScale: number ){+		let player = this.world.characters.find( char => char.uuid === this.world.player_id );

Sure, whatever works for you.

The input system was designed in a general way, so inputReceiver can be any entity. But if you keep that in mind, and you'll be fine.

eachtime

comment created time in 21 days

PullRequestReviewEvent

Pull request review commentswift502/Sketchbook

Cameras

 export class Airplane extends Vehicle implements IControllable, IWorldEntity 	private enginePower: number = 0; 	private lastDrag: number = 0; +	public get classname(): string+	{+		return 'Airplane';

Yeah I've just read that minification breaks that.

It's fine the way it is. I just know I already made an identifier for all entities, so I wondered if it couldn't be used.

eachtime

comment created time in 21 days

PullRequestReviewEvent

Pull request review commentswift502/Sketchbook

Cameras

 export class CameraOperator implements IInputReceiver, IUpdatable 		this.phi += deltaY * (this.sensitivity.y / 2); 		this.phi = Math.min(85, Math.max(-85, this.phi)); 	}+	public nextCamType(){+		this._currentCam.type++;+		this._currentCam.view = 0;+		if( ! this._currentCam.types[ this._currentCam.type ] )+		{+			this._currentCam.type = 0;+		}++		return this._currentCam.types[ this._currentCam.type ];+	}++	public nextView(){+		if( this._currentCam.views[ this._currentCam.view + 1 ]){+			this._currentCam.view++;+		} else {+			this._currentCam.view = 0;+		}+		return this._currentCam.view;+	}++	public get currentCamType(){+		return this._currentCam.types[ this._currentCam.type ];+	}++	public get currentCam(){+		return this._viewpoints[ this._currentCam.name ][ this._currentCam.view ];+	}  	public update(timeScale: number): void 	{-		if (this.followMode === true)-		{-			this.camera.position.y = THREE.MathUtils.clamp(this.camera.position.y, this.target.y, Number.POSITIVE_INFINITY);-			this.camera.lookAt(this.target);-			let newPos = this.target.clone().add(new THREE.Vector3().subVectors(this.camera.position, this.target).normalize().multiplyScalar(this.targetRadius));-			this.camera.position.x = newPos.x;-			this.camera.position.y = newPos.y;-			this.camera.position.z = newPos.z;++		switch ( this.currentCamType ) {+			case 'follow':+				this.followCam( timeScale );+				break;+			case 'free':+				this.freeCam();+				break;+				default:+				this.freeCam();+				break; 		}-		else -		{-			this.radius = THREE.MathUtils.lerp(this.radius, this.targetRadius, 0.1);-	-			this.camera.position.x = this.target.x + this.radius * Math.sin(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);-			this.camera.position.y = this.target.y + this.radius * Math.sin(this.phi * Math.PI / 180);-			this.camera.position.z = this.target.z + this.radius * Math.cos(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);-			this.camera.updateMatrix();-			this.camera.lookAt(this.target);++	}++	private freeCam( ){+		this.radius = THREE.MathUtils.lerp(this.radius, this.targetRadius, 0.1);+		this.camera.position.x = this.target.x + this.radius * Math.sin(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);+		this.camera.position.y = this.target.y + this.radius * Math.sin(this.phi * Math.PI / 180);+		this.camera.position.z = this.target.z + this.radius * Math.cos(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);+		this.camera.updateMatrix();+		this.camera.lookAt(this.target);+	}++	private _viewpointRelativeTo(target: any){+		let name = target.classname;+		name = this._viewpoints[ name ] ? name : 'defaults';+		this._currentCam.name = name;+		this._currentCam.views = [ ...this._viewpoints[ this._currentCam.name ], ...this._viewpoints.shared ];++		const pov = this._currentCam.views[ this._currentCam.view ] ?? this._currentCam.views[ this._currentCam.views.length - 1 ];++		const position = pov.position.clone();+		position.applyQuaternion( target.quaternion );+		position.add( target.position );++		const direction = pov.direction.clone();+		direction.applyQuaternion( target.quaternion );+		direction.add( target.position );++		return { position, direction, lerp: pov.lerp };+	}++	private followCam( timeScale: number ){+		let player = this.world.characters.find( char => char.uuid === this.world.player_id );

It's no problem. Maybe I just misunderstood your intentions. I'm happy to just give you feedback. 🙂

All vehicles have the controllingCharacter variable, that's probably the quickest way to access the player from a vehicle.

From everywhere else, probably world.inputManager.inputReceiver, and find out if it's a character. It might not be a character though, it might be the camera for example, when it is in my version "free camera" mode.

eachtime

comment created time in 21 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentswift502/Sketchbook

Cameras

 export class Airplane extends Vehicle implements IControllable, IWorldEntity 	private enginePower: number = 0; 	private lastDrag: number = 0; +	public get classname(): string+	{+		return 'Airplane';

Huh, what are you using this for? Why not use entityType from line 14?

eachtime

comment created time in 21 days

Pull request review commentswift502/Sketchbook

Cameras

 export class CameraOperator implements IInputReceiver, IUpdatable 		};  		world.registerUpdatable(this);+		this.initViews();+	}++	private initViews(){+		this._viewpoint.position = new THREE.Vector3();+		this._viewpoint.direction = new THREE.Vector3();+		this._viewpoints = {+			shared: [+				// {+				//   position: new THREE.Vector3( 0, 3, -5),+				//   direction: new THREE.Vector3(0, 3, 5),+				//   desc: 'Far'+				// },+				// {+				//   position: new THREE.Vector3( 0, 10, 0),+				//   direction: new THREE.Vector3(0, -20, 0),+				//   desc: 'Far top'+				// },+			],+			defaults: [+				{+					position: new THREE.Vector3( 0, 3, -5),+					direction: new THREE.Vector3(0, 3, 5),+				},+				{+					position: new THREE.Vector3( 0, 1, -5),+					direction: new THREE.Vector3(0, 3, 5),+				},+				{+					position: new THREE.Vector3( 0, .7, -.005),+					direction: new THREE.Vector3(0, 0, 0),+					lerp: false,+					desc: 'Inside'+				},+			],+			Airplane: [+				{+					position: new THREE.Vector3( 0, 3, -5),+					direction: new THREE.Vector3(0, 3, 5),+				},+				{+					position: new THREE.Vector3( 0, .7, -.15),+					direction: new THREE.Vector3(0, 0, 0),+					lerp: false,+					desc: 'Pilot'+				},+				{+					position: new THREE.Vector3( 0, 1, -5),+					direction: new THREE.Vector3(0, 3, 5),+				},+				{+					position: new THREE.Vector3( 0, .7, .2),+					direction: new THREE.Vector3(0, 0, 0),+					lerp: false,+					desc: 'Front'+				},+				{+					position: new THREE.Vector3( 0, 1, -1),+					direction: new THREE.Vector3(0, 0, 0),+					lerp: false,+					desc: 'Back'+				},+			],+			Character: [+				{+					position: new THREE.Vector3( 0, .5, -1.5),+					direction: new THREE.Vector3(0, .5, .5),+					desc: 'Third person'+				},+				{+					position: new THREE.Vector3( 0, .3, -.3),+					direction: new THREE.Vector3(0, 0, 10),+					lerp: false,+					desc: 'First person'+				},+				{+					position: new THREE.Vector3( -.5, .4, -1),+					direction: new THREE.Vector3(-.8, .4, .2),+					desc: 'Over the shoulder'+				},+		 ],+			Car: [+				{+					position: new THREE.Vector3( 0, 1, -3),+					direction: new THREE.Vector3(0, 1, 1),+					desc: 'Behind'+				},+				{+					position: new THREE.Vector3( .15, .6, .07),+					direction: new THREE.Vector3(0, 0, 0),+					lerp: false,+					desc: 'Driver'+				},+				{+					position: new THREE.Vector3( -.2, .6, 0),+					direction: new THREE.Vector3(3.14, 0, 0),+					lerp: false,+					desc: 'Passenger sit'+				},+				{+					position: new THREE.Vector3( 0, .5, 1),+					direction: new THREE.Vector3(0, 0, 0),+					lerp: false,+					desc: 'Front'+				},+			],+			Helicopter:+			[+				{+				position: new THREE.Vector3( 0, 2, -3),+				direction: new THREE.Vector3(0, 1, 1),+				},+				{+					position: new THREE.Vector3( .15, .3, .1),+					direction: new THREE.Vector3(0, 0, 0),+					lerp: false,+					desc: 'Pilot'+				},

Yet another example. I definitely couldn't accept these hard coded positions.

What if the airplane model changes slightly? Then these values would have to be painstakingly changed.

The way to do this would be to place referential empties in Blender, where every empty object would specify the position and orientation for given camera position. That way the positions would be tied to their respective vehicle (or even character) models.

eachtime

comment created time in 21 days

PullRequestReviewEvent

Pull request review commentswift502/Sketchbook

Cameras

 export class CameraOperator implements IInputReceiver, IUpdatable 		this.phi += deltaY * (this.sensitivity.y / 2); 		this.phi = Math.min(85, Math.max(-85, this.phi)); 	}+	public nextCamType(){+		this._currentCam.type++;+		this._currentCam.view = 0;+		if( ! this._currentCam.types[ this._currentCam.type ] )+		{+			this._currentCam.type = 0;+		}++		return this._currentCam.types[ this._currentCam.type ];+	}++	public nextView(){+		if( this._currentCam.views[ this._currentCam.view + 1 ]){+			this._currentCam.view++;+		} else {+			this._currentCam.view = 0;+		}+		return this._currentCam.view;+	}++	public get currentCamType(){+		return this._currentCam.types[ this._currentCam.type ];+	}++	public get currentCam(){+		return this._viewpoints[ this._currentCam.name ][ this._currentCam.view ];+	}  	public update(timeScale: number): void 	{-		if (this.followMode === true)-		{-			this.camera.position.y = THREE.MathUtils.clamp(this.camera.position.y, this.target.y, Number.POSITIVE_INFINITY);-			this.camera.lookAt(this.target);-			let newPos = this.target.clone().add(new THREE.Vector3().subVectors(this.camera.position, this.target).normalize().multiplyScalar(this.targetRadius));-			this.camera.position.x = newPos.x;-			this.camera.position.y = newPos.y;-			this.camera.position.z = newPos.z;++		switch ( this.currentCamType ) {+			case 'follow':+				this.followCam( timeScale );+				break;+			case 'free':+				this.freeCam();+				break;+				default:+				this.freeCam();+				break; 		}-		else -		{-			this.radius = THREE.MathUtils.lerp(this.radius, this.targetRadius, 0.1);-	-			this.camera.position.x = this.target.x + this.radius * Math.sin(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);-			this.camera.position.y = this.target.y + this.radius * Math.sin(this.phi * Math.PI / 180);-			this.camera.position.z = this.target.z + this.radius * Math.cos(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);-			this.camera.updateMatrix();-			this.camera.lookAt(this.target);++	}++	private freeCam( ){+		this.radius = THREE.MathUtils.lerp(this.radius, this.targetRadius, 0.1);+		this.camera.position.x = this.target.x + this.radius * Math.sin(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);+		this.camera.position.y = this.target.y + this.radius * Math.sin(this.phi * Math.PI / 180);+		this.camera.position.z = this.target.z + this.radius * Math.cos(this.theta * Math.PI / 180) * Math.cos(this.phi * Math.PI / 180);+		this.camera.updateMatrix();+		this.camera.lookAt(this.target);+	}++	private _viewpointRelativeTo(target: any){+		let name = target.classname;+		name = this._viewpoints[ name ] ? name : 'defaults';+		this._currentCam.name = name;+		this._currentCam.views = [ ...this._viewpoints[ this._currentCam.name ], ...this._viewpoints.shared ];++		const pov = this._currentCam.views[ this._currentCam.view ] ?? this._currentCam.views[ this._currentCam.views.length - 1 ];++		const position = pov.position.clone();+		position.applyQuaternion( target.quaternion );+		position.add( target.position );++		const direction = pov.direction.clone();+		direction.applyQuaternion( target.quaternion );+		direction.add( target.position );++		return { position, direction, lerp: pov.lerp };+	}++	private followCam( timeScale: number ){+		let player = this.world.characters.find( char => char.uuid === this.world.player_id );

Even less important are the particulars of the implementation. I only had a quick look through the code, but this line caught my eye.

Sketchbook already has a system for identifying the player. The InputManager has an inputReceiver variable, which is an entity that receives an input. Most of the time, that's the player. Adding a player_id to the world feels very strange to me and is an example of something I definitely couldn't merge.

Just an example, I only had a very quick look at the code. Even if our ideas matched and there were no issues, we would have to improve the implementation details.

eachtime

comment created time in 21 days

PullRequestReviewEvent

pull request commentswift502/Sketchbook

Cameras

I played around in the demo, and I appreciate your efforts, but I'm afraid your implementation isn't compatible with my idea of the GTA-style camera. Your changes are also quite vast and your implementation from a quick glance isn't up to my standard. But while the specific implementation could be easily improved, the general functionality just isn't what I was looking for.

My idea for the camera behavior

The most important thing is that our ideas for how the camera should behave are very different. For that reason alone I can't currently merge your changes. Hope you understand.

In my eyes, the behavior of the gta camera is quite well defined.

  1. The camera follows an entity using a very specific algorithm: a. Look at the car b. Set the distance between the camera and the entity to a specified radius

This results in a nice predictable behavior where the camera naturally orbits the entity it follows. For example, you seem to have implemented some sort of a car "reverse" camera, that's not what happens in GTA right? In GTA the camera naturally orbits so it's in front of the car, looking back.

  1. Joystick movement adjusts the camera orbit, but the camera still tends to fall into it's natural following algorithm. (I guess that's not applicable since Sketchbook doesn't support joystick input)

  2. Moving the mouse stops the following algorithm for several seconds (so it behaves like sketchbook currently does) and after a few seconds of no mouse input, the following logic kicks in again.

Your behavior is very different from how it behaves in GTA, which is what I wanted in Sketchbook. There's also too many camera modes for my personal taste, I feel the shortcuts are a bit impractical (I already closed my browser window by accidentally pressing ctrl+w), you can't seem to look around when you're driving in the first person, there seems to be micro-jittering on the default camera, etc., etc..


I'm just can't merge this into master, because the general idea isn't compatible with mine, sorry. But maybe there's no need. Sketchbook is my pet project where I implement stuff that I personally feel are right. This in a sense is your Sketchbook with your cool camera system right? 😃

Let me know what you want to do now. We can work further if you wanted to implement "my idea" of the camera behavior. But I don't expect you to want to do that.

eachtime

comment created time in 21 days

issue closedswift502/Sketchbook

Multiple cameras and points of view.

Hello everyone, first of all I want to thank you for all this amazing work. It is quite impressive!

I saw that you are planning to implement a kind of GTA-like follow camera. I gave it a try my self, I'm not there yet at all, but maybe it's worth taking a look at my code. I implemented it very naively but the result looks surprisingly good to me (I'm certainly not as exigent as you guys).

I have to make a few caveats though, I'm a little bit comfortable with JavaScript, but this is my first time with Typescript. I'm also not very good at maths or geometry. I read a few articles and saw a couple of videos on quaternions, three.js cameras and stuff, but this was more of a trial and error implementation, so it could hurt your eyes really bad.

Anyway, I would be glade to share my modifications and have some feedbacks. I created a new branch called cameras. Correct me if I'm wrong, but according to the GitHub documentation, I think that you have to create the same one in order for me to do a pull request. Or I can share it by any other means that is convenient for you. I can also put an instance on my server if you want to try it first to decide if it's worth it for you to take a look at the code.

closed time in 21 days

eachtime

issue commentswift502/Sketchbook

Multiple cameras and points of view.

I'll do it. 👍

eachtime

comment created time in 21 days

issue commentswift502/Sketchbook

Multiple cameras and points of view.

Hi!

Awesome. I'd definitely be interesting in checking out your changes and possibly merging them if we both like the final implementation.

You could've already made a pull request. https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request You can request pulls across different branches as well.

And you don't have to put an instance on your server (unless you want to). Just link me the repo (or better yet, create the pull request), I can build it and test it myself. I checked your profile but you seem to have no public repositories?

eachtime

comment created time in 21 days

push eventswift502/Web

swift502

commit sha 2db1cee939650c0476dfaee87be71b16c87892a3

update

view details

push time in 22 days

push eventswift502/Web

swift502

commit sha 7150090e3f57fb37e47112420deffb57d27f32ed

html lang

view details

push time in 22 days

push eventswift502/Web

swift502

commit sha eed12e9eaa18bf023b51488993b6d12152667eb9

update

view details

push time in 23 days

push eventswift502/Web

swift502

commit sha fccb86a8d07f3e0acea196637a17e1755b2c28ac

404 responsivity fix

view details

push time in 23 days

push eventswift502/Web

swift502

commit sha e91fa88e120607f414335831eb3798ac5705bd76

404 og data

view details

push time in 23 days

push eventswift502/Web

swift502

commit sha 0ba829cd0edff06a942f1aaf269e53aa859cba14

Update README.md

view details

push time in 23 days

push eventswift502/Web

swift502

commit sha e08bd509f89f15c4eee019e56705d13024feeb54

redundant page data

view details

push time in 23 days

push eventswift502/Web

swift502

commit sha c2e5dbb2e765cd060c2013558c11411542893582

update

view details

push time in 23 days

push eventswift502/Web

swift502

commit sha 8421acada3d81497cbaff0ff9fe0e98543ea6ce0

SEO

view details

push time in 23 days

push eventswift502/Web

swift502

commit sha 24bd9e72d7d7e5555f4f58481f749a7cf5a85e02

update

view details

push time in 23 days