Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UPBGE: Implement physics mesh refit. #835

Open
wants to merge 423 commits into
base: master
Choose a base branch
from
Open

Conversation

panzergame
Copy link
Contributor

Bullet library is allowing for triangle mesh shapes (btBvhTriangleMeshShape
and btGImpactMeshShape) tree refit which is faster than rebuilding the whole
BVH tree.

To detect a possible refit we must check if only the vertices changed, to do so
we store information of the converted display arrays into struct MeshPart
during CcdShapeConstructionInfo::UpdateMesh.
Next call to CcdShapeConstructionInfo::UpdateMesh will compare the previous
mesh parts with the current one and if they are equivalent then only update the
vertices of the btTriangleIndexVertexArray. The vertices are always converted
from the display arrays and stored into m_vertexArray.

Finally CcdShapeConstructionInfo::UpdateMesh returns a flag to tell if physics
controllers need to recreate the shape (UPDATE_RECREATE) or update the shape
tree (UPDATE_REFIT). The last flag is making ReinstancePhysicsShape to call
CcdPhysicsEnvironment::RefitCcdPhysicsControllerShape which itself forward
to RefitCollisionShape of all the physics controllers using the same shape.
RefitCollisionShape is managing BVH shape and gimpact shape by calling
the proper functions for the both shape types.

Actually the tree is refit and not partially refit as it will request the user
to select a maximum AABB, the complete refit is a little bit more expensive
but much safer.
A new function in btGimpactMeshShape is added to refit the tree: refitTree.

Tested with 8192 triangles:
Static:
Before Current
12.32ms 1.89ms

Rigid:
Before Current
1.69ms 1.48ms

panzergame and others added 30 commits October 30, 2017 20:30
Some deformers as skin and shape deformer need an object to update
a blender mesh, but this object must own the blender mesh. To do
so we used previously a argument in some deformer constructor to
pass a blender object owning the blender mesh.
But in case the mesh is replaced the blender object of a game object
can't be used, in these case we looked at a blender object registered
along the blender mesh during the conversion.

With the recent merge of deformer creation into BL_DeformableGameObject::LoadDeformer
the look at blender object from mesh was always used. This worked fine
only when only one game object used a deformer for one blender mesh,
when two deformer used the same mesh the both conflicted and no update
appeared.
To solve this issue we first check if the blender object of the game
object own the blender mesh, else we do the look at.
Previously when a modifier deformer was detect the code checked if
a armature deformer or shape deformer was present to, in this case
the modifier deformer was created with an aramture object.

This cuased issues when the a shape deformer existed but without
any armature parent object. To avoid both checks, we only check if
the parent is an armature object.

Fix issue: #628.
When we subclass a proxy we previously incref the proxy to
make sure the game data keep the proxy alive, but in case
of proxy owning the game data, we should not incref to
make sure the proxy can be freed independtly of the game
data.
Previously multiple issue related to the render area were noticed.
They are the all due to a common issue: the width and height get
in RAS_Rect return the number of pixel between the corner (x1 - x2)
giving the maximum pixel index but not the real number of pixels
which is one pixel more.
This issue wasn't unknown as "+ 1" were spread in all the code for
the functions SetViewport and SetScissor of the rasterizer.

But the python function to get window size didn't used the + 1 and
gave wrong values to the user compared to filter off screen size
which were correct.

To avoid all futur issues the functions GetWidth and GetHeight in
RAS_Rect include the addition of 1 and the + 1 workaround is removed
is the rest of the code.

After testing with a custom shape cursor (a simple dot), it seems that linux
cursor doesn't use the corner of the cursor but the corner without the little
white margin contrary to windows which use the corner with the margin.
The mouse event code was introducing a offset for linux cursor, as this
offset is wrong in windows and the window dimensions are right, the mouse
offset is removed.

Fix issue: #560.
Previously the force computed in servo control logic brick was multiplied
by the mass. This behaviour is correct because bullet in
btRigidBody::integrateVelocities compute the linear velocity using force / mass.
But the angular velocity doesn't use this formula. For the angular
velocity we have to multiply the torque by the inertia of the body because
bullet compute angular velocity with: torque * inertia_tensor.
Previously the vertex were using a common base class named RAS_IVertex
which owned basic vertex data as position, normal, tangent. This base
class also defined function to mutate these value and virtual functions
for value in subclasses. The subclasses were RAS_Vertex, a template class,
which owned the uv and color data with size depending on the template
paramaters. This class also defined the virtual function to access uv or color.

This conception is correct as it allows using small vertex memory if the
user doesn't need a lot of uv or color layers. But the usage of virtual
function imposed the class to store a virtual ptr table, this table is
meanly a pointer (8o), this pointer was send to VBO and used memory for
nothing from OpenGL side.

