1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2014 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 // Authors: Alessandro Tasora
13 // =============================================================================
14 //
15 //   Demo code about
16 //     - collisions and contacts
17 //     - sharing a ChMaterialSurfaceNSC property between bodies
18 //
19 // =============================================================================
20 
21 #include "chrono/physics/ChSystemNSC.h"
22 #include "chrono/physics/ChBodyEasy.h"
23 #include "chrono/solver/ChSolverPSOR.h"
24 #include "chrono/assets/ChTexture.h"
25 
26 #include "chrono_irrlicht/ChIrrApp.h"
27 
28 // Use the namespaces of Chrono
29 using namespace chrono;
30 using namespace chrono::irrlicht;
31 
32 // Use the main namespaces of Irrlicht
33 using namespace irr;
34 using namespace irr::core;
35 using namespace irr::scene;
36 using namespace irr::video;
37 using namespace irr::io;
38 using namespace irr::gui;
39 
40 // Create a bunch of ChronoENGINE rigid bodies that
41 // represent bricks in a large wall.
42 
create_wall_bodies(ChSystemNSC & mphysicalSystem)43 void create_wall_bodies(ChSystemNSC& mphysicalSystem) {
44     // Create a material that will be shared among all collision shapes
45     auto mat = chrono_types::make_shared<ChMaterialSurfaceNSC>();
46     mat->SetFriction(0.4f);
47     mat->SetCompliance(0.0);
48     mat->SetComplianceT(0.0);
49     mat->SetDampingF(0.2f);
50 
51     // Create bricks
52     for (int ai = 0; ai < 1; ai++) {           // N. of walls
53         for (int bi = 0; bi < 10; bi++) {      // N. of vert. bricks
54             for (int ui = 0; ui < 15; ui++) {  // N. of hor. bricks
55 
56                 auto mrigidBody = chrono_types::make_shared<ChBodyEasyBox>(3.96, 2, 4,  // x,y,z size
57                                                                            100,         // density
58                                                                            true,        // visualization?
59                                                                            true,        // collision?
60                                                                            mat);        // contact material
61                 mrigidBody->SetPos(ChVector<>(-8 + ui * 4.0 + 2 * (bi % 2), 1.0 + bi * 2.0, ai * 9));
62 
63                 mphysicalSystem.Add(mrigidBody);
64 
65                 // optional, attach a texture for better visualization
66                 auto mtexture = chrono_types::make_shared<ChTexture>();
67                 mtexture->SetTextureFilename(GetChronoDataFile("textures/cubetexture_borders.png"));
68                 mrigidBody->AddAsset(mtexture);
69             }
70         }
71     }
72 
73     // Create the floor using
74     // fixed rigid body of 'box' type:
75 
76     auto mrigidFloor = chrono_types::make_shared<ChBodyEasyBox>(250, 4, 250,  // x,y,z size
77                                                                 1000,         // density
78                                                                 true,         // visulization?
79                                                                 true,         // collision?
80                                                                 mat);         // contact material
81     mrigidFloor->SetPos(ChVector<>(0, -2, 0));
82     mrigidFloor->SetBodyFixed(true);
83 
84     mphysicalSystem.Add(mrigidFloor);
85 
86     // Create a ball that will collide with wall
87     auto mrigidBall = chrono_types::make_shared<ChBodyEasySphere>(4,     // radius
88                                                                   8000,  // density
89                                                                   true,  // visualization?
90                                                                   true,  // collision?
91                                                                   mat);  // contact material
92     mrigidBall->SetPos(ChVector<>(0, -2, 0));
93     mrigidBall->SetPos(ChVector<>(0, 3, -8));
94     mrigidBall->SetPos_dt(ChVector<>(0, 0, 16));  // set initial speed
95 
96     mphysicalSystem.Add(mrigidBall);
97 
98     // optional, attach a texture for better visualization
99     auto mtextureball = chrono_types::make_shared<ChTexture>();
100     mtextureball->SetTextureFilename(GetChronoDataFile("textures/bluewhite.png"));
101     mrigidBall->AddAsset(mtextureball);
102 }
103 
104 // Create a bunch of ChronoENGINE rigid bodies that
105 // represent bricks in a Jenga tower
106 
create_jengatower_bodies(ChSystemNSC & mphysicalSystem)107 void create_jengatower_bodies(ChSystemNSC& mphysicalSystem) {
108     // Create a material that will be shared among all collision shapes
109     auto mat = chrono_types::make_shared<ChMaterialSurfaceNSC>();
110     mat->SetFriction(0.4f);
111     mat->SetCompliance(0.0);
112     mat->SetComplianceT(0.0);
113     mat->SetDampingF(0.2f);
114 
115     // Create bricks
116     for (int bi = 0; bi < 12; bi += 2) {
117         auto mrigidBody1 = chrono_types::make_shared<ChBodyEasyBox>(2, 2, 14,  // x,y,z size
118                                                                     100,       // density
119                                                                     true,      // visualization?
120                                                                     true,      // collision?
121                                                                     mat);      // contact material
122         mrigidBody1->SetPos(ChVector<>(-5, 1.0 + bi * 2.0, 0));
123         mphysicalSystem.Add(mrigidBody1);
124 
125         auto mrigidBody2 = chrono_types::make_shared<ChBodyEasyBox>(2, 2, 14,  // x,y,z size
126                                                                     100,       // density
127                                                                     true,      // visualization?
128                                                                     true,      // collision?
129                                                                     mat);      // contact material
130         mrigidBody2->SetPos(ChVector<>(5, 1.0 + bi * 2.0, 0));
131         mphysicalSystem.Add(mrigidBody2);
132 
133         auto mrigidBody3 = chrono_types::make_shared<ChBodyEasyBox>(14, 2, 2,  // x,y,z size
134                                                                     100,       // density
135                                                                     true,      // visualization?
136                                                                     true,      // collision?
137                                                                     mat);      // contact material
138         mrigidBody3->SetPos(ChVector<>(0, 3.0 + bi * 2.0, 5));
139         mphysicalSystem.Add(mrigidBody3);
140 
141         auto mrigidBody4 = chrono_types::make_shared<ChBodyEasyBox>(14, 2, 2,  // x,y,z size
142                                                                     100,       // density
143                                                                     true,      // visualization?
144                                                                     true,      // collision?
145                                                                     mat);      // contact material
146         mrigidBody4->SetPos(ChVector<>(0, 3.0 + bi * 2.0, -5));
147         mphysicalSystem.Add(mrigidBody4);
148     }
149 
150     // Create the floor using
151     // fixed rigid body of 'box' type:
152     auto mrigidFloor = chrono_types::make_shared<ChBodyEasyBox>(250, 4, 250,  // x,y,z size
153                                                                 1000,         // density
154                                                                 true,         // visualization?
155                                                                 true,         // collision?
156                                                                 mat);         // contact material
157     mrigidFloor->SetPos(ChVector<>(0, -2, 0));
158     mrigidFloor->SetBodyFixed(true);
159 
160     mphysicalSystem.Add(mrigidFloor);
161 
162     // Create a ball that will collide with tower
163     auto mrigidBall = chrono_types::make_shared<ChBodyEasySphere>(4,     // radius
164                                                                   1000,  // density
165                                                                   true,  // visualization?
166                                                                   true,  // collision?
167                                                                   mat);  // contact material
168     mrigidBall->SetPos(ChVector<>(0, 3, -8));
169     mrigidBall->SetPos_dt(ChVector<>(0, 0, 2));  // set initial speed
170 
171     mphysicalSystem.Add(mrigidBall);
172 
173     // optional, attach a texture for better visualization
174     auto mtextureball = chrono_types::make_shared<ChTexture>();
175     mtextureball->SetTextureFilename(GetChronoDataFile("textures/bluewhite.png"));
176     mrigidBall->AddAsset(mtextureball);
177 }
178 
main(int argc,char * argv[])179 int main(int argc, char* argv[]) {
180     GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
181 
182     // Create a ChronoENGINE physical system
183     ChSystemNSC mphysicalSystem;
184 
185     // Create the Irrlicht visualization (open the Irrlicht device,
186     // bind a simple user interface, etc. etc.)
187     ChIrrApp application(&mphysicalSystem, L"Bricks test", core::dimension2d<u32>(800, 600));
188     application.AddTypicalLogo();
189     application.AddTypicalSky();
190     application.AddTypicalLights(core::vector3df(70.f, 120.f, -90.f), core::vector3df(30.f, 80.f, 60.f), 290, 190);
191     application.AddTypicalCamera(core::vector3df(-15, 14, -30), core::vector3df(0, 5, 0));
192 
193     //
194     // HERE YOU POPULATE THE MECHANICAL SYSTEM OF CHRONO...
195     //
196 
197     // Create all the rigid bodies.
198     create_wall_bodies(mphysicalSystem);
199     // create_jengatower_bodies (mphysicalSystem);
200 
201     // Use this function for adding a ChIrrNodeAsset to all items
202     // If you need a finer control on which item really needs a visualization proxy in
203     // Irrlicht, just use application.AssetBind(myitem); on a per-item basis.
204     application.AssetBindAll();
205 
206     // Use this function for 'converting' into Irrlicht meshes the assets
207     // into Irrlicht-visualizable meshes
208     application.AssetUpdateAll();
209 
210     // Prepare the physical system for the simulation
211 
212     auto solver = chrono_types::make_shared<ChSolverPSOR>();
213     solver->SetMaxIterations(40);
214     solver->EnableWarmStart(true);
215     mphysicalSystem.SetSolver(solver);
216 
217     // mphysicalSystem.SetUseSleeping(true);
218     mphysicalSystem.SetMaxPenetrationRecoverySpeed(1.0);
219 
220     // Simulation loop
221 
222     application.SetTimestep(0.02);
223     application.SetTryRealtime(true);
224 
225     while (application.GetDevice()->run()) {
226         application.BeginScene(true, true, SColor(255, 140, 161, 192));
227 
228         tools::drawGrid(application.GetVideoDriver(), 5, 5, 20, 20,
229                              ChCoordsys<>(ChVector<>(0, 0.04, 0), Q_from_AngAxis(CH_C_PI / 2, VECT_X)),
230                              video::SColor(50, 90, 90, 150), true);
231 
232         application.DrawAll();
233 
234         application.DoStep();
235 
236         application.EndScene();
237     }
238 
239     return 0;
240 }
241