mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
more hair tweaks, don’t render in 1P, improved toy ball
This commit is contained in:
parent
95a66a06af
commit
88c01266ab
4 changed files with 50 additions and 33 deletions
|
@ -26,14 +26,21 @@ var RIGHT_TIP = 3;
|
|||
var RIGHT_BUTTON_FWD = 11;
|
||||
var RIGHT_BUTTON_3 = 9;
|
||||
|
||||
var BALL_RADIUS = 0.08;
|
||||
var GRAVITY_STRENGTH = 0.5;
|
||||
|
||||
var HELD_COLOR = { red: 240, green: 0, blue: 0 };
|
||||
var THROWN_COLOR = { red: 128, green: 0, blue: 0 };
|
||||
|
||||
var leftBallAlreadyInHand = false;
|
||||
var rightBallAlreadyInHand = false;
|
||||
var leftHandParticle;
|
||||
var rightHandParticle;
|
||||
|
||||
var throwSound = new Sound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw");
|
||||
var newSound = new Sound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw");
|
||||
var catchSound = new Sound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw");
|
||||
var targetRadius = 0.25;
|
||||
var throwSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Switches%20and%20sliders/slider%20-%20whoosh1.raw");
|
||||
var targetRadius = 1.0;
|
||||
|
||||
|
||||
var wantDebugging = false;
|
||||
|
@ -54,7 +61,7 @@ function getBallHoldPosition(whichSide) {
|
|||
tipPosition = Controller.getSpatialControlPosition(RIGHT_TIP);
|
||||
}
|
||||
|
||||
var BALL_FORWARD_OFFSET = 0.08; // put the ball a bit forward of fingers
|
||||
var BALL_FORWARD_OFFSET = 0.15; // put the ball a bit forward of fingers
|
||||
position = { x: BALL_FORWARD_OFFSET * normal.x,
|
||||
y: BALL_FORWARD_OFFSET * normal.y,
|
||||
z: BALL_FORWARD_OFFSET * normal.z };
|
||||
|
@ -69,6 +76,7 @@ function getBallHoldPosition(whichSide) {
|
|||
function checkControllerSide(whichSide) {
|
||||
var BUTTON_FWD;
|
||||
var BUTTON_3;
|
||||
var TRIGGER;
|
||||
var palmPosition;
|
||||
var ballAlreadyInHand;
|
||||
var handMessage;
|
||||
|
@ -76,18 +84,20 @@ function checkControllerSide(whichSide) {
|
|||
if (whichSide == LEFT_PALM) {
|
||||
BUTTON_FWD = LEFT_BUTTON_FWD;
|
||||
BUTTON_3 = LEFT_BUTTON_3;
|
||||
TRIGGER = 0;
|
||||
palmPosition = Controller.getSpatialControlPosition(LEFT_PALM);
|
||||
ballAlreadyInHand = leftBallAlreadyInHand;
|
||||
handMessage = "LEFT";
|
||||
} else {
|
||||
BUTTON_FWD = RIGHT_BUTTON_FWD;
|
||||
BUTTON_3 = RIGHT_BUTTON_3;
|
||||
TRIGGER = 1;
|
||||
palmPosition = Controller.getSpatialControlPosition(RIGHT_PALM);
|
||||
ballAlreadyInHand = rightBallAlreadyInHand;
|
||||
handMessage = "RIGHT";
|
||||
}
|
||||
|
||||
var grabButtonPressed = (Controller.isButtonPressed(BUTTON_FWD) || Controller.isButtonPressed(BUTTON_3));
|
||||
|
||||
var grabButtonPressed = (Controller.isButtonPressed(BUTTON_FWD) || Controller.isButtonPressed(BUTTON_3) || (Controller.getTriggerValue(TRIGGER) > 0.5));
|
||||
|
||||
// If I don't currently have a ball in my hand, then try to catch closest one
|
||||
if (!ballAlreadyInHand && grabButtonPressed) {
|
||||
|
@ -107,8 +117,11 @@ function checkControllerSide(whichSide) {
|
|||
var ballPosition = getBallHoldPosition(whichSide);
|
||||
var properties = { position: { x: ballPosition.x,
|
||||
y: ballPosition.y,
|
||||
z: ballPosition.z },
|
||||
velocity : { x: 0, y: 0, z: 0}, inHand: true };
|
||||
z: ballPosition.z },
|
||||
color: HELD_COLOR,
|
||||
velocity : { x: 0, y: 0, z: 0},
|
||||
lifetime : 600,
|
||||
inHand: true };
|
||||
Particles.editParticle(closestParticle, properties);
|
||||
|
||||
var options = new AudioInjectionOptions();
|
||||
|
@ -127,7 +140,7 @@ function checkControllerSide(whichSide) {
|
|||
//}
|
||||
|
||||
// If '3' is pressed, and not holding a ball, make a new one
|
||||
if (Controller.isButtonPressed(BUTTON_3) && !ballAlreadyInHand) {
|
||||
if (grabButtonPressed && !ballAlreadyInHand) {
|
||||
var ballPosition = getBallHoldPosition(whichSide);
|
||||
var properties = { position: { x: ballPosition.x,
|
||||
y: ballPosition.y,
|
||||
|
@ -135,11 +148,11 @@ function checkControllerSide(whichSide) {
|
|||
velocity: { x: 0, y: 0, z: 0},
|
||||
gravity: { x: 0, y: 0, z: 0},
|
||||
inHand: true,
|
||||
radius: 0.05,
|
||||
radius: BALL_RADIUS,
|
||||
damping: 0.999,
|
||||
color: { red: 255, green: 0, blue: 0 },
|
||||
color: HELD_COLOR,
|
||||
|
||||
lifetime: 10 // 10 seconds - same as default, not needed but here as an example
|
||||
lifetime: 600 // 10 seconds - same as default, not needed but here as an example
|
||||
};
|
||||
|
||||
newParticle = Particles.addParticle(properties);
|
||||
|
@ -155,7 +168,7 @@ function checkControllerSide(whichSide) {
|
|||
var options = new AudioInjectionOptions();
|
||||
options.position = ballPosition;
|
||||
options.volume = 1.0;
|
||||
Audio.playSound(catchSound, options);
|
||||
Audio.playSound(newSound, options);
|
||||
|
||||
return; // exit early
|
||||
}
|
||||
|
@ -188,7 +201,9 @@ function checkControllerSide(whichSide) {
|
|||
y: tipVelocity.y * THROWN_VELOCITY_SCALING,
|
||||
z: tipVelocity.z * THROWN_VELOCITY_SCALING } ,
|
||||
inHand: false,
|
||||
gravity: { x: 0, y: -2, z: 0},
|
||||
color: THROWN_COLOR,
|
||||
lifetime: 10,
|
||||
gravity: { x: 0, y: -GRAVITY_STRENGTH, z: 0},
|
||||
};
|
||||
|
||||
Particles.editParticle(handParticle, properties);
|
||||
|
|
|
@ -379,22 +379,22 @@ void Avatar::renderBody(RenderMode renderMode, float glowLevel) {
|
|||
renderHair();
|
||||
}
|
||||
|
||||
const float HAIR_LENGTH = 0.4f;
|
||||
const float HAIR_LENGTH = 0.2f;
|
||||
const float HAIR_LINK_LENGTH = HAIR_LENGTH / HAIR_LINKS;
|
||||
const float HAIR_DAMPING = 0.99f;
|
||||
const float HEAD_RADIUS = 0.25f;
|
||||
const float HEAD_RADIUS = 0.15f;
|
||||
const float COLLISION_RELAXATION = 10.f;
|
||||
const float CONSTRAINT_RELAXATION = 10.0f;
|
||||
const float NOISE = 0.0f; // 0.1f;
|
||||
const float NOISE_MAGNITUDE = 0.02f;
|
||||
const glm::vec3 HAIR_GRAVITY(0.f, -0.05f, 0.f);
|
||||
const glm::vec3 HAIR_GRAVITY(0.f, -0.005f, 0.f);
|
||||
const float HAIR_ACCELERATION_COUPLING = 0.025f;
|
||||
const float HAIR_ANGULAR_VELOCITY_COUPLING = 0.15f;
|
||||
const float HAIR_MAX_LINEAR_ACCELERATION = 5.f;
|
||||
const float HAIR_ANGULAR_VELOCITY_COUPLING = 0.10f;
|
||||
const float HAIR_MAX_LINEAR_ACCELERATION = 4.f;
|
||||
const float HAIR_THICKNESS = 0.025f;
|
||||
const float HAIR_STIFFNESS = 0.002f;
|
||||
const glm::vec3 HAIR_COLOR1(0.98f, 0.92f, 0.843f);
|
||||
const glm::vec3 HAIR_COLOR2(0.545f, 0.533f, 0.47f);
|
||||
const glm::vec3 WIND_DIRECTION(1.0f, -1.0f, 0.f);
|
||||
const glm::vec3 WIND_DIRECTION(0.5f, -1.0f, 0.f);
|
||||
const float MAX_WIND_STRENGTH = 0.01f;
|
||||
|
||||
void Avatar::renderHair() {
|
||||
//
|
||||
|
@ -447,18 +447,14 @@ void Avatar::simulateHair(float deltaTime) {
|
|||
acceleration = acceleration * rotation;
|
||||
glm::vec3 angularVelocity = getAngularVelocity() + getHead()->getAngularVelocity();
|
||||
|
||||
float windIntensity = randFloat() * 0.02f;
|
||||
float windIntensity = randFloat() * MAX_WIND_STRENGTH;
|
||||
|
||||
for (int strand = 0; strand < HAIR_STRANDS; strand++) {
|
||||
for (int link = 0; link < HAIR_LINKS; link++) {
|
||||
int vertexIndex = strand * HAIR_LINKS + link;
|
||||
if (vertexIndex % HAIR_LINKS == 0) {
|
||||
// Base Joint - no integration
|
||||
if (randFloat() < NOISE) {
|
||||
// Move base of hair
|
||||
_hairPosition[vertexIndex] += randVector() * NOISE_MAGNITUDE;
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
//
|
||||
// Vertlet Integration
|
||||
//
|
||||
|
@ -477,6 +473,10 @@ void Avatar::simulateHair(float deltaTime) {
|
|||
// Add linear acceleration of the avatar body
|
||||
_hairPosition[vertexIndex] -= acceleration * HAIR_ACCELERATION_COUPLING * deltaTime;
|
||||
|
||||
// Add stiffness (product)
|
||||
_hairPosition[vertexIndex] += (_hairOriginalPosition[vertexIndex] - _hairPosition[vertexIndex])
|
||||
* powf(1.f - link / HAIR_LINKS, 2.f) * HAIR_STIFFNESS;
|
||||
|
||||
// Add some wind
|
||||
glm::vec3 wind = WIND_DIRECTION * windIntensity;
|
||||
_hairPosition[vertexIndex] += wind * deltaTime;
|
||||
|
@ -529,17 +529,17 @@ void Avatar::simulateHair(float deltaTime) {
|
|||
}
|
||||
|
||||
void Avatar::initializeHair() {
|
||||
const float FACE_WIDTH = 0.25f * PI;
|
||||
const float FACE_WIDTH = PI / 4.0f;
|
||||
glm::vec3 thisVertex;
|
||||
for (int strand = 0; strand < HAIR_STRANDS; strand++) {
|
||||
float strandAngle = randFloat() * PI;
|
||||
float azimuth = randFloat() * 2.f * PI;
|
||||
float elevation;
|
||||
if ((azimuth > FACE_WIDTH) || (azimuth < -FACE_WIDTH)) {
|
||||
float azimuth = FACE_WIDTH / 2.0f + (randFloat() * (2.0 * PI - FACE_WIDTH));
|
||||
float elevation = PI_OVER_TWO - (randFloat() * 0.75 * PI);
|
||||
/*if ((azimuth > FACE_WIDTH) || (azimuth < -FACE_WIDTH)) {
|
||||
elevation = randFloat() * PI_OVER_TWO;
|
||||
} else {
|
||||
elevation = (PI_OVER_TWO / 2.f) + randFloat() * (PI_OVER_TWO / 2.f);
|
||||
}
|
||||
}*/
|
||||
glm::vec3 thisStrand(sinf(azimuth) * cosf(elevation), sinf(elevation), -cosf(azimuth) * cosf(elevation));
|
||||
thisStrand *= HEAD_RADIUS + 0.01f;
|
||||
|
||||
|
@ -562,6 +562,7 @@ void Avatar::initializeHair() {
|
|||
}
|
||||
_hairPosition[vertexIndex] = thisVertex;
|
||||
_hairLastPosition[vertexIndex] = _hairPosition[vertexIndex];
|
||||
_hairOriginalPosition[vertexIndex] = _hairPosition[vertexIndex];
|
||||
|
||||
_hairQuadDelta[vertexIndex] = glm::vec3(cos(strandAngle) * HAIR_THICKNESS, 0.f, sin(strandAngle) * HAIR_THICKNESS);
|
||||
_hairNormals[vertexIndex] = glm::normalize(randVector());
|
||||
|
|
|
@ -201,6 +201,7 @@ protected:
|
|||
virtual void updateJointMappings();
|
||||
|
||||
glm::vec3 _hairPosition[HAIR_STRANDS * HAIR_LINKS];
|
||||
glm::vec3 _hairOriginalPosition[HAIR_STRANDS * HAIR_LINKS];
|
||||
glm::vec3 _hairLastPosition[HAIR_STRANDS * HAIR_LINKS];
|
||||
glm::vec3 _hairQuadDelta[HAIR_STRANDS * HAIR_LINKS];
|
||||
glm::vec3 _hairNormals[HAIR_STRANDS * HAIR_LINKS];
|
||||
|
|
|
@ -833,9 +833,9 @@ void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
|
|||
// Render head so long as the camera isn't inside it
|
||||
if (shouldRenderHead(Application::getInstance()->getCamera()->getPosition(), renderMode)) {
|
||||
getHead()->render(1.0f, modelRenderMode);
|
||||
renderHair();
|
||||
}
|
||||
getHand()->render(true, modelRenderMode);
|
||||
renderHair();
|
||||
}
|
||||
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
||||
|
|
Loading…
Reference in a new issue