-
Posts
544 -
Joined
-
Last visited
Content Type
Blogs
Forums
Store
Gallery
Videos
Downloads
Everything posted by martyj
-
We do loose some performance no doubt as w use Entity objects rather than billboards. We also loose some range as well due to this as well. You're correct that we use the veg system for position and rotation. If someone wanted to, they could extend the radius around this using custom LOD models to provide more of a "billboard" affect. We do "replace" vegetation items around the player only, but you can't mix the two. With Leadwerks you cannot hide a specific vegetation object. You either hide everything or nothing. Benefits: 1. Allows animated models to be placed as easily as vegetation 2. Allows us to hide/show specific vegetation trees as players interact with them Cons: 1. Less distance with vegetation since we don't support billboards 2. Performance hit of trading 1 vegetation layer vs 50 Entity objects. World Factions uses this technique for 2 use cases. 1. Players can cut down any tree in the game. This allows us to place trees with the vegetation system, but provides user interactive content. The tree that the player cuts down is made of two Entities. A top half of tree, and a bottom trunk. When the player cuts the tree, we enable physics on the Tree and provide a random force on the top half to "cut it down" 2. Animals in the game. These are animated models with a small amount of AI added to them. We use the vegetation information for starting point. Players can kill specific animals so we need to hide them.
-
We're not loading the model for tree every vegetation model. We do a model->Instnace. Have a look at VegetatedModel class. It loads VEG_MODEL_ENTITY_COUNT number of models via model->Instance. For your second comment we do an AABB check around the player position like you have suggested. We find all entities in a "boxSize" around the player. AABB scope = AABB(playerPosit.x-boxSizeX, -1000, playerPosit.z-boxSizeZ, playerPosit.x+boxSizeX, 1000, playerPosit.z+boxSizeZ); For your last question, we hide everything on the Veg System and use real Instanced models instead. ==================== Edit: I see what you're saying. This code can be removed. AABB aabb = world->aabb; std::vector<Mat4> instances; layer->GetInstancesInAABB(aabb, instances); System::Print("Loading Layer: " + parentName + " of Size: " + std::to_string(instances.size())); for (unsigned int j = 0; j < instances.size(); j++) { Mat4 instance = instances[j]; Entity* copy = model->Instance(true, false); copy->SetMatrix(instance, true); copy->SetScale(scale); }
-
I had to do this for my game, it's possible, just not with the vegetation system exactly. You have to convert vegetation instances into real Entity objects. Due to performance reasons, you can't convert every vegetation object to an entity, so you have to be smart, and look at the closest objects to the player. I used a pool of about 50 objects and moved them to the closest trees around a player. I would sticky a vegetation entity to a specific tree as well, so if you started cutting one tree down, and you moved a little bit, you could go back to that tree and finish it off. Here is the C++ code. (Headers not included) VegetationToEntity -- Converts a vegetation layer into multiple VegetatedModel classes bool findStringIC(const std::string & strHaystack, const std::string & strNeedle) { auto it = std::search( strHaystack.begin(), strHaystack.end(), strNeedle.begin(), strNeedle.end(), [](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); } ); return (it != strHaystack.end() ); } void VegetationToEntity::LoadVegetationLayer(World* world) { App* app = App::GetApp(); if (app == nullptr) { return; } if (world->terrain == nullptr) { return; } std::map<std::string, bool> limitEntityMap = { { "Antelope", true }, { "Deer", true }, { "Lamb", true }, { "Sheep", true }, { "Wolf", true }, }; std::map<std::string, std::string> vegNameEntMap = { { "oak", "OakTree" }, { "maple", "MapleTree" }, { "birch", "BirchTree" }, { "green", "GreenheartTree" }, { "giantwood", "RedwoodTree" }, { "weep", "WillowTree" }, { "mud", "MudHole" }, { "antelope", "Antelope" }, { "fallowdeer", "Deer" }, { "lamb", "Lamb" }, { "sheep", "Sheep" }, { "wolf", "Wolf" }, }; int vegCount = world->terrain->CountVegetationLayers(); for (int i = 0; i < vegCount; i++) { VegetationLayer* layer = world->terrain->GetVegetationLayer(i); std::string modelPath = layer->modelpath; std::string parentName = ""; System::Print(modelPath); for (auto it = vegNameEntMap.begin(); it != vegNameEntMap.end(); it++) { System::Print(it->first); if(findStringIC(modelPath, it->first)) { parentName = it->second; break; } } if (parentName.empty()) { continue; } Entity* model = world->FindEntity(parentName); if (model == nullptr) { continue; } // Hide Layer layer->viewrange = 0; if (limitEntityMap[parentName]) { models.push_back(new VegetatedModel(layer, model, parentName)); continue; } Vec3 scale = model->GetScale(); AABB aabb = world->aabb; std::vector<Mat4> instances; layer->GetInstancesInAABB(aabb, instances); System::Print("Loading Layer: " + parentName + " of Size: " + std::to_string(instances.size())); for (unsigned int j = 0; j < instances.size(); j++) { Mat4 instance = instances[j]; Entity* copy = model->Instance(true, false); copy->SetMatrix(instance, true); copy->SetScale(scale); } } } // Called manually in App::Loop void VegetationToEntity::UpdateWorld() { for (auto it = models.begin(); it != models.end(); it++) { VegetatedModel* model = *it; model->UpdateWorld(); } } The next class is where the work comes in. VegetatedModel represents a single Vegetation Layer as N number of entities. This will auto-populate the entities around the players positions as the player moves. VegetatedModel::VegetatedModel(VegetationLayer* layer, Entity* model, std::string className) { this->layer = layer; this->cameraPosit = Vec3(0); for (int i = 0; i < VEG_MODEL_ENTITY_COUNT; i++) { Entity* copy = model->Instance(true, false); WFModel* model = Binder::InitCtor(copy, className); this->realEntities[i] = new VegetatedEntity(model, copy); } } void VegetatedModel::UpdateWorld() { Player* p = Player::GetPlayer(); if (p == NULL) { return; } Vec3 playerPosit = p->GetPosition(); if (this->cameraPosit.DistanceToPoint(playerPosit) < 4) { return; } this->cameraPosit = playerPosit; int boxSizeX = 30; int boxSizeZ = 30; AABB scope = AABB(playerPosit.x-boxSizeX, -1000, playerPosit.z-boxSizeZ, playerPosit.x+boxSizeX, 1000, playerPosit.z+boxSizeZ); World* world = World::GetCurrent(); std::vector<Vec3> possiblePoints(0); std::vector<Mat4> instances(0); this->layer->GetInstancesInAABB(world->aabb, instances); for (unsigned int j = 0; j < instances.size(); j++) { Mat4 mat = instances[j]; possiblePoints.push_back(mat.GetTranslation()); } std::sort(possiblePoints.begin(), possiblePoints.end(), VegetatedModel::PointSort); // First VEG_MODEL_ENTITY_COUNT as we want to show only the closest point if (possiblePoints.size() > VEG_MODEL_ENTITY_COUNT) { possiblePoints.erase(possiblePoints.begin() + VEG_MODEL_ENTITY_COUNT, possiblePoints.end()); } std::vector<VegetatedEntity*> entitiesNeedingPoints; std::vector<Vec3> pointsToRemove; int Count = Math::Min(possiblePoints.size(), VEG_MODEL_ENTITY_COUNT); for (int i = 0 ; i < Count; i++) { VegetatedEntity* vegEntity = this->realEntities[i]; Entity* ent = vegEntity->GetEntity(); bool found = false; for (int j = 0; j < Count; j++) { Vec3 posit = possiblePoints[j]; if (vegEntity->GetVegetationPosition() == posit) { found = true; pointsToRemove.push_back(posit); break; } } if (!found) { entitiesNeedingPoints.push_back(vegEntity); } } std::vector<Vec3> newPossiblePoints; for (int i = 0; i < possiblePoints.size(); i++) { Vec3 possiblePoint = possiblePoints[i]; bool found = false; for (auto it = pointsToRemove.begin(); it != pointsToRemove.end(); it++) { Vec3 pointRemove = *it; if (possiblePoint == pointRemove) { found = true; break; } } if (!found) { newPossiblePoints.push_back(possiblePoint); } } possiblePoints = newPossiblePoints; int numEntitiesToSet = Math::Min(possiblePoints.size(), entitiesNeedingPoints.size()); for (int i = 0; i < numEntitiesToSet; i++) { VegetatedEntity* vegEntity = entitiesNeedingPoints[i]; Entity* ent = vegEntity->GetEntity(); WFModel* model = vegEntity->GetWFModel(); Vec3 point = possiblePoints[i]; vegEntity->SetVegetationPosition(point); model->Reset(); } // Remove unused entities for (unsigned int i = numEntitiesToSet; i < entitiesNeedingPoints.size(); i++) { VegetatedEntity* vegEntity = entitiesNeedingPoints[i]; Entity* ent = vegEntity->GetEntity(); //vegEntity->SetVegetationPosition(Vec3(0, -123, 0)); //ent->Hide(); } } bool VegetatedModel::PointSort(Vec3 posit1, Vec3 posit2) { Player* p = Player::GetPlayer(); if (p == NULL) { return 0; } double d1 = p->GetPosition().DistanceToPoint(posit1); double d2 = p->GetPosition().DistanceToPoint(posit2); return d1 < d2; }
-
An game engine is exploitable. It's why valve has VAC software. IMO player movement is a fairly small exploit. Depending on the type of game you are making, there are exploits far more damaging. FPS - suffers from auto-aim bots MMORPG - Duplicate items, auto xp Player movement hacks are less likely as you have to find the memory address of the player positions in the application memory and then modify that memory externally. Auto-aim bots, and auto xp bots are more likely as you don't have to worry about cross application memory. On most modern operating systems application memory is stored in pages. These pages are protected by the operating system to make sure your program doesn't bump into another applications memory. A common way to get past this protection is to do DLL injection. Basically take a commonly used DLL by your game (libcurl for example), modify the library to function exactly how it normally does, plus add in hooks to let you control the game. TLDR: Yes
-
Try running it on an AMD card. Back when I was working on OpenGL I had a bug where a uniform was set to zero by default on Nvidia, yet it was randomized on AMD. If the terrain flashes random colors, you know that's your issue.
-
Wonderful blog post! When can we get a new "beta" for this? Vegetation is the only feature missing to complete everything I need for where I am going with my game. I will be hiring a full time content creator on Oct 1st, so this is exciting.
-
Texture::SetPixels doesn't work in Windows in Leadwerks 4.6
martyj replied to martyj's topic in Leadwerks Engine Bug Reports
Please close this topic. I found the issue. It was my mistake. In Windows, Context->GetWidth() is not the same as Window->GetWidth() This caused my texture to be rendered weird. As far as why this worked in Linux compared to Windows, who knows. -
Texture::SetPixels doesn't work in windows: Linux Screenshot: Windows Screenshot: Code: virtual void RenderBuffer(unsigned char* buffData, int width, int height) { this->texture->SetPixels((const char*)buffData, 0, 0, 0); } I can get Windows to work by manually setting each pixel, but it's hella slow performance. Here is a TGA of what I am trying to render in Linux. (Raw BGRA image format with first 36 bytes being a header) linux_render_21_36.tga TGA for Windows: render_windows2.tga
-
Three improvements I made to Leadwerks Game Engine 5 today
martyj commented on Josh's blog entry in Development Blog
I would like to see Terrain and Vegetation. I'd rather see these before lighting tbh. If I could get a "playable" version of World Factions, that doesn't require a $500 graphics card, it would allow me to hire content developers to develop content until LE5 can deliver the visuals. *Is planning on hiring a full-time content developer in 2 months* From a marketing standpoint, I could see how lighting would be preferred though. -
Very similar to how I did my cutscenes. It would be nice if Leadwerks supported this as well, but allowed the user-interface to add co-routines. For my cutscenes, I have things like Start Animation, Go to position, Go to rotation. You could even have a "Execute Lua Function". I like it!
-
So the one major issue I have at the moment is as follows: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease' For some reason it is passing /MDd to the compiler instead of /MT I will have a look at your CMake project tomorrow to see if I can resolve it based off that.
-
@reepblue That's the goal. To use a single CMake script for Linux and Windows. Right now I have to maintain a VS project for Windows, and a CMake for Linux. There are a lot of caveats to getting CMake for windows to work, such as setting /SUBSYTEM:CONSOLE having the correct MD/MT/MTd flags. Things that normally just work out of the box for visual studio.
-
@Josh How would Upwork work as my task requires the professional C++ license for Leadwerks? My concern for switching to Steamworks library is I already have CEF working well in my game. I'm just trying to not have to maintain a Visual Studio Project for Windows and CMake project for Linux. If I can get CMake to work on Windows I am set.
-
I'm looking for a C++ freelancer to "port" a library and example project into Windows. The library is a wrapper around Chromium Embedded Framework. The example project is just using the library in a Leadwerks sample. There probably isn't any C++ coding required, but more of CMake configurations. (CMake is a requirement. No Visual Studio projects.) PM me if you're interested, include your hourly rate, and a resume/work history.
-
From a Leadwerks Pro perspective. Linux is a hell of a lot easier to deal with. From a Leadwerks perspective, the Leadwerks UI on Linux is no where near the quality of that in Windows. It's this fact alone that's probably hurting Leadwerks Linux. If I need to make a map change. I dual boot into windows to make changes to the map. I have been on Leadwerks Linux for the last year I currently use kubuntu 18.04.
-
This will help tremendously!
-
So I have it rendering to a file/texture in a background thread. What I'd like to do now is to use wglShareLists to have textures synced between the Leadwerks Context and the SDL_Context to render a GL_TEXTURE_2D. What's the best way to create a Leadwerks::Texture from a GLuint? If I don't have to call glReadPixels to render a texture, it will probably help with performance. I assume if I set these values it will work to call context->DrawImage? int filtermode -> Pixel; int format -> RGBA8; int target -> Texture2D; bool hasmipmaps -> false; static float anisotropy -> What goes here? int bindindex -> output from glGenTextures; int width -> FBO Width; int height -> FBO height; int depth -> 0; bool clamp[3] -> What goes here? int currentmiplevel -> What goes here? int samples -> 0;
-
This post is for future reference. I don't have it working with a 2nd off screen context. I have two threads rendering two scenes to two windows. I think my next steps is to ditch SDL and use Frame Buffer Objects. https://www.khronos.org/opengl/wiki/Framebuffer_Object I'll update people on my progress. #include <Leadwerks.h> #include <SDL.h> using namespace Leadwerks; #include <GL/glut.h> GLfloat light_diffuse[] = { 1.0, 0.0, 0.0, 1.0 }; /* Red diffuse light. */ GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; /* Infinite light location. */ GLfloat n[6][3] = { /* Normals for the 6 faces of a cube. */ {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0} }; GLint faces[6][4] = { /* Vertex indices for the 6 faces of a cube. */ {0, 1, 2, 3}, {3, 2, 6, 7}, {7, 6, 5, 4}, {4, 5, 1, 0}, {5, 6, 2, 1}, {7, 4, 0, 3} }; GLfloat v[8][3]; /* Will be filled in with X,Y,Z vertexes. */ void drawBox(void) { int i; for (i = 0; i < 6; i++) { glBegin(GL_QUADS); glNormal3fv(&n[i][0]); glVertex3fv(&v[faces[i][0]][0]); glVertex3fv(&v[faces[i][1]][0]); glVertex3fv(&v[faces[i][2]][0]); glVertex3fv(&v[faces[i][3]][0]); glEnd(); } } void screendump(int W, int H) { FILE* out = fopen("screenshot.tga", "wb"); char* pixel_data = new char[3 * W*H]; short TGAhead[] = { 0, 2, 0, 0, 0, 0, W, H, 24 }; glReadBuffer(GL_RENDERBUFFER_EXT); glReadPixels(0, 0, W, H, GL_BGR, GL_UNSIGNED_BYTE, pixel_data); // TODO: Render to texture instead. Use texture with Context::drawImage fwrite(&TGAhead, sizeof(TGAhead), 1, out); fwrite(pixel_data, 3 * W*H, 1, out); fclose(out); delete[] pixel_data; } void init(void) { /* Setup cube vertex data. */ v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1; v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1; v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1; v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1; v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1; v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1; /* Enable a single OpenGL light. */ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); /* Use depth buffering for hidden surface elimination. */ glEnable(GL_DEPTH_TEST); /* Setup the view of the cube. */ glMatrixMode(GL_PROJECTION); gluPerspective( /* field of view in degree */ 40.0, /* aspect ratio */ 1.0, /* Z near */ 1.0, /* Z far */ 10.0); glMatrixMode(GL_MODELVIEW); gluLookAt(0.0, 0.0, 5.0, /* eye is at (0,0,5) */ 0.0, 0.0, 0.0, /* center is at (0,0,0) */ 0.0, 1.0, 0.); /* up is in positive Y direction */ /* Adjust cube position to be asthetic angle. */ glTranslatef(0.0, 0.0, -1.0); glRotatef(60, 1.0, 0.0, 0.0); glRotatef(-20, 0.0, 0.0, 1.0); } int webBrowserMain() { // Window mode MUST include SDL_WINDOW_OPENGL for use with OpenGL. SDL_Window *window = SDL_CreateWindow("Browser", 0, 0, 512, 512, SDL_WINDOW_OPENGL); // Create an OpenGL context associated with the window. SDL_GLContext glcontext = SDL_GL_CreateContext(window); init(); while (true) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawBox(); SDL_GL_SwapWindow(window); } SDL_GL_DeleteContext(glcontext); return 0; } DWORD WINAPI MyThreadFunction(LPVOID lpParam) { return webBrowserMain(); } #define GLUT int main(int argc, char *argv[]) { DWORD threadId = 0; CreateThread(NULL, 0, MyThreadFunction, nullptr, 0, &threadId); Window* window = Leadwerks::Window::Create(); Context* context = Context::Create(window); World* world = World::Create(); Light* light = DirectionalLight::Create(); light->SetRotation(35, 35, 0); //Create the ground Model* ground = Model::Box(10, 1, 10); ground->SetPosition(0, -0.5, 0); ground->SetColor(0.0, 1.0, 0.0); //Create a shape Shape* shape = Shape::Box(0, 0, 0, 0, 0, 0, 10, 1, 10); ground->SetShape(shape); shape->Release(); //Create a character Pivot* player = Pivot::Create(); Entity* visiblecapsule = Model::Cylinder(16, player); visiblecapsule->SetScale(1, 2, 1); visiblecapsule->SetPosition(0, 1, 0); player->SetMass(1); player->SetPhysicsMode(Entity::CharacterPhysics); Camera* camera = Camera::Create(); camera->SetPosition(Vec3(0, 1.5, 0), false); camera->SetParent(player); while (true) { if (window->Closed() || window->KeyDown(Key::Escape)) return false; Leadwerks::Time::Update(); float move = (window->KeyDown(Key::W) - window->KeyDown(Key::S)) * 4; float strafe = (window->KeyDown(Key::D) - window->KeyDown(Key::A)) * 4; player->SetInput(0, move, strafe); world->Update(); world->Render(); context->Sync(); } }
-
This is the approach I am taking. It doesn't work right now, but it should pass along the idea for #2. We would have two threads. Thread 1 would be the game in itself. Thread 2 would be the HTML render thread that uses OpenGL implementation for Ultralight UI Is this a good approach? const GLchar* vertexShader = R"EOF( #version 140 in vec3 in_Position; in vec3 in_Color; out vec3 ex_Color; void main(void) { gl_Position = vec4(in_Position, 1.0); ex_Color = in_Color; } )EOF"; const GLchar* fragShader = R"EOF( #version 140 precision highp float; // needed only for version 1.30 in vec3 ex_Color; out vec4 out_Color; void main(void) { out_Color = vec4(ex_Color,1.0); } )EOF"; unsigned int vertexArrayObjID[1]; unsigned int vertexBufferObjID[2]; void init(void) { /* set viewing projection */ glMatrixMode(GL_PROJECTION); glFrustum(-0.5F, 0.5F, -0.5F, 0.5F, 1.0F, 3.0F); /* position viewer */ glMatrixMode(GL_MODELVIEW); glTranslatef(0.0F, 0.0F, -2.0F); int vertSize = 9; int colorSize = 9; GLfloat vertData[]{ -0.3, 0.5, -1.0, -0.8, -0.5, -1.0, 0.2, -0.5, -1.0 }; GLfloat colorData[]{ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 }; // Allocate Vertex Array Objects glGenVertexArrays(1, &vertexArrayObjID[0]); // Setup first Vertex Array Object glBindVertexArray(vertexArrayObjID[0]); glGenBuffers(2, vertexBufferObjID); // VBO for vertex data glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[0]); glBufferData(GL_ARRAY_BUFFER, vertSize * sizeof(GLfloat), vertData, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); // VBO for colour data glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[1]); glBufferData(GL_ARRAY_BUFFER, colorSize * sizeof(GLfloat), colorData, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); glBindVertexArray(0); GLuint renderBuffer[1]; glGenRenderbuffersEXT(1, renderBuffer); glBindRenderbufferEXT(GL_FRAMEBUFFER_EXT, renderBuffer[0]); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, 512, 512); } void initShaders(void) { GLuint glProgram; GLuint vertShaderPtr = glCreateShader(GL_VERTEX_SHADER); GLuint fragShaderPtr = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(vertShaderPtr, 1, &vertexShader, 0); glShaderSource(fragShaderPtr, 1, &fragShader, 0); GLint compiled; glCompileShader(vertShaderPtr); glGetShaderiv(vertShaderPtr, GL_COMPILE_STATUS, &compiled); if (!compiled) { cout << "Vertex shader not compiled." << endl; } glCompileShader(fragShaderPtr); glGetShaderiv(fragShaderPtr, GL_COMPILE_STATUS, &compiled); if (!compiled) { cout << "Fragment shader not compiled." << endl; } glProgram = glCreateProgram(); glBindAttribLocation(glProgram, 0, "in_Position"); glBindAttribLocation(glProgram, 1, "in_Color"); glAttachShader(glProgram, vertShaderPtr); glAttachShader(glProgram, fragShaderPtr); glLinkProgram(glProgram); glUseProgram(glProgram); } void display(void) { // clear the screen glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(vertexArrayObjID[0]); // First VAO glDrawArrays(GL_TRIANGLES, 0, 3); // draw first object glBindVertexArray(0); } void screendump(int W, int H) { FILE* out = fopen("screenshot.tga", "wb"); char* pixel_data = new char[3 * W*H]; short TGAhead[] = { 0, 2, 0, 0, 0, 0, W, H, 24 }; glReadBuffer(GL_RENDERBUFFER_EXT); glReadPixels(0, 0, W, H, GL_BGR, GL_UNSIGNED_BYTE, pixel_data); // TODO: Render to texture instead. Use texture with Context::drawImage fwrite(&TGAhead, sizeof(TGAhead), 1, out); fwrite(pixel_data, 3 * W*H, 1, out); fclose(out); delete[] pixel_data; } static Window* window; DWORD WINAPI MyThreadFunction(LPVOID lpParam) { System::Print("THread2"); HDC hdc = CreateCompatibleDC(0); HGLRC glrc = wglCreateContext(hdc); wglMakeCurrent(window->hdc, glrc); init(); initShaders(); int w = 512; int h = 512; glViewport(0, 0, (GLsizei)w, (GLsizei)h); while (true) { display(); SwapBuffers(window->hdc); //screendump(w, h); } wglDeleteContext(glrc); } int main(int argc,const char *argv[]) { // Leadwerks Stuff // ... // Game Setup window = Leadwerks::Window::Create(); Context* context = Context::Create(window); World* world = World::Create(); Light* light = DirectionalLight::Create(); light->SetRotation(35, 35, 0); //Create the ground Model* ground = Model::Box(10, 1, 10); ground->SetPosition(0, -0.5, 0); ground->SetColor(0.0, 1.0, 0.0); //Create a shape Shape* shape = Shape::Box(0, 0, 0, 0, 0, 0, 10, 1, 10); ground->SetShape(shape); shape->Release(); //Create a character Pivot* player = Pivot::Create(); Entity* visiblecapsule = Model::Cylinder(16, player); visiblecapsule->SetScale(1, 2, 1); visiblecapsule->SetPosition(0, 1, 0); player->SetMass(1); player->SetPhysicsMode(Entity::CharacterPhysics); Camera* camera = Camera::Create(); camera->SetPosition(Vec3(0, 1.5, 0), false); camera->SetParent(player); DWORD threadId; HANDLE thread = CreateThread(NULL, 0, MyThreadFunction, nullptr, 0, &threadId); System::Print("THread1"); while (true) { if (window->Closed() || window->KeyDown(Key::Escape)) return false; Leadwerks::Time::Update(); float move = (window->KeyDown(Key::W) - window->KeyDown(Key::S)) * 4; float strafe = (window->KeyDown(Key::D) - window->KeyDown(Key::A)) * 4; player->SetInput(0, move, strafe); world->Update(); world->Render(); context->Sync(); }
-
I'm trying to implement Ultralight into Leadwerks and I"m struggling to find the best way to do it. I can see to "easy" options. 1. Create a GPUDriver instance for Ultralight which utilizes Leadwerks rendering. (Requires my own custom 2D shader) 2. Use the OpenGL implementation for Ultralight but use a separate thread for rendering the browser and writing the image data to a shared buffer #1 seems very difficult and error prone as I have to provide my own shader and support for this rendering. #2 seems easier but I don't know quite the best way to do this. Would something like this work for #2? DWORD WINAPI MyThreadFunction(LPVOID lpParam) { System::Print("THread2"); HDC hdc = CreateCompatibleDC(0); HGLRC glrc = wglCreateContext(hdc); wglMakeCurrent(window->hdc, glrc); unsigned char buff[512 * 512 * 3]; while (true) { drawUI(); dumpToBuffer(512, 512); } wglDeleteContext(glrc); } What would you guys recommend?
-
@Josh Did you mess up your xorg.config? Usually installing graphics drivers causes displays to get lost. If you press Ctrl + Alt + F4 this will give you a command line login without GPU. If you are still in Utah we can meet up some time so I can try to help you resolve it. Having an Ubuntu version of Leadwerks is important to me.
-
You'll spend more time loading assets than you ever would parsing a JSON file.
-
I love the idea of having JSON for scene data. This would allow for multiple people to make map changes using version control. For data like heightmap, you could even store it as a base64 encoded text. By storing as base64 text, it could also allow to users to modify different parts of the heightmap at the same time without issues
-
@reepblue You can compile with Visual Studio compiler using Makefiles. Have a look at CMake.
-
@klepto2 I keep getting an error while linking Leadwerks about adding -fPIE to the compiler. Adding this option doesn't fix the issue. I am using CMake for the project itself. How well does SWIG work with Leadwerks? Did you compile it off of the Leadwerks.h file, or each individual class such as Window, or Entity? Thanks