To avoid this vptr, the vertex class is split in two classes: RAS_VertexData
and RAS_Vertex.
The first class is only vertex data without function. It use template
parameters for uvs and colors and is based upon RAS_VertexDataBasic for
the position, color, normal data.
The second class is containing the functions and used only to mutate the
vertex data. When accessing a vertex a RAS_Vertex instance is created with as
parameters the vertex data pointer and the vertex format. This vertex
format is used in uv and color getter to compute the return value based
on the vertex data pointer plus a gap corresponding to the looked layer.

As RAS_Vertex is now a new class, it functions names are cleaned using
CamelCase.
Previously the vertex was using float array converted to Moto
type and converted back to float array. To avoid these two
conversion stages the function RAS_IDisplayArray::CreateVertex now
accept float arrays.
The previous CreateVertex function is still keep for future mesh builder.
The activity culling helps to disable the physics or logic
of an object depending of its distance to the nearest camera.

From user side options were added in both UI and python API
to control this feature. In UI the activity culling is put
in three level, scene, camera, object. The two first level
are enabled as default and the last disabled. Also the object
panel expose option to enabled physics or logic culling with
a different radius.
In python the attribute activityCulling is added to these
three levels and KX_GameObject receive four attributes to
enabled physics and logic culling and controlling their
radius.

In internal sources the activity culling info are stored into
KX_GameObject::ActivityCullingInfo which is owned by in
KX_GameObject::m_activityCullingInfo.

To suspend logic we suspend from SCA_IObject calling Suspend
and Resume but in the same time we need to suspend animation
as they are independant of logic and that it will be hard
to control them when the object doesn't run its logic.
To do so BL_ActionManager implement a suspend flag which disallow
any task creation in KX_Scene::UpdateAnimations.

Thanks for youle's work on this.
The recursive argument of this function was always known at
compile time, it is converted to a template parameter.
Previously the camera were able to use custom viewport only
in python.
An UI is created to do the same based on entire viewport
ratios. The UI expose an option named "Custom Viewport"
and four ratio for left, right, bottom and top. These ratio
correspond with the width or height of the canvas multiplied
by the ratio.
These utilities instore a mechanism where multiple clients are
checking for modifications of a common server, but the client
are not looking at the server at the same time and the server
state is changing.
To ensure that all client know that the server is modified,
at each update the server iterate over all the clients registered
and set a modification state to true in each client if the
update flag from the server match a part of a filter from the
clients.

The client class is CM_UpdateClient, the server CM_UpdateServer,
these both class use a template paramter for the type studied
for update in the perspective to avoid messing clients and
servers of different types.
This doesn't change the behaviour of the servo control.
KX_CullingNode is not interesting as is goal was just to offer
a pointer to the game object using it and the SG_CullingNode
API.
This class can be replaced by KX_GameObject in KX_CullingHandler
which still get the culling node, but this time only SG_CullingNode.
The usage of undocumented python function _PyArg_ParseTupleAndKeywordsFast
(already used in blender) helps to improve performance spend during
function argument parsing. After some test this new function is 2/3 of
the runnign time of the previous parsing function.

But this function has a drawback: it request more code and variable to be
used especially a python parser pre created. To avoid to write this code
each time the template function EXP_ParseTupleArgsAndKeywords is used.
This function receive the args and kwds tuples, the format, the keywords
name and pointers converted values.
The sanitizer is enabled only for the game engine sources compilation,
it is enabled from cmake and the argument passed can also be customized.
…ject.

as BL_DeformableGameObject::m_activePriority was not used and as
m_lastframe was always set in SetActiveAction, this function is replaced
by SetlastFrame which just update m_lastframe attribute.
The skip transform value from deformer is used to know if during
render we have to apply the object matrix or not, only soft body
deformers are using it.
The goal of this commit is to access only time to this value while
creating a display array bucket, to do so we have first to ensure
that the construction of DAB is not in the constructor of deformers
because it will mean that any virtual call will be invalid as the
vptr is not yet complete. To avoid this a function called
InitDisplayArrays is implemented in RAS_Deformer and called in
BL_DeformableGameObject::LoadDeformer.
After these modification it is now possible to call SkipVertexTransform
in DAB constructor and affect its value to m_applyMatrix.
Previously in CcdPhysicsEnvironment::ConvertObject we iterate over all
the parents from the object tree to find the closer object possibly
used as a compound shape parent. But by doing this we affected the
search of just the root parent object to disable dynamic or just for
tracking (e.g for fh spring).
To found both the root parent and the root compound parent, two
variables are used in COnvertObject, compoundParent and parentRoot.
Also to clairfy, the function in physics controller named SetParentCtrl
is rename SetParentRoot as it was used to set the root parent controller
only, not the parent controller.

