Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Paint In 3D ✍️ Paint In Editor✏️ Paint In 2D

Discussion in 'Assets and Asset Store' started by Darkcoder, Jul 10, 2018.

  1. Danielsantalla

    Danielsantalla

    Joined:
    Jan 7, 2015
    Posts:
    75
    Hi guys. Is there a way to make this plugin work with a game object that has a non-convex mesh collider + rigidbody in VR? I'm using p3d hit between but this requires a convex mesh collider on my meshes.

    Edit: I've found that p3dHitNearby doesn't need a collider. How can I mask by layer that component just like p3dhitbetween?
     
    Last edited: Dec 15, 2021
  2. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    Rigidbodies only work with convex MeshColliders in Unity. To make a non-convex MeshCollider you must make a compound collider from multiple convex MeshCollider pieces. There are assets and probably workflows with Blender or something that can generate these for you.

    P3dHitNearby only sends position and rotation data to components like P3dPaintSphere, so it cannot filter any layers. However, paint components like P3dPaintSphere has the Layers and Group setting which allows you to do this.
     
  3. spikezart

    spikezart

    Joined:
    Oct 28, 2021
    Posts:
    72
    Hey there, Im very excited Ive come across this asset. Ive done a bit of searching but felt it better if I could ask some basics directly. Can I use this asset to enable my app users to paint a 3d object (maybe even with an idle animation looping), and save as a new 3d object ? Im thinking how an app user could use this in a 3d environment to, for example, paint their house.
    Thanks
     
  4. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    Yes, as long as:

    1) Your mesh is UV mapped properly without overlap or tiling. You can see the documentation for more information.

    2) If you're using mouse/touch painting then your mesh must have colliders that are similar to the visual mesh. If your mesh has animation then you will need to add colliders to the bones or some other technique.
     
    spikezart likes this.
  5. spikezart

    spikezart

    Joined:
    Oct 28, 2021
    Posts:
    72
    Thank you :)
     
    Darkcoder likes this.
  6. Danielsantalla

    Danielsantalla

    Joined:
    Jan 7, 2015
    Posts:
    75
    Hi guys. Is there a way to get an old version of the plugin? I updated to the latest and forgot to backup the package and now I can’t go back :/
     
  7. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    Nope, you're stuck forever! If you say which version you had before, then Santa may be able to send it though.
     
  8. happydays1286

    happydays1286

    Joined:
    Dec 23, 2020
    Posts:
    1
    Hi everyone :) how can I use PaintDecal to draw in the desired color without mixing it with the color of the material I'm drawing on?
     
    Last edited: Dec 28, 2021
  9. mag_

    mag_

    Joined:
    Nov 12, 2013
    Posts:
    1
    Hi! I've been finally testing and trying to learn this great asset, but as much as I struggled, I couldn't figure out a way to do something that is essential to my project -- to export a painted texture exactly how it shows in play mode.

    I managed to use GetPngData and WriteAllBytes, but the resulting png doesn't show all the colors that appear in play mode. The same thing happens if I try to export the texture through the Paintin3d window -- the exported png won't show all the colors, even though they're actually there and show correctly when I click the load button.

    I'm using P3dBlendMode.Additive to paint the Albedo group of an Unlit material, with Fade Rendering mode and Overlay Color mode, so if I paint red over green, for example, it becomes yellow, but that yellow doesn't appear in the exported png. Is there any way to make it work, please? Any help would be greatly appreciated!

    Edit: I've finally achieved some success with Graphics.Blit and ReadPixels... is there any better/easier way?
     
    Last edited: Dec 29, 2021
  10. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    You set your material to white, and set the original material's color in the P3dPaintableTexture's Color setting instead.

    I don't understand what the issue with GetPngData is. If the yellow doesn't appear, then what does appear?
     
  11. RonnieGaikwad

    RonnieGaikwad

    Joined:
    May 14, 2017
    Posts:
    13
    HEY HOW CAN I MAKE AN OBJECT GET PAINTED WHEN A EMPTY OBJECT WITHOUT COLLIDER MOVES OVER IT?

    I'm making a spiral roll game -
    https://image.winudf.com/v2/image1/...kxNjcxXzAyMw/screen-1.jpg?fakeurl=1&type=.jpg

    and i was planning a tilling trail behind the chisel to make it look like roll is being cut from the wood, and i think i should add a empty object to the chisel that will paint the wood with texture. How would you suggest me to do this?

    Gameplay link -
     
    Last edited: Dec 30, 2021
  12. NotEvenTrying

    NotEvenTrying

    Joined:
    May 17, 2017
    Posts:
    43
    Hi, I've been using this to do some texture painting in-editor, but I'm a little unsure on working with multiple albedo textures for a single mesh, as it doesn't seem to be supported out of the box - currently my shader uses multiple albedo textures stacked on top of one another based on alpha (like different layers in photoshop for example), and I would like to be able to toggle between painting the different textures on the same object without having to exit play mode, change the setup, and enter play mode again, as that is far too tedious. Any ideas?
     
  13. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    YOU CAN USE THE P3DHitNearby COMPONENT, AS SEEN IN THE "37 Nearby Painting" DEMO SCENE :)

    In your example video it looks like the mesh itself is being modified or removed to reveal the deeper cut wood though, so it doesn't require painting unless you want to do this all in a custom shader.


    This can be done by setting up multiple P3dPaintTexture components, one for each layer. You can either make a new group for each layer like Albedo1, Albedo2, etc, and then write a custom script to switch the albedo group of your painting tool. Or, you can set the active layer to the Albedo group, set the others to DUMMY, and have a custom script that switches between them. In either case this is a very project-specific setup that would require a little custom code to handle. You may even want to make some custom code to configure your object for painting with the correct P3dPaintableTexture components, because I'm not sure if the preset system can support this kind of scenario.
     
  14. NotEvenTrying

    NotEvenTrying

    Joined:
    May 17, 2017
    Posts:
    43
    Ah I see, I saw a warning box when I assigned multiple P3dPaintableTexture components to the same albedo texture, so I assumed it wasn't compatible - I'll give it a shot!
     
  15. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    Great! Indeed, the warning is just about painting multiple textures on the same material with the same group. Without isolating the group or using multiple groups every layer will receive the same paint which likely isn't what anyone wants. The most common painting scenario with multiple textures of the same group is if your mesh has multiple sub groups, which requires multiple materials to render, so it's easy for users to forget to change the material index in the paintable texture's slot setting.
     
  16. knas01

    knas01

    Joined:
    Feb 24, 2018
    Posts:
    236
    So I was reading the documentation for painting custom shaders and I saw that the mesh should not be moving. The problem is I want to paint damage effects and I have no static meshes at all in the scene.
    So what can I get away with here? It said simple stuff will still work but I don't know what that is really. What I must have in the shader is a main texture, normal and an emission mask and I want this to tile if the paint area is large enough. Parallax would be nice but not required.

    What could my problems with this be?
     
  17. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    This is referring to the mesh VERTEX positions, because your shader could be moving them anywhere with no way for Paint in 3D to know. You can of course move the object as you like. Same thing with the UVs.

    The distance you could move these depends on your tolerance for a disparity between where you paint and where the paint appears.
     
  18. knas01

    knas01

    Joined:
    Feb 24, 2018
    Posts:
    236
    Ok, that's a bit technical for me. Are you saying that as long as the mesh doesn't move or change shape from the shader I'm fine? This doesn't matter at all if I just change the objects transform?
     
  19. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    Yes, all Transform and skinned mesh animation / blend shape movement is supported. All shader movement and UV adjustment will be ignored.
     
    knas01 likes this.
  20. knas01

    knas01

    Joined:
    Feb 24, 2018
    Posts:
    236
    Very nice, thanks.
     
    Darkcoder likes this.
  21. sdogan

    sdogan

    Joined:
    Dec 20, 2021
    Posts:
    1
    Hi, is there a way to use paintable texture and change counter work with each other? I have paintable texture and changecounter. Changecounter can't calculate different colors i choose at runtime. When i set same color values for change counter and paintable texture's color it works fine but i want it work for different colors i choose it runtime. Also i work with sprays(hit particles, paint sphere)
     
  22. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    I'm not sure I understand the issue. P3dChangeCounter tells you the difference between the Texture × Color settings you specify, and the Target P3dPaintableTexture. You can always change the Texture or Color to compare your paintable texture to something else.

    If you need to be able to detect how many pixels you've painted even if they are the same color, then you must use the P3dChannelCounter with a transparent texture layer, then you can count the alpha channel pixels.
     
    sdogan likes this.
  23. Danielsantalla

    Danielsantalla

    Joined:
    Jan 7, 2015
    Posts:
    75
    thanks A LOT! I need version 1.11.3 . My email is josedanielsantalla@gmail.com , let me know if you wanna see my Unity asset store receipt. Again, Thanks!
     

    Attached Files:

  24. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    Sent!
     
  25. NotEvenTrying

    NotEvenTrying

    Joined:
    May 17, 2017
    Posts:
    43
    I just found it funny that @Darkcoder said "Santa may be able to send it ", and that "santa" is part of your name :D
     
    Darkcoder likes this.
  26. RonnieGaikwad

    RonnieGaikwad

    Joined:
    May 14, 2017
    Posts:
    13
    Hi I'm using the "Holes" scene example to actually make it look like the mesh is being cut, for this I added a extra layer of mesh at top to show its being cutting down, What i now wanna know is how can i make it look like cutting down without using the "matte white" and instead using the toony color pro material, Also how to make it cut if the mesh has two materials on it? right now I'm using 2 toony color pro material on it each with different texture.

    Right now I'm using splines which consists of same cube mesh lined together to form a path, when i use a small unity cube then the spline creates large number of same cube lined together and form the path, in this case when the cutting of mesh starts the cutting happens on all cubes at same time, so I'm using a large cube with lots of vertices so the splines doesnot need to create more cubes to create path instead it deforms the cube with lots of vertices into a path,but this can get very performance heavy, so is there a way that i can use normal unity cube on splines but they dont get cut at the same time but one by one.
     
  27. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    The holes example uses a white paintable texture. To make it look like wood you just need to change the paintable texture component's Texture setting to wood. I've never used the Toony Color Pro asset, but if this shader has an albedo texture then it should work if it's on the _MainTex slot, if not you must change it to whatever the texture slot name is for the albedo.

    To optimize this you would either move the vertices down when cutting, or cut 'holes' in the texture. You can move the vertices down using a custom vertex shader and paint a texture that defines how far to move down using Paint in 3D. This would require the mesh to be UV mapped where each part of the mesh has unique UV area. Optimizing this is very game specific and probably requires a lot of custom code and maybe shaders and isn't really related to Paint in 3D so I can't help you much.
     
  28. DrViJ

    DrViJ

    Joined:
    Feb 9, 2013
    Posts:
    158
    Hi! First I want to thank you for creation of this plugin, It's very easy to use and there are so many example scenes that help to start working with it.

    Could you please tell if plugin should work in Unity 2021.2 and WebGL 2? I see that painting works, but percent of painted zone could not be calculated in Google Chrome. It gives errors like this:

    Code (CSharp):
    1. glMapBufferRange is only supported when access is MAP_WRITE|INVALIDATE_BUFFER
    2. WebGL: INVALID_OPERATION: readPixels: buffer is not large enough for dimensions
    p.s. I can create test scene or send bug report if you need. But maybe it is just unsupported feature so I decided to write here to find out :)
     
    Last edited: Jan 9, 2022
  29. GreaterHawkeye

    GreaterHawkeye

    Joined:
    Apr 13, 2017
    Posts:
    34
    Hi @Darkcoder!

    Is there any equivalent of the P3DPaintSphere but for a square? I would like to use a square as a brush for painting but a standard square decal does not work as well as your P3DPaintSphere, for example a decal does not take "hardness" into account.

    Thanks!
     
    DrViJ likes this.
  30. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    I couldn't get a 2021.2 WebGL 2 build to work, but I got a build to work in 2021.1.15f1 and noticed no issues with demo scene 53. Based on the error message you get, it seems like your browser is running out of memory. Perhaps you're trying to read a high resolution texture, or your browser is out of memory, or Unity somehow limits the maximum moery or something like this.

    P3dPaintDecal is designed to do this. The Hardness setting for this controls the hardness of the depth/z. The x/y axes hardness is controlled by the Texture/Shape.
     
    DrViJ likes this.
  31. villaman

    villaman

    Joined:
    Apr 21, 2021
    Posts:
    69
    Hello,
    I have a couple of questions.
    1) My goal is to animate what the user painted. In other words, the user paints on some 3D object. Later, the user can "replay" what they painted from scratch. Is a behind-the-scenes undo/redo the best way to achieve this? i.e. When the user clicks "replay paint", behind-the-scenes, the painting is "undone" to the start and then the "redos" programatically applied in sequence to create the animated effect?

    2) If undo/redo is the appropriate method, what kinds of modifications can one make from the point in time the object was painted to the point in time the "paint animation" is replayed?
    a) Object is transformed (translated, rotated, scaled)
    b) Object mesh is deformed (but keeping its mesh vertices and triangles intact.. i.e.. vertices are only moved, not added or deleted)
    c) Object mesh is deformed but its vertices and triangles are not intact (eg. applying something like Rayfire)
    d) Object shader displaces vertices.

    Reading the forum, it seems to me that 2d would not work. I did a couple of experiments and it seems that 2a and 2b do work. i.e. I can paint, undo the paint, transform and deform the object and then redo and the paint is applied in the correct place. Would 2c work?

    I wanted to confirm that this would work in theory and not just in the couple of examples I happened to pick. If only 2a and 2b would work, then it would imply that the undo/redo is based on vertex id?

    Lastly, I'm a little surprised that 2a and 2b work because of a comment in the documentation. Under the "Serialization" section it mentions that paint hits are stored in world space. So if the object was moved/deformed (2a/2b), then when deserialization would happen the paint would appear in the wrong place?

    If I want to have the undo/redo survive game restarts, then presumably I need to serialize the undo/redo commands and I would run into this issue and even 2a and 2b would not work?

    However, in the save/load example scene, I painted the object, saved the paint, stopped the game, moved the object and ran the game again. The paint correctly moved (case 2a). So, it seems that serialization/deserialization does indeed not have this world space issue?

    I'm hoping the answer is that I can do 2a and 2b and serialize (i.e. have it survive game restarts) the undo/redo commands in such a way that this "serialization in world space" is not an issue. Is that a fair assumption?

    If this is not good assumption, how would one achieve this? Somehow convert hits to be based on vertex id and apply them back based on the current position/normal of the same vertex id?

    thanks for your time and great asset btw!
     
  32. DrViJ

    DrViJ

    Joined:
    Feb 9, 2013
    Posts:
    158
    I will try to investigate the problem deeper, can I post here the results if I find some more info about this?

    p.s. Thats how scene 53 works in Unity 2021.2.7
     
    Last edited: Jan 11, 2022
  33. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    1, 2, 2a, and some of 2b, 2d are possible. 2c would not be.

    Paint hits are stored/handled in world space, so they aren't so useful unless you only have one object - in which case you could transform the hit data into local space when saving, and then back into world space before you apply them again. For multiple objects you should use the lower level paint commands, which are stored per-object, and have built in commands to transform between local <-> world space. You can see the "89 Command Serialization" demo scene for an example of how to listen for paint commands, and then repaint an object using them.

    The Undo/Redo system is only designed for undo/redo. This 'could' be used for your scenario, but if you have many paint strokes then it will be a waste of memory and very slow. Manually drawing the commands one by one from your own list will be much faster, and also look smoother since you can do one paint command per frame or similar, instead of per undo state, which may be a lot of paint.


    Sure. I recommend you profile the memory of your system, browser, etc. You can also try and see if a much lower resolution texture works, try different versions of Unity, etc.
     
  34. villaman

    villaman

    Joined:
    Apr 21, 2021
    Posts:
    69
    Thanks for your quick response.

    In my case I only have a single GameObject (with a P3DPaintableTexture) active at a time so I will always know the target GameObject. So, it may be simpler for me to use the IHit*** approach which avoids the issue of managing persistent hashing for many textures and GameObjects. I essentially have another form of persistent id.

    If I go with this approach, I have a few additional questions

    1) How should undo/redo be handled? If the user does an "undo" one would presumably need to undo the serialized hits (or serialized commands). For example, if I have hit1, hit2, hit3... etc. and the user does an "undo", then both the undo state and my list should undo the same set of hits. Does the built-in undo ever undo more than a single (non-preview) hit at a time? If yes, I assume this means that I have to re-implement undo/redo so that these are the same?

    I assume the command serialization approach has the same issue?

    2) Since I want to make my "replay animation" work even with a deforming mesh, not just a transform, I assume it is not sufficient to convert from global to local space? I presume I would have to further convert to local UV space? Essentially, after getting the local position, traversing the mesh triangles and looking to see whether the local position lies within a triangle and if yes, interpolating the triangle UV's to get the UV corresponding to the position? And then on "replay" going from UV->Local->Global.

    3) I assume I would need to implement all the interfaces IHitCoord, IHitLine, IHitPoint, IHitQuad and IHitTriangle?

    4) When is IHitCoord called? I noticed that in the "basic" demo, IHitCoord seems not to be called, but IHitPoint is. In the basic demo how is the world position obtained if not by raycast from mouse to mesh?

    thanks!
     
  35. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    1 - The undo/redo system works using the StoreState method on each P3dPaintableTexture, which is called by components like P3dHitScreen when you first touch the screen and begin painting. Depending on your setting this StoreState method either save a full texture snapshot, or saves a list of local paint commands. Therefore each undo/redo state can contain any number of actual paint depending on how you paint and when StoreState gets called. This doesn't store hit information though, so it wouldn't be of use to you.

    2 - If you use full texture states then deformation doesn't matter, but if it's local commands then your mesh deformation must be minimal relative to the size of the paint sphere/decals used. If it's significant then the paint will apply to the wrong area. You could maybe apply the same transformation to the paint command matrix, but this would only work if all vertices of the triangles painted by that command have the same linear transformation applied to them.

    3 - If you wish to intercept the hits and then re-broadcast them then yes. This is how the "72 Simulated Multiplayer" demo scene works.

    4 - It depends on the hit component's Emit setting (e.g. P3dHitScreen.Emit must be set to PointsOnUV to send coord info).
     
  36. villaman

    villaman

    Joined:
    Apr 21, 2021
    Posts:
    69
    Thanks for your response. I think I've got enough to get started. In summary I would implement this using the IHit*** and also implement my own undo/redo in terms of IHit***s.

    The only thing I'm a little confused by is comment #2. I guess, firstly, by definition, if a mesh is significantly deformed, one would not expect an exact replica of the painting.

    My thinking is that if one serializes UV positions instead of local positions, then one should get a good approximate painting. Would this be true? Imagine I started with a Plane Mesh and the IHit was at (U, V) = (0.5, 0.6). After some deformation (say, bending the plane mesh), I would now apply the IHit at (U, V) = (0.5, 0.6) which would have a completely different local position compared to the initial local position. However it would have the same relative position.

    So, if one did something like...

    Step 1: Serialize UV Position (IHit World Position -> Local Position -> UV Position)
    Step 2: Deform mesh
    Step 3: Deserialize UV Position (UV Position -> Local Position -> IHit World Position)

    Wouldn't one get an approximate replica of the painting?

    In the screenshots below, I
    a) Applied the red paint to the wing
    b) Deformed the wings by approximately 40 degrees
    c) Now the red paint still has its relative position on the wing.

    Wouldn't something similar happen with the Step 1->3 approach above even if one uses the "command" approach and not the full texture approach? I think in your example, you stop at the local position and don't further transform and serialize at the U,V position.

    Additionally, In my case I'm going to start with a relatively fine grained Plane Mesh (say 50x50) and then deform it. Maybe in this case the approximation will be close?

    thoughts?

    thanks

    UNDEFORMED MESH
    Undeformed Paint.png


    DEFORMED MESH
    Deformed Paint.png
     
  37. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    If you can write code to transform world <-> UV points then yes this will work as you describe. For a plane this transformation may not be too difficult, but for an arbitrary mesh I imagine it gets quite complex because a point may belong to any number of triangles until you iterate through them all (or find suitable candidates with some sort of tree) and perform some kind of distance check and barycentric coordinate conversion to get the UV.

    A simpler approach would be to use Emit = PointsOnUV so you can get the RaycastHit UV position and triangleIndex directly (assuming you're using a non-convex MeshCollider that provides this info). You could then do the much easier task of getting the world point from this data. In this scenario you would manually call the paint component using world positions, rather than letting the PointsOnUV data emit directly to the paint component (because I assume you don't want to paint in UV space).
     
  38. villaman

    villaman

    Joined:
    Apr 21, 2021
    Posts:
    69
    Yes, I think we are on the same page now. I was planning on iterating over the triangles and doing a "containment" check and barycentric coordinate conversion to get the UV. Because I know the shape of my mesh, I can avoid searching over all triangles.

    One thing I did was to take the Unity Cube and replace its box collider with a mesh collider. I am aware that it is not properly UV mapped and when I apply (say) a "duck" decal with the "Brush" set to "Points in 3D", I get 6 ducks. But I was just trying to test the same thing with the "Points on UV" setting. When I set it to "Points on UV" I get zero ducks (i.e. paint not applied anywhere). Any idea why this might be happening?

    I looked at your "21 UV" Scene example, where the painting takes place correctly. The problem seems to be related to UV mapping, but I could not figure out the essential difference.

    Similarly, with my own box mesh (which is UV mapped differently than both the Unity Box), when I use "Points in UV", I can paint on some sides but not others. With the PaintIn3D Separated Cube Mesh, when I use "Points in UV" the "duck" appears at a different position than the cursor. Any idea why this might be happening?

    Also, what's the advantage of "manually calling the paint component using world positions, rather than letting the PointsOnUV data emit directly to the paint component"?
     
  39. villaman

    villaman

    Joined:
    Apr 21, 2021
    Posts:
    69
    Additionally, currently the Paint component HandleHitCoord is automatically called. Would one have to move it to a different Game Object from the Game Object that contains P3D Hit Screen in order to suppress it being automatically called and then manually call it?

    Also going from UV to a world point seems easy. How would Handle Hit Line work?

    thanks
     
  40. villaman

    villaman

    Joined:
    Apr 21, 2021
    Posts:
    69
    ok, I got most of the above working by using the Point rather than UV approach and doing the whole mapping from world position to local position to mesh UV myself using triangle iteration and barycentric coordinates etc. It all seems to be working fine and I am able to "record" the painting before transform and deformation and "replay" the painting after transform and deformation.

    I have one issue and one question remaining.

    The issue I have is that PaintIn3D seems to change the mesh reference after every hit. Is this true? I can handle this in my own code by not caching the mesh reference and retrieving it on every HandleHit** call. However, other third-party assets (in this case I am using Megafiers for Mesh deformation) don't seem to be able to handle the mesh reference changing constantly. Is there a way to avoid the mesh reference changing constantly? I see the Mesh Filter go from "Instance" to "Instance Instance" etc..

    The question I have is what the Quaternion rotation is supposed to represent in HandleHit***. Is it the normal to the mesh at the position? I am transforming the worldRotation to localRotation and back. But I'm wondering if I have to do something similar in the deformation case, i.e. look at the rotation of the deformed mesh at the uv position.

    thanks
     
  41. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    It's probably the NormalFront/Back setting. This will skip painting a pixel if the hit normal is out of range of the paint normal, and since there are 6 overlapping triangles it's probably comparing the triangle you hit against some other triangle (e.g. the last one) and this always fails so it doesn't draw anything.

    Now that I think about it this wouldn't matter so forget I said it.

    A paint line in Paint in 3D is defined as two points, so it's the same process as converting a point, just twice.


    Which mesh reference? The MeshFilter's Mesh shouldn't be modified at any time.

    The rotation tells the paint which way to apply (e.g. decals), where Quaternion.identity means you want to paint down the +Z axis. This is the same as the camera rotation.
     
  42. DrViJ

    DrViJ

    Joined:
    Feb 9, 2013
    Posts:
    158
    @Darkcoder, I solved my problem on 2021.2 unity in webgl. The reason of my error was "Async" parameter on P3D Channel Counter. Looks like it worked in 2021.1 and stopped working in 2021.2/2022.1.0bX. maybe this information will be helpful for anybody in future :)
    Screenshot 2022-01-14 at 20.45.40.png
     
    Darkcoder likes this.
  43. villaman

    villaman

    Joined:
    Apr 21, 2021
    Posts:
    69
    I found the Mesh issue. In the IHitPoint component, I was calling MeshFilter.mesh which apparently makes a copy of the mesh. Calling MeshFilter.sharedMesh instead resolves this problem.

    Regarding rotation, I guess the language around the "Relative To" property is "Based on the Normal what should the rotation be rolled to". I found this a little unclear and what exactly is "rolling".

    If I pick Rotate To = "Normal", Direction="Hit Normal" and Relative To="World Up", what exactly does this mean?

    I'm trying to imagine this in the context of a Decal.

    The HitNormal and and WorldUp vectors will not in general be perpendicular to each other and so it can't be just that the DecalNormal and DecalY are aligned with HitNormal and WorldUp.

    The only thing I could come up with was that the HitNormal CROSS WorldUp would give us the DecalX vector. Then the DecalX CROSS HitNormal would give the DecalY vector. Then the decal is oriented to (DecalX, DecalY, HitNormal) and then projected to the mesh along the -HitNormal direction.

    Anyway, this is probably completely wrong :) So, maybe if you could explain this specific example in detail, that would be helpful :)

    thanks,
     
    Last edited: Jan 15, 2022
  44. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    Yeah that description could be better. I recommend you look at the code in P3dHitScreenBase.cs line 332+ (CalcHitData) to see exactly what's happening.
     
  45. villaman

    villaman

    Joined:
    Apr 21, 2021
    Posts:
    69
    From line 372 of P3DScreenBase.cs, it has
    finalRotation = Quaternion.LookRotation(-finalNormal, finalUp);

    and looking up the definition of LookRotation we get
    DecalZ = -finalNormal
    DecalX = -finalNormal CROSS finalUp
    DecalY
    = -finalNormal CROSS DecalX

    which in my example would be
    DecalZ = -HitNormal
    DecalX = -HitNormal CROSS WorldUp
    DecalY = -HitNormal CROSS DecalX

    which other than the signs is essentially the same as what I guessed.

    I presume after the decal is aligned along this transform that it is then projected to the mesh along -HitNormal? I couldn't find that code in P3DScreenBase.cs. I assume it happens much later when commands are being executed?

    Anyway, I've got things working including replaying paint commands even while the PaintableTexture is undergoing continuous deforming animation.

    thanks!
     
    Darkcoder likes this.
  46. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    Yes, when actually painting via shader the decal is projected/extruded through the mesh based on this final rotation. It works very similarly to Unity's built in Projector feature, or decals in URP/HDRP. These rotation settings basically the same as the parameters you would send to the Transform.LookAt or Quaternion.LookRotation methods if you're familiar with them.
     
  47. GreaterHawkeye

    GreaterHawkeye

    Joined:
    Apr 13, 2017
    Posts:
    34
    Hi @Darkcoder

    Thanks for the reply. We dont manage to do apply hardness on decals (using P3dPaintDecal). But we do manage to make the hardness work on P3DSphere.

    We're not sure how to use Texture/Shape or other settings to have the same result than the circle but for the square.
    Can you help out a bit please?

    Many thanks!

     
  48. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,404
    You need to manually create (e.g. in photoshop) different textures that are of squares with different hardness values. You can then set them in your decal's Texture or Shape setting.
     
  49. GreaterHawkeye

    GreaterHawkeye

    Joined:
    Apr 13, 2017
    Posts:
    34
    Thanks! Got you.

    Also, do you know any solution to avoid this behaviour:

    upload_2022-1-17_11-0-51.png

    I set the brush to have low opacity, thus we see each circle being rendered. That is because the decals are overlapping. Is there any functionnality to avoid that?

    Thanks!
     
    Last edited: Jan 17, 2022
  50. villaman

    villaman

    Joined:
    Apr 21, 2021
    Posts:
    69
    Hello,

    In HandleHitPoint is there any parameter that indicates whether a consecutive set of hitpoints are part of the same click-drag? This would be useful for implementing a custom undo feature (which I need to do) and avoiding every single hitpoint being an undo state?

    One way to do this would be to look at distance and/or times between hitpoints and use that to guess the beginning and end of logical "strokes". However, getting information on the set of hitpoints in the click-drag would be an important additional indicator.

    What's the best way to achieve this?
    thanks,