VR Hand Interative Deformation Project
Team: 31
Names: Yun Chung Chang, Jiashen(Jason) Du, Panfeng(Gavin) Jiang, Zitong
(Peter) Hu
Link to webpage:
https://zx40224617.github.io/CS184_Final_Deliverables/
Link to GitHub repository:
Final Deliverables Website
Our Code Base (switch to master branch if you see nothing)
Link to Slides:
https://docs.google.com/presentation/d/1q-nhmrn9E7Ki5GwHW6Tn03XHFC5PPzgYxx3Citovl6E/edit?usp=sharing
Link to Videos:
https://drive.google.com/file/d/1Zw4CIiLIGkhweLPhIh0miRUF3K-n1QF2/view?usp=drive_link
Link to Proposal:
https://zx40224617.github.io/CS184FinalProposal/
Abstract
This project is inspired by CS184 Project 4 about physical simulation. We
aims to develop a real-time, interactive mesh deformation system for
virtual reality environments using Unity and Meta Quest 3. By enhancing
immersion through dynamic, responsive mesh modifications, we seek to
explore novel ways users can interact with and manipulate virtual objects
directly via hand tracking or controller inputs. From the baseline, we
improve the physical simulation by applying TBD for a more realistic
objects deformation. We also replace the original mesh with a customized
mesh and rewrite the code for multi-objects interactions in the same
scene. We also build an immersive scene for better experience.
Technical Approach
We implement custom Shader-Based Deformation: Leverages GPU-powered
shaders to compute and render mesh deformations at high performance
without modifying the underlying mesh data on the CPU.
GPU: Compute Buffer
In typical physics simulation, unlike in project 4, it usually involve a
much more complex mesh that contains huge amounts of verticies. In this
case, we will need to populate a buffer to hold the vertex information
including position and velocities on the GPU using Compute Buffers. It is
simply a memory container that the Compute Shader read and write to. This
is much more efficient since we can now compute parallely on the GPU
without relying on CPU for dealing with large amount of data.
To utilize compute buffer, we need to know how much storage that we need
exactly. In our case, for each Vertex struct, there are 8 floats including
position in 3 different axis, velocity in 3 different axis, and uv. So the
total memory that we need will ended up being
vertex_number * size_of_float * 8
Deformation in Compute Shader
Because we already have a per-vertex running program in compute shader, we
are able to do vertices movements in the unity environment. In
Modifymesh.compute, we are using similar modification only using the
approximation of a force, which is just some complicated and restricted
variables controlling the speed / displacement of the vertices movements.
There are multiple restriction terms we are using to achieve better
deformation simulation:
_distanceBegin; _distanceEnd; _pushforce; _elasticity; _drag;
_maxOffset; _stiffFalloff; _maxVelocity; _velocityBlend; _handEnabled;
We will list and explain our "regularization" terms that you can change
down below.
Parameter |
Purpose & Effect |
Typical Range we determined when tuning |
_distanceBegin |
Outer radius where hand influence starts; farther ⇒ easier to
press. When the distance from a vertex to a hand is ≤
_distanceBegin, the push force starts to grow from 0. Sets how far
you can be and still touch the object.
|
0.010 – 0.030 m |
_distanceEnd |
Inner radius where push force reaches full strength. At distance ≤
_distanceEnd the push force reaches its full magnitude. Think of
it as the “core” collision radius. Smaller values make the force
spike only when the hand is almost touching.
|
0.01 – 0.08 m (must be < _distanceBegin )
|
_pushforce |
Scalar impulse multiplier; higher ⇒ deeper dents. Too high may
cause instability or penetrations.
|
0.1 – 1 (plush) |
_elasticity |
Spring-like return force toward bind pose; controls rebound speed.
|
Increase for snappy rebound; decrease for slow “memory-foam”
return. Excessive values require higher _drag or _maxVelocity
clamping.
|
_drag |
Per-frame damping on velocity; lower ⇒ softer, higher ⇒ bouncy.
|
0.80 – 0.97 |
_maxOffset |
Maximum allowed displacement from initial position (safety clamp).
|
0.01 – 0.05 m |
_stiffFalloff |
Exponent shaping the fall-in curve; >1 stiff, <1 soft.
|
0.3 – 3.0 |
_maxVelocity |
Hard cap on per-vertex speed; prevents numerical explosions.
|
Keep low for delicate cloth, higher for rigid rubber. |
_velocityBlend |
Mix between positional push and hand-velocity push (0 → pos only,
1 → vel only). Lets you decide whether a quick slap matters more
than static penetration.
|
0 – 1 (0.5–0.7 feels natural) |
_handEnabled |
Just for debug use. |
0 = off, 1 = on |
Eye-watering tips if you want to tweak your objects to the desired
"feel".
Spatial bounds (_maxOffset, _distanceBegin, _distanceEnd) keep vertices
inside a safe range. Energy control (_pushforce, _elasticity, _drag,
_maxVelocity) ensures impulses don’t explode numerically and that energy
eventually dissipates. Force-shaping curves (_stiffFalloff,
_velocityBlend) smooth discontinuities that could otherwise create sudden
big tearings or jitter. Tweak these in pairs: If you raise _pushforce, you
almost always need a higher _drag or a lower _maxVelocity. Decreasing
_distanceEnd without adjusting _stiffFalloff can make forces too peaky;
raise the falloff exponent to compensate. Large _elasticity + low _drag +
high _maxOffset is the recipe for “spaghetti bear”—use clamps wisely.
Rendering
After the verticies have be altered, the compute shader are responsible
for rendering that reflects the changes. In the baseline project, there
are 2 differnet methods that are implemented, but we are focusing on the
one that we ended up using here, which is DrawProcedural.
In order to implement DrawProcedural, we need to turn off the MeshRenderer
whenever this method is selected. We first need to initiliaze a Structured
Buffer and bind it on the CPU side in the vertex shader. So we are
bascially just reading from the Compute Shader to access the position and
velocity after deformation. For sampling, we can use the VertexID
supported in Unity since the Structured Buffer has the same order as the
vertex buffer.
Bur for DrawProcedural, we need another Buffer called Index Buffer, which
we simply just copy the triangles of the mesh into a Graphics Buffer that
allows us to draw the traingles based on the deformed verticies as we
already read as mentioned above.
Hand Interaction
The idea here is really easy, we first calculate the distance between
verticies and hand using the positions. and base on distance, apply
differnt level of pusing force using HLSL built in functions smoothstep().
Also, since we only want pushing force, we calculate the dot product of
the hand moving direction and the vertex. Using the HLSL built in function
saturate() to clamp out negtaive values so that there onlt force apply
when the vertex is relatively in front of the hand.
Results
Result for Soft Object Deformation
Teddy Bear Deformation
|
Sofa Deformation
|
Comparison between our implementation and baseline implementation
Our Implementation
|
Base Line Implementation
|
References