Fix issue: #634.
This commit fix the vertex reading from triangles in display array.
Currently in the conversion vertex data are always allocated,
checked for redundant then maybe copied and free.
To avoid frequently allocation a memory pool is used for
each display array type, this memory pool is a boost::object_pool.

Tested with sintel desert_level.blend file:
Before: 0.85s
After: 0.82s
Previously when we only get a float array and wanted to convert
it to python vector we were obligated to convert first to MT_Vector.
To avoid this extra conversion PyObjectFrom is also implemented
for float array of a template size.
This improvement is used mainly in KX_VertexProxy, but in consideration
the data passed to PyObjectFrom must be a array reference not a
pointer, to do so the getter in RAS_Vertex are modified.
The "Form Factor" UI value was not working anymore since a long time,
this was caused by the fact that UpdateCcdPhysicsController was
always called on conversion and that this function recalculated
the inertia tensor without the factor.

In this bug two parts are fixed, first the factor is applied
properly everytime setMassProps is called.
Secondly the call to UpdateCcdPhysicsController is avoided during
conversion. This call was proceeded because the functions
SetUserCollision[Group/mask] are calling RefreshCollisions. To avoid
these calls the collision group and mask are moved fully to
physics part, now KX_GameObject is reading and setting these bitmask
from the PHY_IPhysicsController API. The group and mask is initialized
along physics controller in ConvertObject function.
lordloki and others added 24 commits August 26, 2018 23:05
UPBGE version infos access from bpy (can be useful for addons)

Feature request from Momel on discord
48000Hz is the newer standard used in professional audio recording as it
"works" better with multiple frame rates.

Additionally, it solves the frequent "Error AL lib: UpdateDeviceParams:
Failed to set 44100hz, got 48000hz instead" raised in a lot realtek,
intel, nvidia integrated sound cards (some of them even with crash).

And it seems to works better with HRTF binaural sound (in me own TODO
list)

TODO: To make this value configurable by user
Previously the function getScreenRay was adapted to only perspective
cameras because the ray cast was always starting from the center of
the camera.
In case of orthographic the ray cast should start from a point unprojected
from the near plane and continue to in the direction of the camera
(-Z orientation axis).
This is proceeded in getScreenRay and the indirect call to getScreenVect
is removed.

Fix issue #765.
I added an image in the readme, made some adjustments and added a release notes link.
Previously objects were considered as occluder if the occluder option
was checked and that the object was visible. The last constraint is
bothering for the user that could define a simplified mesh for occlusion
that naturally will not be visible.

This commit is introducing the condition "visible || occluder" for the
call activating the graphic controller in KX_GameObject::SetVisible/
SetOccluder and the initialization of the graphic controller.

Fix issue #807.
Previously the components name was exposed by a property non-editable which
was rendered in light gray and the component box was always expanded.
Also the module name was inaccesible from bpy.

The last issue is simply solved by exposing the "module" string to RNA.
The name property is replaced by a label in the UI. To expanse the box
the property "show_expanded" similar to the logic brick is implemented,
when this property is True, an inner box is generated containing all the
properties.

Fix issue #793.
Some unused options/entities are removed from the UI in game engine mode:
- scene keying set
- speaker and force field in add menu

The game engine is renamed UPBGE and the audio panel under scene tab is siplified
to expose only the speed of sound, doppler factor and the distance model, these
attributes are used by LA_Launcher to initialize the AUD_Device.

Fix issue #756.
code picked from BF sources
The function KX_Mesh.constructBvh can now use as first argument
a transform 4x4 matrix used over all the vertices. This allow
the user to create a BVH in world space by passing the object
world transform.

Fix issue #786.
When the user pref config isn't saved, blender load one from memory and
call the function BLO_update_defaults_userpref_blend to initialize properly
the preferences such as the auto exec script option defaulted to true.

Unfortunatly this function is called after the check of the option
and so for blender auto exec is always false until the user saves the
preferences and reload.

Also the cmake option WITH_PYTHON_SECURITY is defaulted to OFF to avoid
new users compiling the software been blocked by this it.
Since ever UPBGE was starting a startup file from blender that was adapted only
to blender with the selection of "Blender Render" and the shading to solid (non-GLSL).

As UPBGE is designed for game, the new startup include:
- select the proper render engine to "Blender Game"
- logic editor is exposed with component tab expanded
- default component in Cube
- physics static for Plane and Cube
- shadow PCF from sun light
- back lighting with 2 hemi
- environment lighting
- blue color on Cube
- MSAA 4x
- script editor exposed at bottom
- world background
- framerate and profiler

The theme is also changed to a flat dark theme proposed by @Momel15.
This theme is named "upbge" and select by default in the startup.

Fix issue: #742.
Previously the color management was always of sRGB and the user had no control
over it. To fill this gap the user should have the ability to define the final
color space, linear or sRGB.

