Jump to content

Josh

Staff
  • Posts

    23,402
  • Joined

  • Last visited

Community Answers

  1. Josh's post in Renewal cycle was marked as the answer   
    You can renew before the expiration date and it will add that time to your existing days left. In other words, there is no penalty for renewing early or for pre-paying for a block of time. If you have a payment method stored (credit card or account credit) then that will be billed automatically at your selected renewal rate. You can also disable automatic renewals at any time and it won't effect your current time left.
  2. Josh's post in Bounds not calculating was marked as the answer   
    Without looking at it, I am guessing box2 has a node at the top of the hierarchy with no geometry, so it's just a point. You can get the recursive bounds and that will include all the children.
  3. Josh's post in Classic Shading was marked as the answer   
    I would try to use the PBR approach because it looks good. Your environment maps or probes are very important for this.
  4. Josh's post in World::Pick() Callback from a variable? was marked as the answer   
    I think this is weird design. You could call a class method from within the callback. If the same class might use different types of callbacks, then you would probably just create a class for your pick handling:
    class PickFilter { public: virtual bool Filter(shared_ptr<Entity> e) { return true; } }; class ColliderPickFilter : public PickFilter { public: virtual bool Filter(shared_ptr<Entity> e) { return e->collider != NULL; } }; bool Callback(shared_ptr<Entity> e, shared_ptr<Object> extra) { auto filter = extra->As<PickFilter>(); if (filter) return filter->Filter(e); else return true; }  
  5. Josh's post in Timing things in Ultra was marked as the answer   
    You can, but since the update step is fixed, unlike Leadwerks, you can rely on each iteration occurring in intervals of 16.667 milliseconds.
  6. Josh's post in 2D Depth was marked as the answer   
    WIdget::SetParent has an optional position parameter for this purpose:
    https://www.ultraengine.com/learn/Widget_SetParent?lang=cpp
    "Position" here means position in the child list, not the sprite depth value.
  7. Josh's post in Object Rotation was marked as the answer   
    Yes, you answered your own question.
    Euler angles are easy for humans to understand, but they cannot accurately describe all rotations. When the pitch approaches 90 degrees, there is no way to describe the roll accurately, because at that angle the pitch and roll are the same. This is called Gimbal lock:

    This has even caused problems in space missions. I can't find the exact clip, but they talk about this in the movie "Apollo 13".
    Quaternions are an exact description, but you need a degree in mathematics to understand them. In fact there is an entire book I hope to some day read named simply "Visualizing Quaternions":
    https://www.elsevier.com/books/visualizing-quaternions/hanson/978-0-12-088400-1
    Each entity stores its rotation in both Euler and quaternion form, and these are kept in sync whenever rotation changes. The Turn method uses quaternions to accurately turn the entity, and then fills in the entity's Euler rotation value by converting it from the resulting quaternion.
    So everything is correct.
  8. Josh's post in Newton Crash was marked as the answer   
    I can't say what the problem was but I clean and rebuild of the engine fixed it. The update is available now on 1.0.1.
    BTW, it seems a lot of your colliders consist of 1-2 triangles. This is probably very inefficient and it would be better if they were in bigger pieces, but that should still not cause a crash like you were experiencing.
  9. Josh's post in Screenshot Notifications was marked as the answer   
    I've reported this to Invision Power Services.
  10. Josh's post in Orthogonal camera skipping frames was marked as the answer   
    Here you go.

    I had problems using a wireframe rect. I suspect the scaling breaks the pixel-perfect alignment. I will look into that now, but this gives you enough to work with:
    #include "UltraEngine.h" using namespace UltraEngine; #define MB_LEFT 1 int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create window auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0]); //Create framebuffer auto framebuffer = CreateFramebuffer(window); //Create world auto world = CreateWorld(); //Create a 3d camera auto camera = CreateCamera(world); camera->SetFov(70); camera->SetPosition(0, 50, 0); camera->SetRotation(45, 0, 0); camera->SetClearColor(0.125); //Sunlight auto light = CreateDirectionalLight(world); light->SetRotation(45, 35, 0); light->SetColor(2); //Create terrain auto terrain = CreateTerrain(world, 512); terrain->LoadHeightmap("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Terrain/512.r16"); terrain->SetScale(1, 100, 1); //Create base material auto ground = CreateMaterial(); auto diffusemap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/river_small_rocks_diff_4k.dds"); auto normalmap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/river_small_rocks_nor_gl_4k.dds"); ground->SetTexture(diffusemap, TEXTURE_DIFFUSE); ground->SetTexture(normalmap, TEXTURE_NORMAL); terrain->SetMaterial(ground); //Create paint material auto rocks = CreateMaterial(); diffusemap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/Rocks_Dirt_Ground_2k.dds"); normalmap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/Rocks_Dirt_Ground_2k_dot3.dds"); auto dispmap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/Rocks_Dirt_Ground_2k_disp.dds"); rocks->SetTexture(diffusemap, TEXTURE_DIFFUSE); rocks->SetTexture(normalmap, TEXTURE_NORMAL); rocks->SetTexture(dispmap, TEXTURE_DISPLACEMENT); //Apply material based on terrain slope for (int x = 0; x < terrain->resolution.x; ++x) { for (int y = 0; y < terrain->resolution.y; ++y) { float slope = terrain->GetSlope(x, y); if (slope > 15.0f) { float wt = Min((slope - 15.0f) / 10.0f, 1.0f); terrain->SetMaterial(x, y, rocks, wt); } } } //Load a font auto font = LoadFont("Fonts/arial.ttf"); //Create user interface auto ui = CreateInterface(world, font, framebuffer->size); ui->background->SetColor(0, 0, 0, 0); ui->SetRenderLayers(2); auto testpanel = CreatePanel(20, 20, 200, 200, ui->background); //Create camera auto uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition(float(framebuffer->size.x) * 0.5f, float(framebuffer->size.y) * 0.5f, 0); uiCamera->SetClearMode(ClearMode::CLEAR_DEPTH); uiCamera->SetRenderLayers(2); uiCamera->SetDepthPrepass(false); //auto rect = CreatePanel(0, 0, 0, 0, ui->root, PANEL_BORDER); //rect->SetColor(Vec4(0, 0.f, 0.f, 0.f), WIDGETCOLOR_BACKGROUND); //rect->SetColor(Vec4(255, 255, 255.f, 255.f), WIDGETCOLOR_BORDER); auto mouseDown = false; iVec2 clickPos; auto rect = CreateSprite(world, 1, 1, false); rect->SetRenderLayers(2); auto mtl = CreateMaterial(); mtl->SetColor(0, 1, 1, 0.25); mtl->SetTransparent(true); mtl->SetShaderFamily(LoadShaderFamily("Shaders/Unlit.json")); rect->SetMaterial(mtl); while (true) { while (PeekEvent()) { const Event ev = WaitEvent(); switch (ev.id) { case EVENT_WINDOWCLOSE: { if (ev.source == window) { return 0; } break; } case EVENT_MOUSEDOWN: { const auto button = ev.data; if (!mouseDown && button == MB_LEFT) { mouseDown = true; clickPos = { window->GetMousePosition().x, window->GetMousePosition().y }; } break; } case EVENT_MOUSEUP: { const auto button = ev.data; if (button == MB_LEFT) { rect->SetScale(0); //rect->SetShape(0, 0, 0, 0); mouseDown = false; } break; } default: { ui->ProcessEvent(ev); break; } } } if (mouseDown) { auto mousePosition = window->GetMousePosition(); float h = Abs(clickPos.y - mousePosition.y) + 1; rect->SetPosition(Min(mousePosition.x, clickPos.x), framebuffer->size.y - Min(mousePosition.y, clickPos.y) - h); rect->SetScale(Abs(clickPos.x - mousePosition.x) + 1, h, 1); //rect->SetShape(Min(mousePosition.x, clickPos.x), // Min(mousePosition.y, clickPos.y), // Abs(clickPos.x - mousePosition.x) + 1, // Abs(clickPos.y - mousePosition.y) + 1); } world->Update(); world->Render(framebuffer); } return 0; }  
  11. Josh's post in Using World::Pick to get distance was marked as the answer   
    The distance member is used internally by the engine and results in a value from 0 to 1 if the ray test hits anything. You should check if the pickinfo.success  member is true or false. It sounds like the ray is not currently intersecting anything.
    The World::Pick method can be used to determine visibility between two points, if you don't care which object is hit and you just want to see if anything is in the way. If you set the closest parameter to true then the ray will pick the closest object that is hit.
    The distance between the pickinfo.position Vec3 and the ray origin is your distance.
  12. Josh's post in Menu Theme doesn't update. was marked as the answer   
    This will be fixed in an update today.
    I also found combo boxes had the same issue, and I fixed that too.
  13. Josh's post in Managing multiple resolutions was marked as the answer   
    You have two things going on:
    The size of the physical monitor, which usually corresponds to the resolution, i.e. a 1980x1080 monitor is bigger than a 1280x720 monitor. The size of the pixels. A 3920x2050 monitor will be about the same physical size as a 1920x1080 monitor, but its pixels will be twice as small. The first issue is fairly easy to deal with, just position your UI elements relative to a corner. If you have a display item that is 200x200 pixels, maybe it will be positioned at screenresolution - 220, for example. Another option is to create your UI at whatever default resolution you want, create all widgets, lock them to edges with Widget::SetLayout, and then call Interface::SetSize to slide everything into place.
    For the second problem, the display scale is the best indication of how big the pixels are. The best way to incorporate this into your UI is to first create your GUI with the assumption that everything is using 100% scaling, and then scale the UI using the display scale. If you use Widget::SetLayout to control which edges each widget is locked to, then everything will scale up perfectly.
    Additionally, whenever possible you should use Widget::SetIcon instead of Widget::SetPixmap, as icons are resolution-independent images loaded from SVG format.
  14. Josh's post in Setting vertex colors was marked as the answer   
    An update is available now. Make sure your sync your project to get the shader changes:
    https://www.ultraengine.com/learn/Mesh_SetVertexColor?lang=cpp
  15. Josh's post in How can I make a first person controller script for ultra engine? Can you help me? was marked as the answer   
    Here is an example that loads a leadwerks map and uses FPS controls:
    https://www.ultraengine.com/learn/Entity_SetInput?lang=cpp
  16. Josh's post in Material Slots was marked as the answer   
    Let's keep it simple. Here is a valid material file:
    { "material": { "color": [1.0, 1.0, 1.0, 1.0], "displacement": 0.1, "emission": [0.0, 0.0, 0.0], "metallic": 0.0, "roughness": 1.0, "shaderFamily": "Shaders/PBR.json", "shadow": true, "tessellation": false, "texture0": "./defaultmeshface.tex", "transparent": false } } For textures, a file in the same folder as the material file can use a relative path by adding ./ at the beginning of the path. Otherwise it will be considered a path relative to the project folder, i.e. "Materials/brick/brick01.dds".
  17. Josh's post in UAK project manager tab graphic issue was marked as the answer   
    The Ultra Engine client application replaces the UAK launcher.
  18. Josh's post in Leadwerks materials loading was marked as the answer   
    Okay, I removed that plane distance test and it appears to work fine. I am not sure why that was even in there. Maybe we will see a problem in the future that was supposed to solve, but I don't even know why it is in the code.
  19. Josh's post in Pixmap fails to load Leadwerks texture format. was marked as the answer   
    An update is now available.
  20. Josh's post in PBR Setup was marked as the answer   
    PBR is in use by default. The default roughness is 1.0 (maximum) and the default metalness is 0.0 (minimum).
    If a metal/roughness texture is in use it will be used to multiply the metal / roughness values. Metal/roughness textures are the same as in the glTF format, with the green channel storing roughness and the blue channel storing metallic:
    https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#metallic-roughness-material
    Finally, PBR lighting relies a lot on reflections. To get the correct look you must apply a diffuse and specular environment map to the world:
    https://www.ultraengine.com/learn/World_SetEnvironmentMap?lang=cpp
    The specular texture can also be used as the world background, or for a more abstract look you can use the diffuse texture as the background, as I did here:
    https://www.ultraengine.com/community/gallery/image/2548-asset-editor-wip/
    These textures can be generated from an HDRI image with the Khronos IBL sampler tool, which is included in the Tools folder. This outputs KTX2 files, which can be loaded with the KTX2 plugin, or converted to DDS format with this code:
    https://www.ultraengine.com/community/blogs/entry/2780-building-a-single-file-4k-hdr-skybox-with-bc6-compression/?tab=comments#comment-14747
    There are some ready-made environment maps in DDS format here you can also use:
    https://github.com/UltraEngine/Assets/tree/main/Materials/Environment
  21. Josh's post in Any way to extract or convert the TEX files from Leadwerks into PNG or other format? was marked as the answer   
    Yes, just call LoadPixmap and then use the Save() method to save in PNG. You'll need to load the FreeImage texture loader plugin for saving PNG files.
  22. Josh's post in Terrain Texture Problem was marked as the answer   
    The fix is up now. It's just a modified shader, so you will need to sync your project files to get it.
  23. Josh's post in Blank dark gray screen on Intel(R) Iris(R) Xe Graphics GPU was marked as the answer   
    Ah, okay. I will fix it so it emits the correct event indicating it failed to initialize.
  24. Josh's post in UI Label Widget text ignores newline character was marked as the answer   
    Here's an example of it working. I will have an update up shortly:
    #include "UltraEngine.h" #include "ComponentSystem.h" using namespace UltraEngine; #define UI3D int main(int argc, const char* argv[]) { //Get the display list auto displays = GetDisplays(); //Create a window auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a world auto world = CreateWorld(); world->SetAmbientLight(0); //Create a framebuffer #ifdef UI3D auto framebuffer = CreateFramebuffer(window); #endif //Create a camera auto camera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); #ifdef UI3D camera->SetPosition(float(framebuffer->size.x) * 0.5f,float(framebuffer->size.y) * 0.5f); #endif auto font = LoadFont("Fonts/arial.ttf"); auto sprite = CreateSprite(world, font, "AAAAAAAAAAAAA", 26, TEXT_CENTER | TEXT_MIDDLE, 400000.0f); auto ss = CreateSprite(world, 100, 100); ss->SetColor(1, 0, 0); #ifdef UI3D auto ui = CreateInterface(world, font, framebuffer->size); #else auto ui = CreateInterface(window); #endif auto label = CreateLabel("test 1\ntest line 2\ntest 3", 20, 20, 200, 200, ui->background, LABEL_BORDER | LABEL_MIDDLE | LABEL_RIGHT ); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { Sleep(10); #ifdef UI3D world->Update(); world->Render(framebuffer); #endif } return 0; }  
  25. Josh's post in Movement on terrain was marked as the answer   
    Here you go:
    //Create navmesh auto navmesh = CreateNavMesh(world, 512, 512, 512, 8, 8); //navmesh->SetDebugging(true);// visualize navmesh geometry navmesh->Build(); //Create player auto player = CreateCylinder(world, 0.4, 1.8); player->SetNavigationMode(false);// prevent player from triggering navmesh update player->SetColor(0, 0, 1); player->SetScale(10.f, 10.f, 10.f); auto agent = CreateNavAgent(navmesh); agent->SetPosition(0.f, 50.f, 0.5); player->Attach(agent);  
×
×
  • Create New...