Jump to content

Rick

Members
  • Posts

    7,936
  • Joined

  • Last visited

Everything posted by Rick

  1. I actually agree about the whole Lua thing. It's kind of a pain to work with because the editor isn't that great. That thing used to crash on me when I've press to many tabs in a row. I was trying to convince Josh to do the .NET route, but I don't think I was successful. With visual studio you can actually make your own standalone editor that is like visual studio but customized for your needs. He could distribute something like that just for the .NET scripting and it could be smaller and more specialized than just normal visual studio.
  2. Rick

    RakNet .NET

    RakNet can be thought as a level above System.Net.Sockets making life easier on the developer. It's an asynchronous UDP based system that handles staying connected and guaranteed packet delivery automatically for you. All you have to worry about is connecting, and sending data. As you may know UDP is kind of like the only way to fly when making networked video games, but by default it's unreliable and not always connected. RakNet takes care of all that for you so you can just focus on sending data for you game. It gives you the ease of using TCP with the benefits of UDP.
  3. Rick

    RakNet .NET

    So RakNet's new version has a .NET port. I took that, compiled it and then also compiled the generated source into it's own .NET DLL. So all you have to do is put RakNet.dll in the same dir as your exe, and then add a reference to RakNet.Net.dll in your project. It's built with .NET 4.0 in VS 2010. (just put this below dll in your exe dir. don't reference this one in your project) http://dl.dropbox.com/u/1293842/RakNet.Net/RakNet.dll (add a reference to the below dll) http://dl.dropbox.com/u/1293842/RakNet.Net/RakNet.Net.dll I also have in the works my own RPC (remote procedure call) system. Basically instead of sending messages back and forth between client/server and dealing with all of that, this system let's you "call" functions on the remote computer by name. It'll basically be as simple as deriving from a base class and giving the method you want exposed to the network a custom attribute.
  4. So you are doing an array of structs? http://mail.python.org/pipermail/tutor/2001-May/005957.html
  5. A good way, but maybe somewhat limited, might be to have a huge texture divided into multiple texture sizes. Each "zone" in this massive texture would be it's own texture of a given tree. Then via the shader you determine which zone to offset the texture by on the plane. That way 1 plane mesh can be used for all billboards, but you could offset each one to represent a range of different tree textures. Niops(?) on the boards here did this with an ambulance once when we were talking about instanced meshes and how we can get get different materials on them. The only issue with that was you are limited in how many tree images you can place on this one texture, although depending on the res I seem to remember it being a decently high number that might satisfy vegetation. This massive texture could be made dynamically by the editor/game if each tree placed also provided a texture of it in billboard form. I wonder what the performance on that would be since it's just 1 plane instance and 1 material. Maybe if I find time I'll play around with something like that.
  6. So this other method vs mesh batching is a huge speed booster? Is this propitiatory information or can you share the other method?
  7. Ah ok. Do you ever think you'll expose a way for us to batch things up so we can benefit from this ourselves using LE commands?
  8. What does this mean? I would think slapping a texture on 2 planes (crossing them to make it look like it has depth) would be cheaper than rendering a low resolution LOD mesh.
  9. You could put triggers on the stairs or however the characters get from floor to floor that tell the separate floor models what to do. So for example if you have a 5 story building and it has 1 entrance to the 1st floor, you can place 2 triggers at that door. I say 2 because you can check which trigger gets hit first to tell if they are walking into the building or leaving the building. If they are walking into the building that trigger says to hide the other floors above floor 1. Ect for each floor. This works if you just have the 1 character. With multiple characters and switching between them it might not work, unless you store off the last trigger each character hit so you can know which models to show/hide depending on that.
  10. I guess I'm not sure if 3DWS reads bitmaps. I've always used either DDS or jpg.
  11. This is sweet! Please keep at it, I would love to be able to export mat/shader files with this.
  12. Rick

    3D Pixels

    Then you need bodies, if you want LE to take care of all that for you. Pixels wouldn't have bodies unless you parented a body to them.
  13. I would say the networking, AI, and destructible buildings are all things you'd have to do yourself somehow in Leadwerks. There is 0 AI of any kind of LE. LE has networking code but it's not that advanced yet. It's still in very early stages. Destructible buildings is something you can have, but you have to come up with the implementation yourself as it's not "out of box" in LE. Huge maps aren't an issue. LE has some of the best graphics of any engine. Switching from RTS to FPS and back isn't an issue at the surface, but underneath you'd probably find that most RTS games have limited polygons in their models. Since the camera is so far up it's not really a big deal to do this, but when you get closer it becomes noticeable and things start to look ugly. LOD can help with this but I would think your FPS camera mode might still not be up to par with most FPS games because of the need to be in RTS mode also.
  14. WASD for sure, mouse to look around, and left mouse button for shooting always
  15. Sure enough, if I move Editor.exe and the UI folder to my games base directory it worked. Weird. Thank you Masterxilo, that was driving me nuts.
  16. Is there a bug in the script path setting that anyone knows of? I'm pointing the game path and script path to my projects folders. I then copied the Script folder from my leadwerks folder to this game folder, BUT when I modify class.lua in my project folder that change doesn't reflect when I open up Editor. If I change the class.lua in my LE folder then I see the change. So even though in the editor script path is set to C:\Documents and Settings\Games\My Documents\Visual Studio 2010\Projects\GameO\GameO\bin\Debug\Scripts, it's like it's not really reading that path for things like class.lua and instead it's reading my LE path for the Scripts folder.
  17. btw, I can't stand Win32 API programming. I need to shower now. In .NET this is all encapsulated in a class and it's very easy
  18. This code works, & I got it from the last post at http://cboard.cprogramming.com/windows-programming/77061-readdirectorychangesw.html. He talks about a special message loop. I'm not sure if the message loop is hidden from the users in BMax so not sure if it can be used in BMax. #define _WIN32_WINNT 0x0400 #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include <shlwapi.h> #if defined(_MSC_VER) #pragma comment(lib, "comctl32.lib") #pragma comment(lib, "user32.lib") #pragma comment(lib, "ole32.lib") #endif HINSTANCE g_hinst; typedef void (CALLBACK *FileChangeCallback)(LPTSTR, DWORD, LPARAM); typedef struct tagDIR_MONITOR { OVERLAPPED ol; HANDLE hDir; BYTE buffer[32 * 1024]; LPARAM lParam; DWORD notifyFilter; BOOL fStop; FileChangeCallback callback; } *HDIR_MONITOR; /* * Unpacks events and passes them to a user defined callback. */ VOID CALLBACK MonitorCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { TCHAR szFile[MAX_PATH]; PFILE_NOTIFY_INFORMATION pNotify; HDIR_MONITOR pMonitor = (HDIR_MONITOR) lpOverlapped; size_t offset = 0; BOOL RefreshMonitoring(HDIR_MONITOR pMonitor); if (dwErrorCode == ERROR_SUCCESS) { do { pNotify = (PFILE_NOTIFY_INFORMATION) &pMonitor->buffer[offset]; offset += pNotify->NextEntryOffset; # if defined(UNICODE) { lstrcpynW(szFile, pNotify->FileName, min(MAX_PATH, pNotify->FileNameLength / sizeof(WCHAR) + 1)); } # else { int count = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength / sizeof(WCHAR), szFile, MAX_PATH - 1, NULL, NULL); szFile[count] = TEXT('\0'); } # endif pMonitor->callback(szFile, pNotify->Action, pMonitor->lParam); } while (pNotify->NextEntryOffset != 0); } if (!pMonitor->fStop) { RefreshMonitoring(pMonitor); } } /* * Refreshes the directory monitoring. */ BOOL RefreshMonitoring(HDIR_MONITOR pMonitor) { return ReadDirectoryChangesW(pMonitor->hDir, pMonitor->buffer, sizeof(pMonitor->buffer), FALSE, pMonitor->notifyFilter, NULL, &pMonitor->ol, MonitorCallback); } /* * Stops monitoring a directory. */ void StopMonitoring(HDIR_MONITOR pMonitor) { if (pMonitor) { pMonitor->fStop = TRUE; CancelIo(pMonitor->hDir); if (!HasOverlappedIoCompleted(&pMonitor->ol)) { SleepEx(5, TRUE); } CloseHandle(pMonitor->ol.hEvent); CloseHandle(pMonitor->hDir); HeapFree(GetProcessHeap(), 0, pMonitor); } } /* * Starts monitoring a directory. */ HDIR_MONITOR StartMonitoring(LPCTSTR szDirectory, DWORD notifyFilter, FileChangeCallback callback) { HDIR_MONITOR pMonitor = (HDIR_MONITOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pMonitor)); pMonitor->hDir = CreateFile(szDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); if (pMonitor->hDir != INVALID_HANDLE_VALUE) { pMonitor->ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); pMonitor->notifyFilter = notifyFilter; pMonitor->callback = callback; if (RefreshMonitoring(pMonitor)) { return pMonitor; } else { CloseHandle(pMonitor->ol.hEvent); CloseHandle(pMonitor->hDir); } } HeapFree(GetProcessHeap(), 0, pMonitor); return NULL; } /* * Runs a message loop that allows APCs to be despatched. */ int RunAPCMessageLoop(void) { BOOL done = FALSE; MSG msg = { 0 }; while (!done) { /* Wait for either an APC or a message. */ while (WAIT_IO_COMPLETION == MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE)) /* Do nothing */; /* One or more messages have arrived. */ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { done = TRUE; break; } TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } void CALLBACK FileCallback(LPTSTR szFile, DWORD action, LPARAM lParam) { /* Shouldn't call MessageBox as it will block new notifications coming in. */ MessageBox(NULL, szFile, NULL, 0); } HDIR_MONITOR h; BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpcs) { h = StartMonitoring(TEXT("C:\\Documents and Settings\\Games\\My Documents"), FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_FILE_NAME, FileCallback); return TRUE; } void OnDestroy(HWND hwnd) { if (h) StopMonitoring(h); PostQuitMessage(0); } LRESULT CALLBACK WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) { switch (uiMsg) { HANDLE_MSG(hwnd, WM_CREATE, OnCreate); HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy); } return DefWindowProc(hwnd, uiMsg, wParam, lParam); } BOOL InitApp(void) { WNDCLASS wc = { 0 }; wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hinst; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("Scratch"); if (!RegisterClass(&wc)) return FALSE; return TRUE; } int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nShowCmd) { HWND hwnd; int result; g_hinst = hinst; if (!InitApp()) return 0; hwnd = CreateWindow( TEXT("Scratch"), /* Class Name */ TEXT("Scratch"), /* Title */ WS_OVERLAPPEDWINDOW, /* Style */ CW_USEDEFAULT, CW_USEDEFAULT, /* Position */ CW_USEDEFAULT, CW_USEDEFAULT, /* Size */ NULL, /* Parent */ NULL, /* No menu */ hinst, /* Instance */ 0); /* No special parameters */ ShowWindow(hwnd, nShowCmd); result = RunAPCMessageLoop(); return result; }
  19. So the function pauses? Like when you call it, it doesn't come back until a change happens? That doesn't sound very asynchronous to me. I would assume the call would return right away, and the function you provided as the callback gets called when something changes in the directory.
  20. Yeah, I think the community could benefit from that. Thanks Masterxilo!
  21. Rick

    C# SVN

    Sounds good. I'll stick with the old version and deal with the needed changes if they aren't going to be to radical.
  22. Dang. I guess I should have not just used their dds format and converted them myself. Thanks Lumooja! Would be cool is there was a, "If you have this it means this" kind of thing around materials and models.
  23. I bought a model, loaded it into UU3D, assigned the textures (the uv mapping was there but the textures weren't assigned), exported to gmf, created the mat files, and when I load the model into Model Viewer it animates fine BUT the model is completely black. The textures don't seem to be applied, but they must be found because he's animating fine and I know normally if the mat file was messed up the model would show as red and wouldn't animate. Here is an example of one of the 5 mat files needed. texture0="abstract::cyber_col.dds" texture1="abstract::cyber_normal.dds" shader="abstract::mesh_diffuse_bumpmap_skin.vert","abstract::mesh_diffuse_bumpmap_specular.frag" shadowshader="abstract::mesh_shadow_skin.vert" This is the infiltrator model from DexSoft http://www.dexsoft-games.com/models/infiltrator.html Thanks!
  24. Cool, thanks Klepto. The MouseZ() works great. I'm still not able to get the always on top world though. Not sure if I'm not doing something correctly. Here is the code I'm using. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Leadwerks; namespace EditorTest { public partial class Form1 : Form { private readonly Vector3 camrotation = new Vector3(); private float move; private float mx; private float my; private int mz; private int origx; private int origy; private float strafe; private bool rightMouseDown = false; private World topWorld; private Camera topCamera; private Mesh xAxis; public Form1() { InitializeComponent(); } // it all starts here private void RenderContext_Init(object sender, EventArgs e) { RenderContext.InitFramework(false); RenderContext.RefreshRate = 60; RenderContext.Start(); Leadwerks.Framework.StatisticMode = StatisticMode.Detailed; Leadwerks.Framework.Layers.Main.Camera.Position = new Vector3(0, 0, -4); topWorld = new World(); Leadwerks.World.Current = topWorld; topCamera = new Camera(); topCamera.ClearMode = CameraClearMode.Depth; // load model xAxis = Mesh.Load("abstract::x_red.gmf"); xAxis.Position = new Vector3(0, 0, 0); Leadwerks.World.Current = Leadwerks.Framework.Layers.Main.World; Light light = Light.CreateDirectional(); light.Position = new Vector3(0, 1, 0); Mesh cube = Mesh.CreateCube(); cube.Position = new Vector3(0, 0, 0); } private void RenderContext_Render(object sender, EventArgs e) { } private void RenderContext_AfterRender(object sender, EventArgs e) { Drawing.Blend = BlendType.Alpha; Drawing.Text(mx + ";" + my, 0, 250); Drawing.Text(RenderContext.MouseZ().ToString(), 0, 300); Drawing.Blend = BlendType.None; } Leadwerks.Buffer gbuffer; private void RenderContext_PreRender(object sender, EventArgs e) { gbuffer = Leadwerks.Buffer.Current; if(RenderContext.MouseHit(MouseButtons.Right) == 1) { // save off the orignal location of the mouse so we can put it back here when done origx = RenderContext.MouseX(); origy = RenderContext.MouseY(); // bug: seems the mouse is getting visible after the first frame so we need to do this here and in MouseDown below Leadwerks.Mouse.Hide(); Cursor.Hide(); RenderContext.MoveMouse(50, 50); } if (RenderContext.MouseDown(MouseButtons.Right)) { Leadwerks.Mouse.Hide(); Cursor.Hide(); // camera look mx = Maths.Curve(RenderContext.MouseX() - 50, mx, 1); my = Maths.Curve(RenderContext.MouseY() - 50, my, 1); // move the camera back to our preset location for camera movement RenderContext.MoveMouse(50, 50); // add the delta to the rotation camrotation.X = camrotation.X + my / 5.0f; camrotation.Y = camrotation.Y - mx / 5.0f; Leadwerks.Framework.Layers.Main.Camera.Rotation = camrotation; rightMouseDown = true; } else if ((!RenderContext.MouseDown(MouseButtons.Right)) && rightMouseDown) { rightMouseDown = false; // move the mouse back to where it was RenderContext.MoveMouse(origx, origy); Leadwerks.Mouse.Show(); Cursor.Show(); } move = Maths.Curve( (float) (Convert.ToDouble(RenderContext.KeyDown(Key.W)) - Convert.ToDouble(RenderContext.KeyDown(Key.S))), move, 1); int scroll = RenderContext.MouseZ() - mz; mz = RenderContext.MouseZ(); move += scroll; strafe = Maths.Curve( (float) (Convert.ToDouble(RenderContext.KeyDown(Key.D)) - Convert.ToDouble(RenderContext.KeyDown(Key.A))), strafe, 1); Leadwerks.Framework.Layers.Main.Camera.Move(new Vector3(strafe / 10.0f, 0, move / 10.0f)); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { Engine.Terminate(); } private void Form1_Load(object sender, EventArgs e) { } private void RenderContext_AfterFrameworkRender(object sender, EventArgs e) { Leadwerks.World.Current = topWorld; topCamera.Matrix = Leadwerks.Framework.Layers.Main.Camera.Matrix; Leadwerks.Buffer.Clear(BufferType.Depth); Leadwerks.World.Render(); Leadwerks.World.Current = Framework.Layers.Main.World; } } }
×
×
  • Create New...