Recently a new example textures_mouse_painting was added to raylib, and I thought “that’s neat scribbling on a texture…. hmm….” wouldn’t it be cool to paint on a 3d model instead, while looking at models_mesh_picking, thinking “nah this is going to be too complicated”, I noticed it was using Vector3Barycenter “oooh…..” I thought! I seem to remember that has something to do with interpolating textures on a triangle when rendering. After a slight false start, it all came together quite quickly, there’s some source code below to demonstrate the technique but before explaining the maths, I’ll detail the controls for the demo – there’s a whole bunch as I was too lazy to build a proper GUI!
- Moving the mouse wheel with the shift key held down, moves the camera towards and away from the model
- Mouse wheel without shift changes the size of the drawing cursor
- If you press the s key the texture is saved to disk
- Holding shift down with a, w, x or d held down, moves the model up down left and right
- d, a, w, x, z, c keys rotates the model
- f and v changes the red component of the cursor colour
- g and b changes the green component of the cursor colour
- h and n changes the blue component of the cursor colour
- holding down p colours the whole of the current triangle with the cursor colour
- hold down l (lower case L) to draw a line from the previously clicked location to the point you’ve just clicked.
YUK a program desperately in need of a GUI….!
Right math time! First there is a bonus routine to make a single Matrix from 3 Euler angles, this saves having to multiply three matrices together… Its not ideal as you can induce gimbal lock, I might do a later post on a technique that uses cumulative Quaternion rotations to side step this issue but that’s something for a later date…
I’ll assume you have seen the models_mesh_picking example and understand it, if not have a quick look its simple enough…
Because info like texture coordinates and barycentre info isn’t commonly needed when doing 3d picking, its very understandably missing from raylibs model picking, I simply copied and pasted the appropriate code and added the info I needed.
Barycentre coordinates can very simply converted to UV coordinates if you have the 3 UV coordinates of the triangle in question
float u = mhi.bazza.x * mhi.uv1.x + mhi.bazza.y * mhi.uv2.x + mhi.bazza.z * mhi.uv3.x; float v = mhi.bazza.x * mhi.uv1.y + mhi.bazza.y * mhi.uv2.y + mhi.bazza.z * mhi.uv3.y;
Once you have UV coordinates then everything else is just 2d drawing, which just goes to show – when something initially looks complex, sometimes with the right technique everything falls into place rather easily.
Because I wanted to render cursors on the model I needed to use two render textures, one that the actual drawing is done on, and one that actually textures the model, each frame the drawing texture is used to “clear” the texture that’s actually used on the model, we then have a clean sheet we can render triangles and cursors on.
I’d be willing to collaborate on this with someone, if you’re interested in taking this further, but in the mean time here’s the source.