First of all an option named "Color Management" in a new tab under Render panel
is added, it can be "Linear" or "sRGB", the default is "sRGB", When game engine
is selected changing this option will force the recompilation of all shaders and
they will add or remove color space conversion at the end of the shader.

In game the color space is not managed at the shader level, but at the final
copy of the offscreen to the screen. Firstly the material in game must disable
the color management, this is done by a new set of flags passed to
GPU_material_from_blender or GPU_material_world and the flag
GPU_MATERIAL_NO_COLOR_MANAGEMENT.
Secondly the three shaders used to copy the offscreen to screen (normal, stipple
stereo, anaglyph stereo) now have a sRGB version including a call to
linearrgb_to_srgb enabled by the macro COLOR_MANAGEMENT.
The color space used is stored in the rasterizer in enum variable
m_colorManagement for linear and sRGB, this variable is used to select the
correct shader to bind before flushing to screen.

Because the linear to sRGB conversion is not anymore using a float value with
the highest precision at the output of the fragment shader, the texture
format GL_RGBA8 is introducing bands because of its poor resolution. Replacing
it by GL_RGBA12 prevents the bands.

In the same time the color management used in KX_FontObject or KX_WorldInfo is
now obsolete and removed, also KX_WorldInfo is getting GPUMaterial only in new
function ReloadMaterial called by the FinalizeSceneData such as material shaders
and by setMaterialGLSL.
The commit f62dca6 introduced a remove of the replaced
scene in the scene list, this call is unnecessary as
EXP_ListValue::SetValue is swapping the values.
The drawback of RemoveValue was to reduce the size of the
container by actually erasing the item.

This is fixed by not removing the scene but only replacing
its pointer.

Fix issue: #819.
Rename async parameter from LibLoad as is a reserved word in Python 3.7

A note will be included in Release notes as this breaks compatibility with old scripts.
The option in user prefs enabling cycles UI wasn't checked in startup.

Fix issue: #823.
The noodle curving is set to 5 (like default themes) and regular inner widget color
is set to a darker color to avoid invisible box in layer popup.

Fix issue: #823.
The function rna_GameObjectSettings_used_state_get and rna_GameObjectSettings_state_get
were previously using an array of ints, a blender commit changed it to an array
of bools but forgotten to change the initialization of the arrays on these two
functions. The initialization is using memset and using the previous size for
int is creating a overflow smashing the program stack.

This issue is fixed by using sizeof(bool).
Previously the layer send to the shader is non-zero and so checked with object
layer when:
The lamp is visible OR the lamp is in view layers.

But the correct behaviour is:
The lamp is visible AND the lamp is in view layers.

So that all lamps in layers not selected by view will not affect any objects
even one sharing a layer with the lamp.

To restore this behaviour the dynlayer is set to 0 also when
lamp->lay & viewlay is 0.

Fix issue: #831.
Previously when the frame time was too fast the function KX_KetsjiEngine::NextFrame
concluded that 0 frames have to be proceeded and done nothing. This function was
called until the elapsed time was suffisent to process a frame.

This approch is naive, robust and precise but introduce an high CPU usage because
of the extra calls to KX_KetsjiEngine::NextFrame setting the CPU to it's maximum.

To avoid this high usage, the elapsed time to the next frame is computed and the
main thread sleep of this time.
Bullet library is allowing for triangle mesh shapes (btBvhTriangleMeshShape
and btGImpactMeshShape) tree refit which is faster than rebuilding the whole
BVH tree.

To detect a possible refit we must check if only the vertices changed, to do so
we store information of the converted display arrays into struct MeshPart
during CcdShapeConstructionInfo::UpdateMesh.
Next call to CcdShapeConstructionInfo::UpdateMesh will compare the previous
mesh parts with the current one and if they are equivalent then only update the
vertices of the btTriangleIndexVertexArray. The vertices are always converted
from the display arrays and stored into m_vertexArray.

Finally CcdShapeConstructionInfo::UpdateMesh returns a flag to tell if physics
controllers need to recreate the shape (UPDATE_RECREATE) or update the shape
tree (UPDATE_REFIT). The last flag is making ReinstancePhysicsShape to call
CcdPhysicsEnvironment::RefitCcdPhysicsControllerShape which itself forward
to RefitCollisionShape of all the physics controllers using the same shape.
RefitCollisionShape is managing BVH shape and gimpact shape by calling
the proper functions for the both shape types.

Actually the tree is refit and not partially refit as it will request the user
to select a maximum AABB, the complete refit is a little bit more expensive
but much safer.
A new function in btGimpactMeshShape is added to refit the tree: refitTree.

Tested with 8192 triangles:
Static:
Before	Current
12.32ms	1.89ms

Rigid:
Before	Current
1.69ms	1.48ms
@lordloki
Copy link
Member

Could you upload a test file?

@panzergame
Copy link
Contributor Author

ge_update_physics.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet