[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / internal / bullet-impl / bullet-physics-debug-renderer.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // Class header
18 #include <dali-physics/internal/bullet-impl/bullet-physics-debug-renderer.h>
19
20 // External Includes
21 #include <dali/dali.h>
22
23 // Internal Includes
24 #include <dali-physics/internal/physics-adaptor-impl.h>
25
26 using Dali::Degree;
27 using Dali::Matrix;
28 using Dali::Quaternion;
29 using Dali::Radian;
30 using Dali::Vector3;
31 using Dali::Vector4;
32
33 namespace
34 {
35 GLuint LoadShader(GLenum shaderType, const char* shaderSource)
36 {
37   GLuint shader = glCreateShader(shaderType);
38   if(shader != 0)
39   {
40     glShaderSource(shader, 1, &shaderSource, NULL);
41     glCompileShader(shader);
42     GLint compiled = 0;
43     glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
44     if(compiled != GL_TRUE)
45     {
46       GLint infoLen = 0;
47       glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
48
49       if(infoLen > 0)
50       {
51         std::vector<char> logBuffer;
52         logBuffer.resize(infoLen + 1);
53         glGetShaderInfoLog(shader, infoLen, NULL, &logBuffer[0]);
54         fprintf(stderr, "%s\n", &logBuffer[0]);
55         fflush(stderr);
56
57         glDeleteShader(shader);
58         shader = 0;
59       }
60     }
61   }
62   return shader;
63 }
64
65 GLuint CreateProgram(const char* vertexSource, const char* fragmentSource)
66 {
67   GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vertexSource);
68   if(!vertexShader)
69   {
70     return 0;
71   }
72   GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fragmentSource);
73   if(!fragmentShader)
74   {
75     return 0;
76   }
77   GLuint program = glCreateProgram();
78   if(program)
79   {
80     glAttachShader(program, vertexShader);
81     glAttachShader(program, fragmentShader);
82     glLinkProgram(program);
83     GLint linkStatus = GL_FALSE;
84     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
85     if(linkStatus != GL_TRUE)
86     {
87       GLint bufLength = 0;
88       glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
89       if(bufLength)
90       {
91         std::vector<char> logBuffer;
92         logBuffer.resize(bufLength + 1);
93         glGetProgramInfoLog(program, bufLength, NULL, &logBuffer[0]);
94         fprintf(stderr, "%s\n", &logBuffer[0]);
95         fflush(stderr);
96       }
97       glDeleteProgram(program);
98       program = 0;
99     }
100   }
101   return program;
102 }
103 } // namespace
104
105 namespace Dali::Toolkit::Physics::Internal
106 {
107 std::unique_ptr<PhysicsDebugRenderer> PhysicsDebugRenderer::New(uint32_t width, uint32_t height, Dali::CameraActor camera, PhysicsAdaptor* adaptor)
108 {
109   auto renderer             = std::make_unique<PhysicsDebugRenderer>(width, height, camera, adaptor);
110   renderer->mRenderCallback = Dali::RenderCallback::New<PhysicsDebugRenderer>(renderer.get(), &PhysicsDebugRenderer::OnRender);
111   return renderer;
112 }
113
114 PhysicsDebugRenderer::PhysicsDebugRenderer(uint32_t width, uint32_t height, Dali::CameraActor camera, PhysicsAdaptor* adaptor)
115 : mCamera(camera),
116   mWidth(width),
117   mHeight(height),
118   mAdaptor(*adaptor),
119   mVertexLocation(-1),
120   mVertexColourLocation(-1),
121   mProjectionLocation(-1),
122   mModelViewLocation(-1),
123   mBufferId(0u),
124   mProgramId(0u)
125 {
126 }
127
128 bool PhysicsDebugRenderer::OnRender(const Dali::RenderCallbackInput& input)
129 {
130   if(mState == State::INIT)
131   {
132     Setup();
133     mState = State::RENDER;
134   }
135   glViewport(0, 0, mWidth, mHeight);
136
137   RenderLines(input);
138
139   return false;
140 }
141
142 // Run on first invocation of callback
143 void PhysicsDebugRenderer::Setup()
144 {
145   PrepareShader();
146   mVertexLocation       = glGetAttribLocation(mProgramId, "vertexPosition");
147   mVertexColourLocation = glGetAttribLocation(mProgramId, "vertexColour");
148   mProjectionLocation   = glGetUniformLocation(mProgramId, "projection");
149   mModelViewLocation    = glGetUniformLocation(mProgramId, "modelView");
150
151   glEnable(GL_DEPTH_TEST);
152   glViewport(0, 0, mWidth, mHeight);
153
154   glGenBuffers(1, &mBufferId);
155 }
156
157 void PhysicsDebugRenderer::UpdateWindowSize(Dali::Vector2 size)
158 {
159   mWidth  = size.width;
160   mHeight = size.height;
161 }
162
163 void PhysicsDebugRenderer::PrepareShader()
164 {
165   static const char glVertexShader[] =
166     "attribute vec4 vertexPosition;\n"
167     "attribute vec3 vertexColour;\n"
168     "varying vec3 fragColour;\n"
169     "uniform mat4 projection;\n"
170     "uniform mat4 modelView;\n"
171     "void main()\n"
172     "{\n"
173     "    gl_Position = projection * modelView * vertexPosition;\n"
174     "    fragColour = vertexColour;\n"
175     "}\n";
176
177   static const char glFragmentShader[] =
178     "precision mediump float;\n"
179     "varying vec3 fragColour;\n"
180     "void main()\n"
181     "{\n"
182     "    gl_FragColor = vec4(fragColour, 1.0);\n"
183     "}\n";
184
185   mProgramId = CreateProgram(glVertexShader, glFragmentShader);
186 }
187
188 void PhysicsDebugRenderer::RenderLines(const Dali::RenderCallbackInput& input)
189 {
190   mModelViewMatrix.SetIdentity();
191   mProjectionMatrix = input.projection;
192
193   Matrix::Multiply(mModelViewMatrix, mModelViewMatrix, input.view);
194   glUseProgram(mProgramId);
195
196   // In theory, input.clippingBox should tell us the actor position in clip-space.
197   // But, it appears to be bugged.
198
199   glBindBuffer(GL_ARRAY_BUFFER, mBufferId);
200   glBufferData(GL_ARRAY_BUFFER, GLsizeiptr(mLines.size() * sizeof(VertexLine)), &mLines[0], GL_STATIC_DRAW);
201
202   glVertexAttribPointer(mVertexLocation, 3, GL_FLOAT, GL_FALSE, 24, 0);
203   glEnableVertexAttribArray(mVertexLocation);
204   glVertexAttribPointer(mVertexColourLocation, 3, GL_FLOAT, GL_FALSE, 24, reinterpret_cast<const void*>(12));
205   glEnableVertexAttribArray(mVertexColourLocation);
206   glUniformMatrix4fv(mProjectionLocation, 1, GL_FALSE, mProjectionMatrix.AsFloat());
207   glUniformMatrix4fv(mModelViewLocation, 1, GL_FALSE, mModelViewMatrix.AsFloat());
208
209   glDrawArrays(GL_LINES, 0, mLines.size());
210   mLines.clear();
211 }
212
213 void PhysicsDebugRenderer::drawLine(const btVector3& from, const btVector3& to, const btVector3& color)
214 {
215   mLines.push_back(VertexLine{mAdaptor.TranslateFromPhysicsSpace(Vector3(from.x(), from.y(), from.z())),
216                               Vector3(color.x(), color.y(), color.z())});
217   mLines.push_back(VertexLine{mAdaptor.TranslateFromPhysicsSpace(Vector3(to.x(), to.y(), to.z())), Vector3(color.x(), color.y(), color.z())});
218 }
219
220 void PhysicsDebugRenderer::drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
221 {
222   mLines.push_back(VertexLine{mAdaptor.TranslateFromPhysicsSpace(Vector3(from.x(), from.y(), from.z())), Vector3(fromColor.x(), fromColor.y(), fromColor.z())});
223   mLines.push_back(VertexLine{mAdaptor.TranslateFromPhysicsSpace(Vector3(to.x(), to.y(), to.z())), Vector3(toColor.x(), toColor.y(), toColor.z())});
224 }
225
226 void PhysicsDebugRenderer::drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color)
227 {
228 }
229
230 void PhysicsDebugRenderer::reportErrorWarning(const char* warningString)
231 {
232 }
233
234 void PhysicsDebugRenderer::draw3dText(const btVector3& location, const char* textString)
235 {
236 }
237
238 void PhysicsDebugRenderer::setDebugMode(int debugMode)
239 {
240 }
241
242 int PhysicsDebugRenderer::getDebugMode() const
243 {
244   return true;
245 }
246
247 } // namespace Dali::Toolkit::Physics::Internal